Как написать setup.py для включения репозитория git в качестве зависимости

95

Пытаюсь написать 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

Ответы:

50

Вы можете найти правильный способ сделать это здесь .

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

Ключ не в том, чтобы давать ссылку на репозиторий git, а в ссылке на tarball. Github создаст для вас архив главной ветки, если вы добавите, /tarball/masterкак показано выше.

чел
источник
17
похоже, что этот метод устарел на github.com/pypa/pip/issues/3939
мюон
2
Этот метод также бесполезен для частных репозиториев, поскольку нет возможности аутентифицироваться.
tedivm
3
Мне удалось заставить его работать и добавил еще один ответ.
tedivm
1
/tarball/masterМетод не работает для gitlab
Martin Thoma
3
Не рекомендуется. Правильный ответ - использовать Pep508, ответ от @Dick Fox ниже
SwimBikeRun
104

После того, как копаться в проблеме 3939 пипа связан @muon в комментариях выше , а затем спецификаций PEP-508 , я нашел успех получаю мою зависимость частного хранилища , чтобы установить через setup.pyне используя эту спецификацию шаблона в 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 Не могли бы вы дать ссылку на официальное заявление?
Elephant
11
Обратите внимание, что вы можете это сделать, git+https://github.comесли не хотите использовать SSH.
multithr3at3d
2
Итак, каков правильный подход к выполнению --upgrade? Несмотря на то, что я указываю версию тега, обновление просто игнорирует более новые версии тегов
Пьяченти
1
@Elephant Не супер-официальный, но это, по крайней мере, комментарии к проекту pip GitHub от реальных участников PyPA: github.com/pypa/pip/issues/4187#issuecomment-415667805 и дальнейшее объяснение: github.com/pypa/pip / issues / 4187 # issuecomment-415067034
Доминик Пасторе
19

Следующий ответ устарел для 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описания?
Петерис
2
Из файла setup.py - если вы хотите использовать определенную ветку или тег, вы форматируете вещи немного иначе.
tedivm
«К сожалению, другой ответ не работает с частными репозиториями». Это больше не верно . Ответ Fox действительно работает с частным репо без необходимости dependency_links(что устарело )
Кето
Спасибо @Keto! Я не знаю, почему ваше редактирование было отклонено, кроме модов, но я пошел дальше и отменил этот отказ, чтобы добавить уведомление об устаревании к ответу.
tedivm
3

Более общий ответ, чтобы получить информацию из файла Requeriments.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 является частным и вы хотите установить его внутри контейнера, например, Docker или GitLab runner, вам потребуется авторизованный доступ к вашему репо. Пожалуйста, подумайте об использовании 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

Мне удалось использовать эти 3 варианта в gitlab. Я использую версию gitlab 11.

вариант 1 - токен не указан. оболочка запросит имя пользователя / пароль.

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 в конце.

ErikW
источник