pip从setup.py安装tox的tox依赖项

ite*_*em4 22 python pip setuptools easy-install tox

我制作了我的项目,setuptools我想用它进行测试tox.我在变量中列出了依赖项并添加到setup()参数(tests_requireextras_require)中.我的项目需要安装tests_require测试中列出的所有依赖项,但pip install不安装它们.

我尝试了这个,但它不起作用:

install_command = pip install {opts} {packages}[tests]
Run Code Online (Sandbox Code Playgroud)

如何安装测试依赖项而无需管理多个依赖项列表(即在两者test_requirements.txttests_require变量中列出所有依赖项)?

che*_*hes 39

我通过略微滥用额外要求来实现这一目标.你几乎在尝试额外的语法,只是那些tests_requiredeps不会自动提供.

setup.py这样的:

from setuptools import setup

test_deps = [
    'coverage',
    'pytest',
]
extras = {
    'test': test_deps,
}

setup(
    # Other metadata...
    tests_require=test_deps,
    extras_require=extras,
)
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用extras语法(例如,从项目根目录)获取安装的测试依赖项:

$ pip install .[test]
Run Code Online (Sandbox Code Playgroud)

为Tox提供相同的语法tox.ini,无需调整默认值install_command:

[testenv]
commands = {posargs:pytest}
deps = .[test]
Run Code Online (Sandbox Code Playgroud)

现在,您不需要在两个位置维护依赖关系列表,并且它们表示它们应该用于已发布包的位置:在打包元数据而不是requirements.txt文件中.

看起来这个小小的额外黑客并不是那么罕见.


Guy*_*emi 14

解决方案

Tox 2.6 引入了extras选项。这将从extras它刚刚构建的 sdist安装,仅适用于该 sdist 并且当时它正在执行正常的 sdist 安装。

setup.py 应如下所示:

setuptools.setup(
    ...
    extras_require={
        'tests': ['pytest>=3.7.0', 'more_packages'],
    },
    ...
 )
Run Code Online (Sandbox Code Playgroud)

tox.ini 应如下所示:

[testenv]
...
extras = tests
...
Run Code Online (Sandbox Code Playgroud)

顾虑

其他方法可能会得到类似的结果,但会引入不必要的风险并限制其他功能的有用性:

deps =.[tests]有点像黑客。该字段用于环境需要的包。如果 setup.py install_requires 引用了您开发的另一个包,您可以使用它来获取它的预发布版本。如图所示,它会从你的工作目录(无论处于什么状态!)安装你的整个包,只是为了获取tests. install_command接下来将运行,安装新创建的 sdist。简而言之,sdist 的问题可能会被掩盖,因为您已经从工作副本安装了。

编辑install_command是矫枉过正。它将覆盖通过deps. (同样,也许您用它来安装特定版本的软件包)。

tests_requirepython setup.py test运行时使用。Tox建议避免,python setup.py test以便您可以tests_require一起忽略所有内容。


cho*_*own 4

您可以做的是拥有一个文件(称为test_requirements.txt)并列出测试依赖项,如下所示:

dnspython==1.12.0
easydev==0.8.3
enum34==1.0.4
fabric==1.10.1
...
Run Code Online (Sandbox Code Playgroud)

然后,在 中setup.py,解析文件内容并将其存储在列表中,并将该列表传递给setup

tests_require = [line.strip() for line in 
                 open('test_requirements.txt')
                 if line.strip() and not line.strip().startswith('--')]

setuptools.setup(
    ...
    tests_require=tests_require,
    ...
)
Run Code Online (Sandbox Code Playgroud)