Предотвратите установку setup.py test/pytest от установки дополнительных зависимостей

В моем CI у меня есть шаг сборки, который использует pip и правильно настроен с использованием частных индексов и т.д.

Затем у меня есть тестовый шаг, который выполняет python setup.py test. В этом конкретном случае test является псевдонимом pytest.

Setuptools и PIP разрешают зависимости пакетов пакета, что приводит к шагу проверки, пытающемуся переустановить некоторые из пакетов. Я хотел бы предотвратить это. Есть ли способ сделать это либо с настройкой Setuptools (предпочтительнее), либо с настройкой PyTest?

Update:

По многочисленным просьбам РЕПО продемонстрировать проблему, с которой я сталкиваюсь https://github.com/vartec/example_repo_setuptools_issue

Ответ 1

Почему бы не переопределить тестовую команду следующим образом:

from setuptools import setup
from setuptools.command.test import test


class CustomTest(test):
    def run(self):
        self.distribution.install_requires = []
        super().run()


setup(
    name = "test",
    version = "0.0.1",
    install_requires=['non-existing-package'],
    cmdclass={
        "test": CustomTest,
    },
)

Ответ 2

Небольшая модификация в setup.py, специально применимая для теста, должна выполнять работу

import sys

import pkg_resources
from setuptools import setup, find_packages
from setuptools.dist import Distribution

install_requires = [
    'redis~=2.8.0',
    'example_submodule',
]

tests_require = [
    'pytest',
]

original_function = None

if sys.argv[1] == "test":
    working_set = pkg_resources.WorkingSet()
    new_reqs = set()
    for req in install_requires:
        try:
            sets = working_set.resolve(pkg_resources.parse_requirements(req))
        except Exception as ex:
            new_reqs.add(req)
    install_requires = new_reqs


setup(
    name='example_module',
    version='0.1.0',
    packages=find_packages(),
    install_requires=install_requires,
    tests_require=tests_require,
    setup_requires=['pytest-runner'],
    extras_require={
        'testing': tests_require,
    },
    dependency_links=[
        'git+ssh://[email protected]/vartec/example_repo_setuptools_issue_submodule.git#egg=example_submodule-0.1.0',
    ]
)

Посмотрите, действительно ли это то, что вы искали, а затем не предоставляете свои отзывы.

Edit-1

Если вы действительно не заботитесь о install_requires в случае test, тогда вы можете просто сделать

if sys.argv[1] == "test":
   install_requires = []

Ответ 3

Итак, я понимаю, проблема в том, что setuptools устанавливает внутренние зависимости в локальную папку (.eggs если я правильно помню), а не в обычный virtualenv, который вы используете.

И вам не нравится, как это делает setuptools. Я тоже, особенно когда мне нужен локальный сервер DevPI, который будет использоваться (setuptools игнорирует это). Поэтому я делаю так:

setup(
    ...
    install_requires=['monotonic'],  # just for example
    extras_require={
        'test': ['pytest', 'pytest-timeout'],
        'docs': ['sphinx', 'alabaster'],
    },
)

Когда вам нужно протестировать, предполагая, что вы каким-либо образом создаете и устанавливаете virtualenv:

pip install -e .[test]

Здесь . - текущий каталог. -e средний редактируемый режим (но может быть опущен). [test] является setuptools "extra" . Вы можете объявить несколько "дополнительных" и установить их как pip install mylib[ext1,ext2], если это необходимо.

Затем вы можете запускать тесты в любом случае:

pytest
python setup.py test

Последний вариант только в том случае, если команда test уже настроена для запуска pytest (см. руководство по интеграции pytest).

Фокус в том, что если setuptools может найти тестовые зависимости в текущей среде (virtualenv, pyenv, system python, что-то еще), он не будет устанавливать их как яйца и будет использовать только установленные версии.

На самом деле вам даже не нужно объявлять tests_require= в этом случае, поскольку предполагается, что библиотеки установлены в virtualenv. Если бы они не были, тестовая команда просто терпит неудачу.

Аналогично, вы можете pip install .[docs] и построить свои документы с помощью команды sphinx-build ... из текущего virtualenv.

Обратите внимание, что install_requires устанавливаются всегда, независимо от добавленных дополнений. Таким образом, приложение /lib будет всегда полностью функциональным, импортируемым и интроспективным.

Надеюсь, это был вопрос (если я правильно понял).

Ответ 4

Обновление:
Прежде чем предоставить пример репо, я догадался, что вы ошиблись в своей идее. Поэтому я удалил свой ответ и переписал ответ.

Новый ответ:
Вы можете использовать requirements.txt указанные файлы зависимостей не в PyPI вместо параметра dependency_links метода setup в setup.py.

requirements.txt:

-e git+ssh://[email protected]/gentcys/example_repo_setuptools_issue_submodule.git#egg=example_submodule-0.1.0

-e .[testing]

setup.py:

from setuptools import setup, find_packages

install_requires = [
    'redis~=2.10.0',
    'example_submodule',
]

tests_require = [
    'pytest',
]


setup(
    name='example_module',
    version='0.1.0',
    packages=find_packages(),
    install_requires=install_requires,
    tests_require=tests_require,
    setup_requires=['pytest-runner'],
    extras_require={
        'testing': tests_require,
    },
)

Я развернул ваш пример репо и внес некоторые изменения https://github.com/gentcys/example_repo_setuptools_issue.git
И я создаю репозиторий подмодулей https://github.com/gentcys/example_repo_setuptools_issue_submodule.git