防止setup.py test / pytest安装额外的依赖项

时间:2017-10-17 17:38:38

标签: python pytest setuptools

在我的CI中,我有一个 build 步骤,该步骤使用pip并使用私有索引等正确设置。

然后我有 test 步骤,执行python setup.py test。 在此特定情况下,testpytest的别名。

Setuptools和PIP以不同方式解析包依赖关系,这导致 test 步骤尝试重新安装某些包。我想阻止这一点。有没有办法使用Setuptools配置(首选)或使用PyTest配置?

更新

通过流行的需求回购来举例说明我所拥有的问题 https://github.com/vartec/example_repo_setuptools_issue

4 个答案:

答案 0 :(得分:5)

为什么不像这样覆盖测试命令:

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,
    },
)

答案 1 :(得分:5)

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://git@github.com/vartec/example_repo_setuptools_issue_submodule.git#egg=example_submodule-0.1.0',
    ]
)

看看这是否确实是您所寻找的,如果没有,请提供您的反馈。

修改-1

如果你真的不关心install_requires test那么你就可以了

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

答案 2 :(得分: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 integration manual)。

诀窍是如果setuptools可以在当前环境中找到测试依赖项(virtualenv,pyenv,system python,还有其他),它将不会将它们安装为egg,并且只使用已安装的版本

实际上,在这种情况下你甚至不需要声明tests_require=,因为假定库被安装到virtualenv中。如果不是,测试命令就会失败。

同样,您可以pip install .[docs]使用当前virtualenv中的sphinx-build ...命令构建文档。

请注意,无论您添加多少内容,都会始终安装install_requires。所以app / lib本身将始终完全正常,可导入且内省。

希望这是一个问题(如果我理解正确的话)。

答案 3 :(得分:2)

您可以使用requirements.txt文件指定的依赖项不在PyPI中,而不是dependency_linkssetup方法的setup.py参数。

requirements.txt:

-e git+ssh://git@github.com/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,
    },
)

我将您的示例repo分叉并进行了一些更改 https://github.com/gentcys/example_repo_setuptools_issue.git
我创建了一个子模块仓库 https://github.com/gentcys/example_repo_setuptools_issue_submodule.git