Hello folks,
I'd like to get feedback on a new macro for pyproject-rpm-macros that
allows packagers to override upstream dependency constraints that are
incompatible with the versions available in Fedora.
*The problem*
More and more packages move to pyproject macros that make use of upstream
metadata. Upstream Python projects frequently pin or constrain dependency
versions (e.g. numpy<2.0, attrs==25.3). When Fedora ships a different
version, packagers currently resort to sed/patch in %prep to modify
pyproject.toml, requirements.txt, setup.cfg etc. This is quite fragile and
honestly a pain point every time as it breaks on upstream reformatting,
varies across build systems and pollutes the spec. And I'm not the biggest
fan of deciphering regexes.
*The solution*
A new %pyproject_patch_dependency macro, declared in %prep, that provides a
uniform way to modify dependency constraints regardless of the build
backend. It affects both BuildRequires (via %pyproject_buildrequires) and
runtime Requires (via patching the installed .dist-info/METADATA during
%pyproject_install).
*Usage*
%prep
%autosetup -p1
%pyproject_patch_dependency cython:drop_upper
%pyproject_patch_dependency numpy:set_upper:3.0
%pyproject_patch_dependency legacy-dep:ignore
One override per macro call. The syntax is:
%pyproject_patch_dependency PACKAGE:ACTION[:VALUE][:br_only]
The reasoning for only one override per macro call is that each override
should be verified and possibly commented on why it's needed, instead of
blindly removing dependencies. Also having one per line will keep the spec
readable. More than one argument in the macro call will make it error out.
*Available actions*
- drop_upper: remove upper-bound constraints (<, <=, ==, ~=)
- drop_lower: remove lower-bound constraints (>, >=, ==, ~=)
- drop_constraints: remove all version constraints
- set_upper: replace the upper bound with < VALUE
- set_lower: replace the lower bound with >= VALUE
- ignore: remove the dependency entirely
Note: == and ~= act as both upper and lower bounds, so either drop_upper or
drop_lower will remove them. Exclusions (!=) are always preserved.
*Multi-wheel packages (br_only)*
For spec files that build multiple Python subpackages from one source, a
sibling package may need to be ignored in BuildRequires (as it's not yet
installed during build) but kept as a runtime dependency. The br_only
suffix handles this:
%pyproject_patch_dependency sibling-package:ignore:br_only
This ignores the dependency during %generate_buildrequires but leaves the
installed METADATA untouched, so the runtime Requires is preserved.
Related bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2386906
PR: https://src.fedoraproject.org/rpms/pyproject-rpm-macros/pull-request/567
Alternative approach with a -D flag (most likely will not move this
forward):
https://src.fedoraproject.org/rpms/pyproject-rpm-macros/pull-request/564
Feedback on the API, action names, or overall approach is welcome.
--
Regards,
Charalampos Stratakis
Senior Software Engineer
Python Maintenance Team, Red Hat