如何让 tox 和 poetry 协同工作以支持测试 Python 依赖项的多个版本?
How can I get tox and poetry to work together to support testing multiple versions of a Python dependency?
我正在将一个当前使用 pipenv
的项目切换到 poetry
作为测试以查看有何差异。该项目是一个简单的、可再分发的 Django 应用程序。它支持 Python 3.6-8,以及 Django 2.2 和 3.0。我有一个 tox.ini
文件,涵盖了 Python 和 Django 的所有组合,因此:
[tox]
envlist = py{36,37,38}-django{22,30}
[testenv]
whitelist_externals = poetry
skip_install = true
deps =
django22: Django==2.2
django30: Django==3.0
commands =
poetry install -vvv
poetry run pytest --cov=my_app tests/
poetry run coverage report -m
我遇到的问题(在 pipenv
世界中不存在)是 poetry install
语句将始终覆盖 deps
部分中的任何内容在 poetry.lock
文件中(如果不存在,将自动生成)。这意味着测试矩阵永远不会针对 Django 2.2 进行测试——因为每个 tox virtualenv 默认安装 Django 3.0。
我不明白这应该如何工作 - 使用 poetry
安装依赖项是否应该尊重安装它的现有环境?
所以 - 我的问题是 - 如何设置多版本 tox(或 travis)测试矩阵,将 poetry 作为依赖管理器?
我的 pyproject.toml
将 Python / Django 版本定义为:
[tool.poetry.dependencies]
python = "^3.6"
django = "^2.2 || ^3.0"
生成的 poetry.lock
文件(未提交)具有此 Django 版本信息:
[[package]]
category = "main"
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
name = "django"
optional = false
python-versions = ">=3.6"
version = "3.0"
更新:包括干净的毒物输出
这是我删除lock文件,重新创建tox环境后的结果。如您所见,tox 在 virtualenv 中安装 Django==2.2
作为依赖项,但是 poetry
然后在安装时将其更新为 3.0
。
我需要一个 运行 诗歌安装的解决方案,尊重现有的软件包安装。即,如果 pyproject.toml
声明 Django = "^2.2 || ^3.0"
,并且已经安装了 2.2,则固定到该版本 - 不要尝试升级。
my-app$ tox -r -e py36-django22
py36-django22 recreate: .tox/py36-django22
py36-django22 installdeps: Django==2.2
py36-django22 installed: Django==2.2,my-app==0.1.0,pytz==2019.3,sqlparse==0.3.0
py36-django22 run-test: commands[0] | poetry install -vvv
Using virtualenv: .tox/py36-django22
Updating dependencies
Resolving dependencies...
1: derived: django (^2.2 || ^3.0)
...
PyPI: 10 packages found for django >=2.2,<4.0
...
1: Version solving took 3.330 seconds.
1: Tried 1 solutions.
Writing lock file
Package operations: 52 installs, 1 update, 0 removals, 3 skipped
- ...
- Updating django (2.2 -> 3.0)
- ...
更新 2
按照下面 sinoroc 的说明 - 我更新了 tox 文件以删除 skip_dist
并包含 isolated_build
。这行得通,有点。 tox 构建并安装包 - 但仅非开发版本,不包括 pytest
、coverage
和我想在稍后包含的大量 linting 工具。即我想要通过 tox 运行 的工具在诗歌中被指定为开发依赖项。这里有一个解决方案,将所有这些都包含在 tox 文件中——但这似乎弄巧成拙——因为那时我有 poetry 和 tox 都声明了依赖关系。
[tool.poetry.dependencies]
python = "^3.6"
django = "^2.2 || ^3.0"
[tool.poetry.dev-dependencies]
pytest = "^3.0"
pytest-cov = "^2.8"
pytest-django = "^3.7"
coverage = "^4.5"
pylint = "^2.4"
pylint-django = "^2.0"
flake8 = "^3.7"
flake8-bandit = "^2.1"
flake8-docstrings = "^1.5"
isort = "^4.3"
mypy = "^0.750.0"
pre-commit = "^1.20"
black = "=19.3b0"
更新 3:解决方案
[tox]
isolated_build = True
envlist = lint, mypy, py{36,37,38}-django{22,30}
[travis]
python =
3.6: lint, mypy, py36
3.7: lint, mypy, py37
3.8: lint, mypy, py38
[testenv]
deps =
pytest
pytest-cov
pytest-django
coverage
django22: Django==2.2
django30: Django==3.0
commands =
django-admin --version
pytest --cov=my_app tests/
[testenv:lint]
deps =
pylint
pylint-django
flake8
flake8-bandit
flake8-docstrings
isort
black
commands =
isort --recursive my_app
black my_app
pylint my_app
flake8 my_app
[testenv:mypy]
deps =
mypy
commands =
mypy my_app
还没有彻底测试过,但我相信这样的东西应该有效:
[tox]
envlist = py{36,37,38}-django{22,30}
isolated_build = True
[testenv]
deps =
django22: Django==2.2
django30: Django==3.0
# plus the dev dependencies
pytest
coverage
commands =
pytest --cov=my_app tests/
coverage report -m
参见"poetry" section in the "packaging" chapter of the tox documentation。
为了避免重复 dev 依赖项,可以尝试以下基于 extras feature 的变体:
tox.ini
[tox]
# ...
[testenv]
# ...
deps =
django22: Django==2.2
django30: Django==3.0
extras =
test
pyproject.toml
[tool.poetry]
# ...
[tool.poetry.dependencies]
python = "^3.6"
django = "^2.2 || ^3.0"
#
pytest = { version = "^5.2", optional = true }
[tool.poetry.extras]
test = ["pytest"]
[build-system]
# ...
现在有 tox 插件试图与基于 poetry 的项目更好地集成:
我正在将一个当前使用 pipenv
的项目切换到 poetry
作为测试以查看有何差异。该项目是一个简单的、可再分发的 Django 应用程序。它支持 Python 3.6-8,以及 Django 2.2 和 3.0。我有一个 tox.ini
文件,涵盖了 Python 和 Django 的所有组合,因此:
[tox]
envlist = py{36,37,38}-django{22,30}
[testenv]
whitelist_externals = poetry
skip_install = true
deps =
django22: Django==2.2
django30: Django==3.0
commands =
poetry install -vvv
poetry run pytest --cov=my_app tests/
poetry run coverage report -m
我遇到的问题(在 pipenv
世界中不存在)是 poetry install
语句将始终覆盖 deps
部分中的任何内容在 poetry.lock
文件中(如果不存在,将自动生成)。这意味着测试矩阵永远不会针对 Django 2.2 进行测试——因为每个 tox virtualenv 默认安装 Django 3.0。
我不明白这应该如何工作 - 使用 poetry
安装依赖项是否应该尊重安装它的现有环境?
所以 - 我的问题是 - 如何设置多版本 tox(或 travis)测试矩阵,将 poetry 作为依赖管理器?
我的 pyproject.toml
将 Python / Django 版本定义为:
[tool.poetry.dependencies]
python = "^3.6"
django = "^2.2 || ^3.0"
生成的 poetry.lock
文件(未提交)具有此 Django 版本信息:
[[package]]
category = "main"
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
name = "django"
optional = false
python-versions = ">=3.6"
version = "3.0"
更新:包括干净的毒物输出
这是我删除lock文件,重新创建tox环境后的结果。如您所见,tox 在 virtualenv 中安装 Django==2.2
作为依赖项,但是 poetry
然后在安装时将其更新为 3.0
。
我需要一个 运行 诗歌安装的解决方案,尊重现有的软件包安装。即,如果 pyproject.toml
声明 Django = "^2.2 || ^3.0"
,并且已经安装了 2.2,则固定到该版本 - 不要尝试升级。
my-app$ tox -r -e py36-django22
py36-django22 recreate: .tox/py36-django22
py36-django22 installdeps: Django==2.2
py36-django22 installed: Django==2.2,my-app==0.1.0,pytz==2019.3,sqlparse==0.3.0
py36-django22 run-test: commands[0] | poetry install -vvv
Using virtualenv: .tox/py36-django22
Updating dependencies
Resolving dependencies...
1: derived: django (^2.2 || ^3.0)
...
PyPI: 10 packages found for django >=2.2,<4.0
...
1: Version solving took 3.330 seconds.
1: Tried 1 solutions.
Writing lock file
Package operations: 52 installs, 1 update, 0 removals, 3 skipped
- ...
- Updating django (2.2 -> 3.0)
- ...
更新 2
按照下面 sinoroc 的说明 - 我更新了 tox 文件以删除 skip_dist
并包含 isolated_build
。这行得通,有点。 tox 构建并安装包 - 但仅非开发版本,不包括 pytest
、coverage
和我想在稍后包含的大量 linting 工具。即我想要通过 tox 运行 的工具在诗歌中被指定为开发依赖项。这里有一个解决方案,将所有这些都包含在 tox 文件中——但这似乎弄巧成拙——因为那时我有 poetry 和 tox 都声明了依赖关系。
[tool.poetry.dependencies]
python = "^3.6"
django = "^2.2 || ^3.0"
[tool.poetry.dev-dependencies]
pytest = "^3.0"
pytest-cov = "^2.8"
pytest-django = "^3.7"
coverage = "^4.5"
pylint = "^2.4"
pylint-django = "^2.0"
flake8 = "^3.7"
flake8-bandit = "^2.1"
flake8-docstrings = "^1.5"
isort = "^4.3"
mypy = "^0.750.0"
pre-commit = "^1.20"
black = "=19.3b0"
更新 3:解决方案
[tox]
isolated_build = True
envlist = lint, mypy, py{36,37,38}-django{22,30}
[travis]
python =
3.6: lint, mypy, py36
3.7: lint, mypy, py37
3.8: lint, mypy, py38
[testenv]
deps =
pytest
pytest-cov
pytest-django
coverage
django22: Django==2.2
django30: Django==3.0
commands =
django-admin --version
pytest --cov=my_app tests/
[testenv:lint]
deps =
pylint
pylint-django
flake8
flake8-bandit
flake8-docstrings
isort
black
commands =
isort --recursive my_app
black my_app
pylint my_app
flake8 my_app
[testenv:mypy]
deps =
mypy
commands =
mypy my_app
还没有彻底测试过,但我相信这样的东西应该有效:
[tox]
envlist = py{36,37,38}-django{22,30}
isolated_build = True
[testenv]
deps =
django22: Django==2.2
django30: Django==3.0
# plus the dev dependencies
pytest
coverage
commands =
pytest --cov=my_app tests/
coverage report -m
参见"poetry" section in the "packaging" chapter of the tox documentation。
为了避免重复 dev 依赖项,可以尝试以下基于 extras feature 的变体:
tox.ini
[tox]
# ...
[testenv]
# ...
deps =
django22: Django==2.2
django30: Django==3.0
extras =
test
pyproject.toml
[tool.poetry]
# ...
[tool.poetry.dependencies]
python = "^3.6"
django = "^2.2 || ^3.0"
#
pytest = { version = "^5.2", optional = true }
[tool.poetry.extras]
test = ["pytest"]
[build-system]
# ...
现在有 tox 插件试图与基于 poetry 的项目更好地集成: