Allow passing config_settings to the build backend
Related: rhbz#2208971
This commit is contained in:
parent
d5a5919a27
commit
7f75263357
@ -4,4 +4,4 @@
|
|||||||
# this macro will cause the package with the real macro to be installed.
|
# this macro will cause the package with the real macro to be installed.
|
||||||
# When macros.pyproject is installed, it overrides this macro.
|
# When macros.pyproject is installed, it overrides this macro.
|
||||||
# Note: This needs to maintain the same set of options as the real macro.
|
# Note: This needs to maintain the same set of options as the real macro.
|
||||||
%pyproject_buildrequires(rRxtNwe:) echo 'pyproject-rpm-macros' && exit 0
|
%pyproject_buildrequires(rRxtNwe:C:) echo 'pyproject-rpm-macros' && exit 0
|
||||||
|
@ -26,11 +26,11 @@
|
|||||||
# The value is read and used by the %%pytest and %%tox macros:
|
# The value is read and used by the %%pytest and %%tox macros:
|
||||||
%_set_pytest_addopts %global __pytest_addopts --ignore=%{_pyproject_builddir}
|
%_set_pytest_addopts %global __pytest_addopts --ignore=%{_pyproject_builddir}
|
||||||
|
|
||||||
%pyproject_wheel() %{expand:\\\
|
%pyproject_wheel(C:) %{expand:\\\
|
||||||
%_set_pytest_addopts
|
%_set_pytest_addopts
|
||||||
mkdir -p "%{_pyproject_builddir}"
|
mkdir -p "%{_pyproject_builddir}"
|
||||||
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}" TMPDIR="%{_pyproject_builddir}" \\\
|
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}" TMPDIR="%{_pyproject_builddir}" \\\
|
||||||
%{__python3} -Bs %{_rpmconfigdir}/redhat/pyproject_wheel.py %{_pyproject_wheeldir}
|
%{__python3} -Bs %{_rpmconfigdir}/redhat/pyproject_wheel.py %{?**} %{_pyproject_wheeldir}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
# Note: Keep the options in sync with this macro from macros.aaa-pyproject-srpm
|
# Note: Keep the options in sync with this macro from macros.aaa-pyproject-srpm
|
||||||
%pyproject_buildrequires(rRxtNwe:) %{expand:\\\
|
%pyproject_buildrequires(rRxtNwe:C:) %{expand:\\\
|
||||||
%_set_pytest_addopts
|
%_set_pytest_addopts
|
||||||
# The _auto_set_build_flags feature does not do this in %%generate_buildrequires section,
|
# The _auto_set_build_flags feature does not do this in %%generate_buildrequires section,
|
||||||
# but we want to get an environment consistent with %%build:
|
# but we want to get an environment consistent with %%build:
|
||||||
|
@ -13,7 +13,7 @@ License: MIT
|
|||||||
# Increment Y and reset Z when new macros or features are added
|
# Increment Y and reset Z when new macros or features are added
|
||||||
# Increment Z when this is a bugfix or a cosmetic change
|
# Increment Z when this is a bugfix or a cosmetic change
|
||||||
# Dropping support for EOL Fedoras is *not* considered a breaking change
|
# Dropping support for EOL Fedoras is *not* considered a breaking change
|
||||||
Version: 1.8.1
|
Version: 1.9.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
|
|
||||||
# Macro files
|
# Macro files
|
||||||
@ -161,6 +161,9 @@ export HOSTNAME="rpmbuild" # to speedup tox in network-less mock, see rhbz#1856
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed May 31 2023 Maxwell G <maxwell@gtmx.me> - 1.9.0-1
|
||||||
|
- Allow passing config_settings to the build backend.
|
||||||
|
|
||||||
* Wed May 31 2023 Miro Hrončok <mhroncok@redhat.com> - 1.8.1-1
|
* Wed May 31 2023 Miro Hrončok <mhroncok@redhat.com> - 1.8.1-1
|
||||||
- On Python older than 3.11, use tomli instead of deprecated toml
|
- On Python older than 3.11, use tomli instead of deprecated toml
|
||||||
- Fix literal %% handling in %%{pyproject_files} on RPM 4.19
|
- Fix literal %% handling in %%{pyproject_files} on RPM 4.19
|
||||||
|
@ -14,6 +14,7 @@ import pathlib
|
|||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
from pyproject_requirements_txt import convert_requirements_txt
|
from pyproject_requirements_txt import convert_requirements_txt
|
||||||
|
from pyproject_wheel import parse_config_settings_args
|
||||||
|
|
||||||
|
|
||||||
# Some valid Python version specifiers are not supported.
|
# Some valid Python version specifiers are not supported.
|
||||||
@ -67,7 +68,7 @@ def guess_reason_for_invalid_requirement(requirement_str):
|
|||||||
class Requirements:
|
class Requirements:
|
||||||
"""Requirement gatherer. The macro will eventually print out output_lines."""
|
"""Requirement gatherer. The macro will eventually print out output_lines."""
|
||||||
def __init__(self, get_installed_version, extras=None,
|
def __init__(self, get_installed_version, extras=None,
|
||||||
generate_extras=False, python3_pkgversion='3'):
|
generate_extras=False, python3_pkgversion='3', config_settings=None):
|
||||||
self.get_installed_version = get_installed_version
|
self.get_installed_version = get_installed_version
|
||||||
self.output_lines = []
|
self.output_lines = []
|
||||||
self.extras = set()
|
self.extras = set()
|
||||||
@ -81,6 +82,7 @@ class Requirements:
|
|||||||
|
|
||||||
self.generate_extras = generate_extras
|
self.generate_extras = generate_extras
|
||||||
self.python3_pkgversion = python3_pkgversion
|
self.python3_pkgversion = python3_pkgversion
|
||||||
|
self.config_settings = config_settings
|
||||||
|
|
||||||
def add_extras(self, *extras):
|
def add_extras(self, *extras):
|
||||||
self.extras |= set(e.strip() for e in extras)
|
self.extras |= set(e.strip() for e in extras)
|
||||||
@ -269,7 +271,7 @@ def get_backend(requirements):
|
|||||||
def generate_build_requirements(backend, requirements):
|
def generate_build_requirements(backend, requirements):
|
||||||
get_requires = getattr(backend, 'get_requires_for_build_wheel', None)
|
get_requires = getattr(backend, 'get_requires_for_build_wheel', None)
|
||||||
if get_requires:
|
if get_requires:
|
||||||
new_reqs = get_requires()
|
new_reqs = get_requires(config_settings=requirements.config_settings)
|
||||||
requirements.extend(new_reqs, source='get_requires_for_build_wheel')
|
requirements.extend(new_reqs, source='get_requires_for_build_wheel')
|
||||||
requirements.check(source='get_requires_for_build_wheel')
|
requirements.check(source='get_requires_for_build_wheel')
|
||||||
|
|
||||||
@ -303,7 +305,7 @@ def generate_run_requirements_hook(backend, requirements):
|
|||||||
'Use the provisional -w flag to build the wheel and parse the metadata from it, '
|
'Use the provisional -w flag to build the wheel and parse the metadata from it, '
|
||||||
'or use the -R flag not to generate runtime dependencies.'
|
'or use the -R flag not to generate runtime dependencies.'
|
||||||
)
|
)
|
||||||
dir_basename = prepare_metadata('.')
|
dir_basename = prepare_metadata('.', config_settings=requirements.config_settings)
|
||||||
with open(dir_basename + '/METADATA') as metadata_file:
|
with open(dir_basename + '/METADATA') as metadata_file:
|
||||||
name, requires = package_name_and_requires_from_metadata_file(metadata_file)
|
name, requires = package_name_and_requires_from_metadata_file(metadata_file)
|
||||||
for key, req in requires.items():
|
for key, req in requires.items():
|
||||||
@ -327,7 +329,11 @@ def generate_run_requirements_wheel(backend, requirements, wheeldir):
|
|||||||
wheel = find_built_wheel(wheeldir)
|
wheel = find_built_wheel(wheeldir)
|
||||||
if not wheel:
|
if not wheel:
|
||||||
import pyproject_wheel
|
import pyproject_wheel
|
||||||
returncode = pyproject_wheel.build_wheel(wheeldir=wheeldir, stdout=sys.stderr)
|
returncode = pyproject_wheel.build_wheel(
|
||||||
|
wheeldir=wheeldir,
|
||||||
|
stdout=sys.stderr,
|
||||||
|
config_settings=requirements.config_settings,
|
||||||
|
)
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
raise RuntimeError('Failed to build the wheel for %pyproject_buildrequires -w.')
|
raise RuntimeError('Failed to build the wheel for %pyproject_buildrequires -w.')
|
||||||
wheel = find_built_wheel(wheeldir)
|
wheel = find_built_wheel(wheeldir)
|
||||||
@ -415,7 +421,7 @@ def generate_requires(
|
|||||||
*, include_runtime=False, build_wheel=False, wheeldir=None, toxenv=None, extras=None,
|
*, include_runtime=False, build_wheel=False, wheeldir=None, toxenv=None, extras=None,
|
||||||
get_installed_version=importlib.metadata.version, # for dep injection
|
get_installed_version=importlib.metadata.version, # for dep injection
|
||||||
generate_extras=False, python3_pkgversion="3", requirement_files=None, use_build_system=True,
|
generate_extras=False, python3_pkgversion="3", requirement_files=None, use_build_system=True,
|
||||||
output,
|
output, config_settings=None,
|
||||||
):
|
):
|
||||||
"""Generate the BuildRequires for the project in the current directory
|
"""Generate the BuildRequires for the project in the current directory
|
||||||
|
|
||||||
@ -426,7 +432,8 @@ def generate_requires(
|
|||||||
requirements = Requirements(
|
requirements = Requirements(
|
||||||
get_installed_version, extras=extras or [],
|
get_installed_version, extras=extras or [],
|
||||||
generate_extras=generate_extras,
|
generate_extras=generate_extras,
|
||||||
python3_pkgversion=python3_pkgversion
|
python3_pkgversion=python3_pkgversion,
|
||||||
|
config_settings=config_settings,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -516,6 +523,12 @@ def main(argv):
|
|||||||
metavar='REQUIREMENTS.TXT',
|
metavar='REQUIREMENTS.TXT',
|
||||||
help=('Add buildrequires from file'),
|
help=('Add buildrequires from file'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-C',
|
||||||
|
dest='config_settings',
|
||||||
|
action='append',
|
||||||
|
help='Configuration settings to pass to the PEP 517 backend',
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
@ -550,6 +563,7 @@ def main(argv):
|
|||||||
requirement_files=args.requirement_files,
|
requirement_files=args.requirement_files,
|
||||||
use_build_system=args.use_build_system,
|
use_build_system=args.use_build_system,
|
||||||
output=args.output,
|
output=args.output,
|
||||||
|
config_settings=parse_config_settings_args(args.config_settings),
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
# Log the traceback explicitly (it's useful debug info)
|
# Log the traceback explicitly (it's useful debug info)
|
||||||
|
@ -986,3 +986,40 @@ Self-referencing extras (maze):
|
|||||||
python3dist(rightdep)
|
python3dist(rightdep)
|
||||||
python3dist(startdep)
|
python3dist(startdep)
|
||||||
result: 0
|
result: 0
|
||||||
|
|
||||||
|
config_settings_control:
|
||||||
|
include_runtime: false
|
||||||
|
config_settings:
|
||||||
|
pyproject.toml: |
|
||||||
|
[build-system]
|
||||||
|
build-backend = "test_backend"
|
||||||
|
backend-path = ["."]
|
||||||
|
test_backend.py: |
|
||||||
|
def get_requires_for_build_wheel(config_settings=None):
|
||||||
|
if not (config_settings is None or isinstance(config_settings, dict)):
|
||||||
|
raise TypeError
|
||||||
|
if config_settings and "test-config-setting" in config_settings:
|
||||||
|
return ["test-config-setting"]
|
||||||
|
return ["test-no-config-setting"]
|
||||||
|
expected: |
|
||||||
|
python3dist(test-no-config-setting)
|
||||||
|
result: 0
|
||||||
|
|
||||||
|
config_settings:
|
||||||
|
include_runtime: false
|
||||||
|
config_settings:
|
||||||
|
test-config-setting: ""
|
||||||
|
pyproject.toml: |
|
||||||
|
[build-system]
|
||||||
|
build-backend = "test_backend"
|
||||||
|
backend-path = ["."]
|
||||||
|
test_backend.py: |
|
||||||
|
def get_requires_for_build_wheel(config_settings=None):
|
||||||
|
if not (config_settings is None or isinstance(config_settings, dict)):
|
||||||
|
raise TypeError
|
||||||
|
if config_settings and "test-config-setting" in config_settings:
|
||||||
|
return ["test-config-setting"]
|
||||||
|
return ["test-no-config-setting"]
|
||||||
|
expected: |
|
||||||
|
python3dist(test-config-setting)
|
||||||
|
result: 0
|
||||||
|
@ -1,8 +1,37 @@
|
|||||||
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
def build_wheel(*, wheeldir, stdout=None):
|
def parse_config_settings_args(config_settings):
|
||||||
|
"""
|
||||||
|
Given a list of config `KEY=VALUE` formatted config settings,
|
||||||
|
return a dictionary that can be passed to PEP 517 hook functions.
|
||||||
|
"""
|
||||||
|
if not config_settings:
|
||||||
|
return config_settings
|
||||||
|
new_config_settings = {}
|
||||||
|
for arg in config_settings:
|
||||||
|
key, _, value = arg.partition('=')
|
||||||
|
new_config_settings[key] = value
|
||||||
|
return new_config_settings
|
||||||
|
|
||||||
|
|
||||||
|
def get_config_settings_args(config_settings):
|
||||||
|
"""
|
||||||
|
Given a dictionary of PEP 517 backend config_settings,
|
||||||
|
yield --config-settings args that can be passed to pip's CLI
|
||||||
|
"""
|
||||||
|
if not config_settings:
|
||||||
|
return
|
||||||
|
for key, value in config_settings.items():
|
||||||
|
if value == '':
|
||||||
|
yield f'--config-settings={key}'
|
||||||
|
else:
|
||||||
|
yield f'--config-settings={key}={value}'
|
||||||
|
|
||||||
|
|
||||||
|
def build_wheel(*, wheeldir, stdout=None, config_settings=None):
|
||||||
command = (
|
command = (
|
||||||
sys.executable,
|
sys.executable,
|
||||||
'-m', 'pip',
|
'-m', 'pip',
|
||||||
@ -15,11 +44,26 @@ def build_wheel(*, wheeldir, stdout=None):
|
|||||||
'--no-clean',
|
'--no-clean',
|
||||||
'--progress-bar', 'off',
|
'--progress-bar', 'off',
|
||||||
'--verbose',
|
'--verbose',
|
||||||
|
*get_config_settings_args(config_settings),
|
||||||
'.',
|
'.',
|
||||||
)
|
)
|
||||||
cp = subprocess.run(command, stdout=stdout)
|
cp = subprocess.run(command, stdout=stdout)
|
||||||
return cp.returncode
|
return cp.returncode
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args(argv=None):
|
||||||
|
parser = argparse.ArgumentParser(prog='%pyproject_wheel')
|
||||||
|
parser.add_argument('wheeldir', help=argparse.SUPPRESS)
|
||||||
|
parser.add_argument(
|
||||||
|
'-C',
|
||||||
|
dest='config_settings',
|
||||||
|
action='append',
|
||||||
|
help='Configuration settings to pass to the PEP 517 backend',
|
||||||
|
)
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
args.config_settings = parse_config_settings_args(args.config_settings)
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(build_wheel(wheeldir=sys.argv[1]))
|
sys.exit(build_wheel(**vars(parse_args())))
|
||||||
|
@ -63,6 +63,7 @@ def test_data(case_name, capfd, tmp_path, monkeypatch):
|
|||||||
requirement_files=requirement_files,
|
requirement_files=requirement_files,
|
||||||
use_build_system=use_build_system,
|
use_build_system=use_build_system,
|
||||||
output=output,
|
output=output,
|
||||||
|
config_settings=case.get('config_settings'),
|
||||||
)
|
)
|
||||||
except SystemExit as e:
|
except SystemExit as e:
|
||||||
assert e.code == case['result']
|
assert e.code == case['result']
|
||||||
|
50
tests/config-settings-test.spec
Normal file
50
tests/config-settings-test.spec
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
Name: config-settings-test
|
||||||
|
Version: 1.0.0
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Test config_settings support
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
URL: ...
|
||||||
|
Source0: config_settings_test_backend.py
|
||||||
|
|
||||||
|
|
||||||
|
%description
|
||||||
|
%{summary}.
|
||||||
|
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%autosetup -cT
|
||||||
|
|
||||||
|
cp -p %{sources} .
|
||||||
|
|
||||||
|
cat <<'EOF' >config_settings.py
|
||||||
|
"""
|
||||||
|
This is a test package
|
||||||
|
"""
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<'EOF' >pyproject.toml
|
||||||
|
[build-system]
|
||||||
|
build-backend = "config_settings_test_backend"
|
||||||
|
backend-path = ["."]
|
||||||
|
requires = ["flit-core"]
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "config_settings"
|
||||||
|
version = "%{version}"
|
||||||
|
dynamic = ["description"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
%generate_buildrequires
|
||||||
|
%pyproject_buildrequires -C abc=123 -C xyz=456 -C--option-with-dashes=1
|
||||||
|
%pyproject_buildrequires -C abc=123 -C xyz=456 -C--option-with-dashes=1 -w
|
||||||
|
|
||||||
|
|
||||||
|
%build
|
||||||
|
%pyproject_wheel -C abc=123 -C xyz=456 -C--option-with-dashes=1
|
||||||
|
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Fri May 19 2023 Maxwell G <maxwell@gtmx.me>
|
||||||
|
- Initial package
|
31
tests/config_settings_test_backend.py
Normal file
31
tests/config_settings_test_backend.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
"""
|
||||||
|
This is a test backend for pyproject-rpm-macros' integration tests
|
||||||
|
It is not compliant with PEP 517 and omits some required hooks.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from flit_core import buildapi
|
||||||
|
|
||||||
|
EXPECTED_CONFIG_SETTINGS = {"abc": "123", "xyz": "456", "--option-with-dashes": "1"}
|
||||||
|
|
||||||
|
|
||||||
|
def _verify_config_settings(config_settings):
|
||||||
|
print(f"config_settings={config_settings}")
|
||||||
|
if config_settings != EXPECTED_CONFIG_SETTINGS:
|
||||||
|
raise ValueError(
|
||||||
|
f"{config_settings!r} does not match expected {EXPECTED_CONFIG_SETTINGS!r}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
|
||||||
|
_verify_config_settings(config_settings)
|
||||||
|
return buildapi.build_wheel(wheel_directory, None, metadata_directory)
|
||||||
|
|
||||||
|
|
||||||
|
def get_requires_for_build_wheel(config_settings=None):
|
||||||
|
_verify_config_settings(config_settings)
|
||||||
|
return buildapi.get_requires_for_build_wheel(None)
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
|
||||||
|
_verify_config_settings(config_settings)
|
||||||
|
return buildapi.prepare_metadata_for_build_wheel(metadata_directory, None)
|
@ -98,6 +98,9 @@
|
|||||||
- escape_percentages:
|
- escape_percentages:
|
||||||
dir: .
|
dir: .
|
||||||
run: ./mocktest.sh escape_percentages
|
run: ./mocktest.sh escape_percentages
|
||||||
|
- config-settings-test:
|
||||||
|
dir: .
|
||||||
|
run: ./mocktest.sh config-settings-test
|
||||||
required_packages:
|
required_packages:
|
||||||
- 'https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm'
|
- 'https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm'
|
||||||
- 'https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm'
|
- 'https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm'
|
||||||
|
Loading…
Reference in New Issue
Block a user