Generate run-time requirements for tests

This commit is contained in:
Petr Viktorin 2019-07-17 18:16:16 +02:00
parent 204b801da2
commit bc156c4460
7 changed files with 61 additions and 12 deletions

View File

@ -17,12 +17,14 @@ if [ -d %{buildroot}%{python3_sitearch} ]; then
fi
}
%pyproject_buildrequires() %{expand:\\\
%pyproject_buildrequires(r) %{expand:\\\
echo 'python3-devel'
echo 'python3dist(packaging)'
echo 'python3dist(pip) >= 19'
echo 'python3dist(pytoml)'
# setuptools assumes no pre-existing dist-info
rm -rfv *.dist-info/
if [ -f %{__python3} ]; then
%{__python3} -I %{_rpmconfigdir}/redhat/pyproject_buildrequires.py %{?*}
%{__python3} -I %{_rpmconfigdir}/redhat/pyproject_buildrequires.py %{?**}
fi
}

View File

@ -34,6 +34,8 @@ BuildRequires: python3dist(pyyaml)
BuildRequires: python3dist(packaging)
BuildRequires: python3dist(pytoml)
BuildRequires: python3dist(pip)
BuildRequires: python3dist(setuptools)
BuildRequires: python3dist(wheel)
%endif

View File

@ -8,6 +8,7 @@ from io import StringIO
import subprocess
import pathlib
import re
import email.parser
print_err = functools.partial(print, file=sys.stderr)
@ -83,7 +84,6 @@ class Requirements:
key=lambda s: (s.operator, s.version),
):
version = canonicalize_version(specifier.version)
print_err(version)
if not VERSION_RE.fullmatch(str(specifier.version)):
raise ValueError(
f'Unknown character in version: {specifier.version}. '
@ -154,6 +154,22 @@ def generate_build_requirements(backend, requirements):
requirements.extend(new_reqs, source='get_requires_for_build_wheel')
def generate_run_requirements(backend, requirements):
prepare_metadata = getattr(backend, "prepare_metadata_for_build_wheel", None)
if not prepare_metadata:
raise ValueError(
'build backend cannot provide build metadata '
+ '(incl. runtime requirements) before buld'
)
with hook_call():
dir_basename = prepare_metadata('.')
with open(dir_basename + '/METADATA') as f:
message = email.parser.Parser().parse(f, headersonly=True)
for key in 'Requires', 'Requires-Dist':
requires = message.get_all(key, ())
requirements.extend(requires, source=f'wheel metadata: {key}')
def python3dist(name, op=None, version=None):
if op is None:
if version is not None:
@ -163,12 +179,14 @@ def python3dist(name, op=None, version=None):
return f'python3dist({name}) {op} {version}'
def generate_requires(freeze_output):
def generate_requires(freeze_output, *, include_runtime=False, toxenv=None):
requirements = Requirements(freeze_output)
try:
backend = get_backend(requirements)
generate_build_requirements(backend, requirements)
if include_runtime:
generate_run_requirements(backend, requirements)
except EndPass:
return
@ -178,11 +196,11 @@ def main(argv):
description='Generate BuildRequires for a Python project.'
)
parser.add_argument(
'--runtime', action='store_true',
'-r', '--runtime', action='store_true',
help='Generate run-time requirements (not implemented)',
)
parser.add_argument(
'--toxenv', metavar='TOXENVS',
'-t', '--toxenv', metavar='TOXENVS',
help='generate test tequirements from tox environment '
+ '(not implemented; implies --runtime)',
)
@ -190,8 +208,7 @@ def main(argv):
args = parser.parse_args(argv)
if args.toxenv:
args.runtime = True
if args.runtime:
print_err('--runtime is not implemented')
print_err('--toxenv is not implemented')
exit(1)
freeze_output = subprocess.run(
@ -202,7 +219,7 @@ def main(argv):
).stdout
try:
generate_requires(freeze_output)
generate_requires(freeze_output, include_runtime=args.runtime)
except Exception as e:
# Log the traceback explicitly (it's useful debug info)
traceback.print_exc()

View File

@ -28,10 +28,13 @@ def test_data(case_name, capsys, tmp_path, monkeypatch):
try:
generate_requires(
case['freeze_output'],
include_runtime=case.get('include_runtime', False),
)
except SystemExit as e:
assert e.code == case['result']
except Exception as e:
if 'except' not in case:
raise
assert type(e).__name__ == case['except']
else:
assert 0 == case['result']

View File

@ -99,7 +99,7 @@ Build system dependencies in pyproject.toml:
python3dist(wheel)
result: 0
Default build system, dependencies in setup.py:
Default build system, build dependencies in setup.py:
freeze_output: |
setuptools==50
wheel==1
@ -109,6 +109,7 @@ Default build system, dependencies in setup.py:
name='test',
version='0.1',
setup_requires=['foo', 'bar!=2'],
install_requires=['inst'],
)
expected: |
python3dist(setuptools) >= 40.8
@ -117,3 +118,26 @@ Default build system, dependencies in setup.py:
python3dist(foo)
(python3dist(bar) < 2 or python3dist(bar) > 2.0)
result: 0
Default build system, run dependencies in setup.py:
freeze_output: |
setuptools==50
wheel==1
pyyaml==1
include_runtime: true
setup.py: |
from setuptools import setup
setup(
name='test',
version='0.1',
setup_requires=['pyyaml'], # nb. setuptools will try to install this
install_requires=['inst > 1', 'inst2 < 3'],
)
expected: |
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(pyyaml)
python3dist(inst) > 1
python3dist(inst2) < 3
result: 0

View File

@ -27,7 +27,8 @@ Discover and load entry points from installed packages.
%generate_buildrequires
%pyproject_buildrequires
rm -rfv *.dist-info/
%pyproject_buildrequires -r
%build

View File

@ -27,7 +27,7 @@ py.test provides simple, yet powerful testing for Python.
%generate_buildrequires
%pyproject_buildrequires
%pyproject_buildrequires -r
%build