阻止 setup.py test / pytest 安装额外的依赖项
Prevent setup.py test / pytest from installing extra dependencies
在我的 CI 中,我有一个 build 步骤,它使用 pip
并使用私有索引等正确设置
然后我有 test 步骤,它执行 python setup.py test
。
在这种特殊情况下 test
是 pytest
.
的别名
Setuptools 和 PIP 以不同方式解析包依赖性,这导致 test 步骤尝试重新安装某些包。我想阻止这种情况。有没有办法通过 Setuptools 配置(最好)或 PyTest 配置来做到这一点?
更新:
通过热门需求回购来举例说明我遇到的问题
https://github.com/vartec/example_repo_setuptools_issue
为什么不覆盖这样的测试命令:
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,
},
)
因此,据我了解,问题是 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"。您可以声明多个 "extras",并在需要时将它们安装为 pip install mylib[ext1,ext2]
。
然后您可以 运行 两种方式进行测试:
pytest
python setup.py test
后一个仅在 test
命令已经配置为 运行 pytest(参见 pytest integration manual)时才会出现。
诀窍是,如果setuptools
可以在当前环境中找到测试依赖(virtualenv,pyenv,系统python,等等),它不会像鸡蛋一样安装它们,并且只会使用已安装的版本。
实际上,在这种情况下您甚至不需要声明 tests_require=
,因为假定库已安装到 virtualenv 中。如果不是,测试命令将失败。
同样,您可以 pip install .[docs]
,并使用当前 virtualenv 中的 sphinx-build ...
命令构建您的文档。
请注意 install_requires
始终会安装,无论您是否添加了附加功能。因此 app/lib 本身将始终具有完整的功能、可导入和自省。
希望这就是问题所在(如果我理解正确的话)。
您可以使用 requirements.txt
文件指定的依赖项不在 PyPI 中,而不是 setup.py
.
中 setup
方法的 dependency_links
参数
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,
},
)
我分叉了你的示例回购并做了一些更改
https://github.com/gentcys/example_repo_setuptools_issue.git
我创建了一个子模块回购
https://github.com/gentcys/example_repo_setuptools_issue_submodule.git
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
如果你真的不关心 test
情况下的 install_requires
那么你可以只做
if sys.argv[1] == "test":
install_requires = []
在我的 CI 中,我有一个 build 步骤,它使用 pip
并使用私有索引等正确设置
然后我有 test 步骤,它执行 python setup.py test
。
在这种特殊情况下 test
是 pytest
.
Setuptools 和 PIP 以不同方式解析包依赖性,这导致 test 步骤尝试重新安装某些包。我想阻止这种情况。有没有办法通过 Setuptools 配置(最好)或 PyTest 配置来做到这一点?
更新:
通过热门需求回购来举例说明我遇到的问题 https://github.com/vartec/example_repo_setuptools_issue
为什么不覆盖这样的测试命令:
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,
},
)
因此,据我了解,问题是 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"。您可以声明多个 "extras",并在需要时将它们安装为 pip install mylib[ext1,ext2]
。
然后您可以 运行 两种方式进行测试:
pytest
python setup.py test
后一个仅在 test
命令已经配置为 运行 pytest(参见 pytest integration manual)时才会出现。
诀窍是,如果setuptools
可以在当前环境中找到测试依赖(virtualenv,pyenv,系统python,等等),它不会像鸡蛋一样安装它们,并且只会使用已安装的版本。
实际上,在这种情况下您甚至不需要声明 tests_require=
,因为假定库已安装到 virtualenv 中。如果不是,测试命令将失败。
同样,您可以 pip install .[docs]
,并使用当前 virtualenv 中的 sphinx-build ...
命令构建您的文档。
请注意 install_requires
始终会安装,无论您是否添加了附加功能。因此 app/lib 本身将始终具有完整的功能、可导入和自省。
希望这就是问题所在(如果我理解正确的话)。
您可以使用 requirements.txt
文件指定的依赖项不在 PyPI 中,而不是 setup.py
.
setup
方法的 dependency_links
参数
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,
},
)
我分叉了你的示例回购并做了一些更改
https://github.com/gentcys/example_repo_setuptools_issue.git
我创建了一个子模块回购
https://github.com/gentcys/example_repo_setuptools_issue_submodule.git
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
如果你真的不关心 test
情况下的 install_requires
那么你可以只做
if sys.argv[1] == "test":
install_requires = []