%pyproject_buildrequires: Add support for dependency groups (PEP 735), via tox configuration

This commit is contained in:
Miro Hrončok 2024-11-05 19:59:31 +01:00
parent 307d2bef63
commit 8baa94160c
5 changed files with 72 additions and 1 deletions

View File

@ -155,6 +155,9 @@ The `-e` option redefines `%{toxenv}` for further reuse.
Use `%{default_toxenv}` to get the default value.
The `-t`/`-e` option uses [tox-current-env]'s `--print-deps-to-file` behind the scenes.
It generates dependencies listed directly in `deps`,
dependencies defined through `extras`,
and on tox 4.22+ also dependencies defined through `dependency_groups`.
If your package specifies some tox plugins in `tox.requires`,
such plugins will be BuildRequired as well.

View File

@ -175,6 +175,7 @@ export HOSTNAME="rpmbuild" # to speedup tox in network-less mock, see rhbz#1856
%changelog
* Mon Nov 04 2024 Miro Hrončok <mhroncok@redhat.com> - 1.16.0-1
- %%pyproject_buildrequires: Add support for dependency groups (PEP 735), via the -g flag
- This is implied when used tox testenvs depend on dependency groups (requires tox 4.22+)
- Fixes: rhbz#2318849
* Thu Oct 03 2024 Karolina Surma <ksurma@redhat.com> - 1.15.1-1

View File

@ -468,6 +468,29 @@ def generate_tox_requirements(toxenv, requirements):
source=f'tox --print-deps-only: {toxenv}')
def tox_dependency_groups(toxenv):
# We call this command separately instead of folding it into the previous one
# becasue --print-dependency-groups-to only works with tox 4.22+ and tox-current-env 0.0.14+.
# We handle failure gracefully: upstreams using dependency_groups should require tox >= 4.22.
toxenv = ','.join(toxenv)
with tempfile.NamedTemporaryFile('r') as groups:
r = subprocess.run(
[sys.executable, '-m', 'tox',
'--print-dependency-groups-to', groups.name,
'-q', '-e', toxenv],
check=False,
encoding='utf-8',
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
if r.returncode == 0:
if r.stdout:
print_err(r.stdout, end='')
if output := groups.read().strip():
return output.splitlines()
return []
def generate_dependency_groups(requested_groups, requirements):
"""Adapted from https://peps.python.org/pep-0735/#reference-implementation (public domain)"""
from collections import defaultdict
@ -573,6 +596,7 @@ def generate_requires(
config_settings=config_settings,
)
dependency_groups = dependency_groups or []
try:
if (include_runtime or toxenv or read_pyproject_dependencies) and not use_build_system:
raise ValueError('-N option cannot be used in combination with -r, -e, -t, -x, -p options')
@ -588,7 +612,8 @@ def generate_requires(
generate_build_requirements(backend, requirements)
if toxenv:
include_runtime = True
generate_tox_requirements(toxenv, requirements) # TODO extend dependency_groups
generate_tox_requirements(toxenv, requirements)
dependency_groups.extend(tox_dependency_groups(toxenv))
if dependency_groups:
generate_dependency_groups(dependency_groups, requirements)
if include_runtime:

View File

@ -1385,3 +1385,37 @@ pyproject.toml with dependency-groups nonexisting requested:
tests = ["pytest>=5", "pytest-mock"]
docs = ["sphinx", "python-docs-theme"]
except: LookupError
tox with dependency_groups:
skipif: not (SETUPTOOLS_60 and TOX_4_22)
installed:
setuptools: 50
wheel: 1
tox: 4.22
tox-current-env: 0.0.14
toxenv:
- py3
pyproject.toml: |
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "my_package"
version = "0.1"
[dependency-groups]
tests = ["pytest>=5", "pytest-mock"]
docs = ["sphinx", "python-docs-theme"]
[tool.tox]
requires = ["tox>=4.22"]
[tool.tox.env_run_base]
dependency_groups = ["tests"]
commands = [["pytest"]]
expected: |
python3dist(setuptools)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox) >= 4.22
python3dist(tox)
python3dist(pytest) >= 5
python3dist(pytest-mock)
result: 0

View File

@ -11,6 +11,14 @@ from pyproject_buildrequires import generate_requires, load_pyproject
SETUPTOOLS_VERSION = packaging.version.parse(setuptools.__version__)
SETUPTOOLS_60 = SETUPTOOLS_VERSION >= packaging.version.parse('60')
try:
import tox
except ImportError:
TOX_4_22 = False
else:
TOX_VERSION = packaging.version.parse(tox.__version__)
TOX_4_22 = TOX_VERSION >= packaging.version.parse('4.22')
testcases = {}
with Path(__file__).parent.joinpath('pyproject_buildrequires_testcases.yaml').open() as f:
testcases = yaml.safe_load(f)