55๐
Note: this answer is now outdated. Have a look at this answer for up-to-date instructions: https://stackoverflow.com/a/54701434/212774
You can find the right way to do it here.
dependency_links=['http://github.com/user/repo/tarball/master#egg=package-1.0']
The key is not to give a link to a Git repository, but a link to a tarball. GitHub creates a tarball of the master branch for you if you append /tarball/master
as shown above.
232๐
Note: this answer is now outdated. Have a look at this answer for up-to-date instructions: https://stackoverflow.com/a/54701434/212774
After digging through the pip issue 3939 linked by @muon in the comments above and then the PEP-508 specification, I found success getting my private repo dependency to install via setup.py
using this specification pattern in install_requires
(no more dependency_links
):
install_requires = [
'some-pkg @ git+ssh://git@github.com/someorgname/pkg-repo-name@v1.1#egg=some-pkg',
]
The @v1.1
indicates the release tag created on github and could be replaced with a branch, commit, or different type of tag.
- [Django]-Django.db.utils.ProgrammingError: relation "bot_trade" does not exist
- [Django]-Passing variable urlname to url tag in django template
- [Django]-CSS styling in Django forms
86๐
This answer has been updated as Python has evolved over the years.
Scroll to the bottom for the most current answer, or read through to see how this has evolved.
Unfortunately the accepted answer does not work with private repositories, which is one of the most common use cases for this.
2019 โ dependency_links (deprecated as of pip v19+)
I eventually did get it working with a setup.py
file that looks like this method:
from setuptools import setup, find_packages
setup(
name = 'MyProject',
version = '0.1.0',
url = '',
description = '',
packages = find_packages(),
install_requires = [
# Github Private Repository - needs entry in `dependency_links`
'ExampleRepo'
],
dependency_links=[
# Make sure to include the `#egg` portion so the `install_requires` recognizes the package
'git+ssh://git@github.com/example_org/ExampleRepo.git#egg=ExampleRepo-0.1'
]
)
Newer versions of pip make this even easier by removing the need to use "dependency_links"-
from setuptools import setup, find_packages
setup(
name = 'MyProject',
version = '0.1.0',
url = '',
description = '',
packages = find_packages(),
install_requires = [
# Github Private Repository
'ExampleRepo @ git+ssh://git@github.com/example_org/ExampleRepo.git#egg=ExampleRepo-0.1'
]
)
However, with the very latest pip youโll run into issues with the EGG format handler. This is because while the egg is ignored pip is now doing direct URL matching and will consider two URLs, one with the egg fragment and the other without, to be completely different versions even if they point to the same package. As such itโs best to leave any egg fragments off.
2021 June โ setup.py
So, the best way (current to June 2021) to add a dependency from Github to your setup.py that will work with public and private repositories:
from setuptools import setup, find_packages
setup(
name = 'MyProject',
version = '0.1.0',
url = '',
description = '',
packages = find_packages(),
install_requires = [
# Github Private Repository
'ExampleRepo @ git+ssh://git@github.com/example_org/ExampleRepo.git'
]
)
2022 February โ setup.cfg
Apparently setup.py is being deprecated (although my guess is itโll be around for awhile) and setup.cfg is the new thing.
[metadata]
name = MyProject
version = 0.1.1
[options]
packages = :find
install_requires =
ExampleRepo @ git+ssh://git@github.com/example_org/ExampleRepo.git
2022 June โ pyproject.toml
setup.cfg is already "pre" deprecated. as setuptools now has experimental support for pyproject.toml files.
This is the future, but since this is still experimental it should not be used in real projects for now. Even though setup.cfg
is on its way out you should use it for a declarative format, otherwise setup.py is still the way to go. This answer will be updated when setuptools has stabilized their support of the new standard.
2023 January โ pyproject.toml
It is now possible to define all of your dependencies in pyproject.toml
. Other options such as setup.cfg still work.
[build-system]
requires = ["setuptools", "setuptools-scm"]
build-backend = "setuptools.build_meta"
[project]
dependencies = [
'ExampleRepo @ git+ssh://git@github.com/example_org/ExampleRepo.git',
]
[project.optional-dependencies]
dev = ['ExtraExample @ git+ssh://git@github.com/example_org/ExtraExample.git']
- [Django]-Adding a user to a group in django
- [Django]-What's the best way to extend the User model in Django?
- [Django]-Django Rest Framework โ Updating a foreign key
8๐
A more general answer: To get the information from the requirements.txt file I do:
from setuptools import setup, find_packages
from os import path
loc = path.abspath(path.dirname(__file__))
with open(loc + '/requirements.txt') as f:
requirements = f.read().splitlines()
required = []
dependency_links = []
# Do not add to required lines pointing to Git repositories
EGG_MARK = '#egg='
for line in requirements:
if line.startswith('-e git:') or line.startswith('-e git+') or \
line.startswith('git:') or line.startswith('git+'):
line = line.lstrip('-e ') # in case that is using "-e"
if EGG_MARK in line:
package_name = line[line.find(EGG_MARK) + len(EGG_MARK):]
repository = line[:line.find(EGG_MARK)]
required.append('%s @ %s' % (package_name, repository))
dependency_links.append(line)
else:
print('Dependency to a git repository should have the format:')
print('git+ssh://git@github.com/xxxxx/xxxxxx#egg=package_name')
else:
required.append(line)
setup(
name='myproject', # Required
version='0.0.1', # Required
description='Description here....', # Required
packages=find_packages(), # Required
install_requires=required,
dependency_links=dependency_links,
)
- [Django]-Django rest framework: query parameters in detail_route
- [Django]-Django admin file upload with current model id
- [Django]-How to view corresponding SQL query of the Django ORM's queryset?
6๐
Actually if you like to make your packages installable recursively (YourCurrentPackage includes your SomePrivateLib), e.g. when you want to include YourCurrentPackage into another one (like OuterPackage โ YourCurrentPackage โ SomePrivateLib) youโll need both:
install_requires=[
...,
"SomePrivateLib @ git+ssh://github.abc.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
],
dependency_links = [
"git+ssh://github.abc.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
And make sure you have a tag created with your version number.
Also if your Git project is private and you like to install it inside the container, e.g., a Docker or GitLab runner, you will need authorized access to your repository. Please consider to use Git + HTTPS with access tokens (like on GitLab: https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html):
import os
from setuptools import setup
TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')
setup(
....
install_requires=[
...,
f"SomePrivateLib @ git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
],
dependency_links = [
f"git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)
Updated:
You have to put #egg=SomePrivateLib at the end of dependency line if you like to have this dependency in requirements.txt file. Otherwise pip install -r requirements.txt wonโt work for you and you wil get something like:
ERROR: Could not detect requirement name for
โgit+https://gitlab-ci-token:gitlabtokenvalue@gitlab.server.com/abc/SomePrivateLib.git@0.1.0โ,
please specify one with #egg=your_package_name
If you use reuirements.txt, this part is resposible for name of dependencyโs folder that would be created inside python_home_dir/src and for name of egg-link in site-packages/
You can use a environment variable in your requirements.txt to store your dependencyโs token value safe in your repo:
Example row in requrements.txt file for this case:
....
-e git+https://gitlab-ci-token:${EXPORTED_VAR_WITH_TOKEN}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib
....
- [Django]-Django's Double Underscore
- [Django]-How to convert JSON data into a Python object?
- [Django]-Django-celery: No result backend configured
3๐
I was successful with these three options in GitLab. I am using version 11 of GitLab.
Option 1 โ no token specified. The shell will prompt for username/password.
from setuptools import setup
TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')
setup(
install_requires=[
"SomePrivateLib @ git+https://gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)
Option 2 โ user access token specified. The token generated by going to GitLab โ account top right โ settings โ access tokens. Create the token with read_repository rights.
Example:
import os
from setuptools import setup
TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')
setup(
install_requires=[
f"SomePrivateLib @ git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)
Option 3 โ repository-level token specified. The token generated by going to the repository โ settings โ repository โ deploy tokens. From here, create a token with read_repository rights.
Example:
import os
from setuptools import setup
TOKEN_USER = os.getenv('EXPORTED_TOKEN_USER')
TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')
setup(
install_requires=[
f"SomePrivateLib @ git+https://{TOKEN_USER}:{TOKEN_VALUE}@gitlab.server.com/abc/SomePrivateLib.git@0.1.0#egg=SomePrivateLib"
]
)
In all three, I was able to do simply: "SomePrivateLib @ git+https://gitlab.server.com/abc/SomePrivateLib.git" without the #egg marking at the end.
- [Django]-Passing STATIC_URL to file javascript with django
- [Django]-How to implement followers/following in Django
- [Django]-Django storages aws s3 delete file from model record
0๐
This solution works for me when I run python setup.py install:
setuptools.setup(
...,
install_requires=[
'numpy',
'pandas',
'my_private_pkg'
],
dependency_links=["git+https://github.com/[username]/[my_private_pkg].git@main#egg=my_private_pkg"],
...
)
- [Django]-Dynamic choices field in Django Models
- [Django]-Why doesn't django's model.save() call full_clean()?
- [Django]-Django staticfiles not found on Heroku (with whitenoise)