如何编写setup.py以包含Git存储库作为依赖项


100

我正在尝试setup.py为我的包裹写东西。我的软件包需要指定对另一个Git存储库的依赖。

这是我到目前为止所拥有的:

from setuptools import setup, find_packages

setup(
    name='abc',
    packages=find_packages(),
    url='https://github.abc.com/abc/myabc',
    description='This is a description for abc',
    long_description=open('README.md').read(),
    install_requires=[
        "requests==2.7.0",
        "SomePrivateLib>=0.1.0",
        ],
    dependency_links = [
     "git+git://github.abc.com/abc/SomePrivateLib.git#egg=SomePrivateLib",
    ],
    include_package_data=True,
)

当我跑步时:

pip install -e https://github.abc.com/abc/myabc.git#egg=analyse

我懂了

找不到满足SomePrivateLib> = 0.1.0要求的版本(来自分析)(来自版本:)找不到SomePrivateLib> = 0.1.0(来自分析)的匹配分布

我究竟做错了什么?


请注意,setup.py和pip是完全不同的系统。我遇到的一个问题是,我能够将其用于pip,但不能用于setup.py。
bcattle

Answers:


51

您可以在此处找到正确的方法。

dependency_links=['http://github.com/user/repo/tarball/master#egg=package-1.0']

关键不是提供指向Git存储库的链接,而是提供指向tarball的链接。如果您/tarball/master像上面那样添加,GitHub会为您创建master分支的压缩包。


17
貌似这个方法每不赞成github.com/pypa/pip/issues/3939
介子

3
该方法对私有存储库也无济于事,因为无法进行身份验证。
tedivm

3
我确实设法使其正常运行,并添加了另一个答案。
tedivm

1
/tarball/master方法不适用于gitlab
Martin Thoma

5
不推荐使用。正确的答案是使用Pep508,由@Dick Fox下方解答
SwimBikeRun

117

在通过上面的评论中@muon链接的pip问题3939PEP-508规范后,我发现成功地通过setup.py使用以下规范模式来安装我的私有repo依赖项install_requires(不再dependency_links):

install_requires = [
  'some-pkg @ git+ssh://git@github.com/someorgname/pkg-repo-name@v1.1#egg=some-pkg',
]

@v1.1指示在GitHub上创建的发布标志,并可以用一个分支,提交,或不同类型的标签来代替。


注意:此工作正常本地/私人包,但是,你不能释放一个包的PyPI使用此语法在setup.py
布赖恩

7
@Brian您能否提供官方声明的链接?
大象

12
请注意,git+https://github.com如果您不想使用SSH,可以这样做。
multithr3at3d

2
那么进行--upgrade的正确方法是什么?即使我指定了标记版本,升级也将忽略较新的标记版本
Piacenti

1
@Elephant不是超级官方,但这些至少是PyPA实际成员对pip GitHub项目的评论:github.com/pypa/pip/issues/4187#issuecomment-415667805以及进一步的解释:github.com/pypa/pip / issues / 4187#issuecomment-415067034
Dominick Pastore

21

以下答案不适用于Pip 19+


不幸的是,其他答案不适用于私有存储库,这是最常见的用例之一。我最终的确使用了如下setup.py文件:

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_organization/ExampleRepo.git#egg=ExampleRepo-0.1'
    ]
)

较新版本的pip消除了使用“ 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_organization/ExampleRepo.git#egg=ExampleRepo-0.1'
    ]
)

1
您能否详细说明-0.1您的方法代表什么?您是从git发行版还是从setup.py描述中获取版本号?
Peteris

2
在setup.py文件中-如果要使用特定的分支或标记,则格式设置会有所不同。
tedivm

“不幸的是,其他答案不适用于私有存储库”这不再是正确的。Fox的答案确实可以在不需要私有存储库的情况下使用dependency_links(已弃用
Keto

谢谢@ Keto!我不知道您的修改为何被拒绝,但mods为何被拒绝,但我继续进行并覆盖了该拒绝,以将弃用通知添加到答案中。
tedivm

3

一个更一般的答案:要从requirements.txt文件中获取信息,请执行以下操作:

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+'):
        if EGG_MARK in line:
            package_name = line[line.find(EGG_MARK) + len(EGG_MARK):]
            required.append(package_name)
            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,
)

1

实际上,如果您希望递归安装软件包(YourCurrentPackage包含SomePrivateLib),例如,当您希望将YourCurrentPackage包含到另一个软件包中(例如OuterPackage→YourCurrentPackage→SomePrivateLib)时,您将同时需要:

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"
]

并确保您使用版本号创建了一个标签。

同样,如果您的Git项目是私有的,并且您想将其安装在容器中(例如DockerGitLab运行器),那么您将需要对存储库的授权访问。请考虑将Git + HTTPS与访问令牌一起使用(例如在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"
    ]
)

0

我在GitLab中成功使用了这三个选项。我正在使用GitLab版本11。

选项1-未指定令牌。Shell将提示输入用户名/密码。

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"
    ]
)

选项2-指定了用户访问令牌。通过转到GitLab→帐户右上方→设置→访问令牌生成的令牌。创建具有read_repository权限的令牌。

例:

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"
    ]
)

选项3-指定存储库级别的令牌。通过转到存储库→设置→存储库→部署令牌生成的令牌。在这里,创建一个具有read_repository权限的令牌。

例:

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"
    ]
)

在这三者中,我都可以简单地做:“ SomePrivateLib @ git + https://gitlab.server.com/abc/SomePrivateLib.git”,最后没有#egg标记。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.