I finally got around to this mail...
On 2020-04-19 16:55, Miro Hrončok wrote:
Hello Python packagers.
After touching the %python_provide topic in:
https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproje...
I have realized several things I don't like about %python_provide:
- It must be used conditionally (it is not defined in python-srpm-macros).
That means you always wrap it in %{?python_provide:...} in order to have a "valid" specfile even when the macro is not yet defined (e.g. during SRPM creation in Koji or on a packager's machine without python-rpm-macros installed).
- You cannot use it with arbitrary versions. Suppose you package
python3-foo 1.0 but you want to provide python3-bar 2.0 for some reason -- this is not very common, but it happens. %python_provide only takes the "name" as an argument, always using %{?epoch} %{version} and %{release}.
- You need to both add a virtual provide + use the macro. Suppose you
want to provide python3-pkg_resources from python3-setuptools. Currently, you need to add:
Provides: python3-pkg_resources = %{version}-%{release} %{?python_provide:%python_provide python3-pkg_resources}
- When used with (sub)package name, it generates a duplicate dependency
on Fedora 33+ (and an rpmlint error).
- It produces Obsoletes, but that might no longer be necessary nor
desired.
- Broken expectations about %_isa. It used to add %_isa provides based
on wrong data, it no longer does that (except on old releases and EPELs), can be used manually with name%{?_isa}, but not on the old releases.
- Undocuemnted error handling (e.g. the macro expands to nothing when
used with pypy-foo, but errors when used with foo).
Hence, I was thinking (for the sake of backwards compatibility) to provide a new mechanism to do this and preserve the old macro as is, deprecating it in Fedora 36-ish, actually maybe removing it once RHEL 9 goes EOL (or never, which is basically the same from today's perspective).
The new macro should solve the problems from above, my current (quick, untested) ideas are:
- Define the macro in python-srpm-macros. No need to use it
conditionally. We can backport it to EPEL 8 and define a "stub" macro in EPEL 7 and 6. (An if we start using the macro only after Fedora 30 goes EOL, we can make the macro behave consistently across all Fedora versions.)
- Accept version identifier as an optional argument, use %{?epoch}
%{version} and %{release} as default. (See for example %{pypi_source} on how this can be done.)
- Make the macro also produce the provide for the given name and
document that. E.g. when you call it with python3-pkg_resources, it also provides python3-pkg_resources (not only python-pkg_resources etc.).
- Make it so that for given arguments, the macro will only expand to
something once per build. Hence when you use it with package name, the automatic provides won't re-add the same provide again. This also means you cannot have 2 different (sub)packages provide the same name-version-release, but that shall be very very very uncommon need and can always be workarounded somehow if needed.
- No obsoletes with the new macro. Packagers use manual obsoletes when
desired.
- Document clearly that there is no %{?_isa} (and there is no
"backwards compatibility" load to carry). When absolutely desired, packagers can call the macro with %{name}%{?_isa}.
- Support arbitrary names. Only provide the given name and nothing else
if not "recognized".
Is that better than erroring out when something is not recognized?
As a bonus, I think the current if-elif-elif-elif-elif code can be replaced with lua patterns (imagine regex).
As always, this leaves us with the name problem, but I'd very much like to use %python_provides (note the s). The only problem I see is that it is likely to be mistaken for the old one, but IMHO it shouldn't really hurt that much.
I guess something like %py_provides would also work, and maybe fit more nicely with the new generation of macros. Do you like full "python" prefix? But that's bikeshedding.
Usage example:
%package -n python3-setuptools %python_provides python3-pkg_resources
Resulting provides:
python3-setuptools = 46.6.6-6.fc33 python-setuptools = 46.6.6-6.fc33 python39-pkg_resources = 46.6.6-6.fc33 python3-pkg_resources = 46.6.6-6.fc33 python-pkg_resources = 46.6.6-6.fc33 python39-pkg_resources = 46.6.6-6.fc33
I assume you meant "python39-setuptools" there.
Another example:
%package -n python3-pillow %python_provides python3-PIL 1.1.6-100
Resulting provides:
python3-pillow = 7.1.1-1.fc33 python-pillow = 7.1.1-1.fc33 python39-pillow = 7.1.1-1.fc33 python3-PIL = 1.1.6-100 python-PIL = 1.1.6-100 python39-PIL = 1.1.6-100
Dummy when used with package name:
%package -n python3-pip %python_provides python3-pip
Provides:
python3-pip = 20.0.2-1.fc33 python-pip = 20.0.2-1.fc33 python39-pip = 20.0.2-1.fc33 (all of them only once)
Any name is OK:
%python_provides wroom 666
Provides:
wroom = 666
What do you think?
Love it! I haven't thought about how feasible it is to implement, but I trust you on that.