在我的CI中,我有一个 build 步骤,该步骤使用pip
并使用私有索引等正确设置。
然后我有 test 步骤,执行python setup.py test
。
在此特定情况下,test
是pytest
的别名。
Setuptools和PIP以不同方式解析包依赖关系,这导致 test 步骤尝试重新安装某些包。我想阻止这一点。有没有办法使用Setuptools配置(首选)或使用PyTest配置?
更新
通过流行的需求回购来举例说明我所拥有的问题 https://github.com/vartec/example_repo_setuptools_issue
答案 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_links
中setup
方法的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