Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-rpm-macros for openSUSE:Factory checked in at 2026-06-29 17:28:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-rpm-macros (Old) and /work/SRC/openSUSE:Factory/.python-rpm-macros.new.11887 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-rpm-macros" Mon Jun 29 17:28:21 2026 rev:62 rq:1358060 version:20260601.4a231f4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-rpm-macros/python-rpm-macros.changes 2026-03-19 17:26:38.307164958 +0100 +++ /work/SRC/openSUSE:Factory/.python-rpm-macros.new.11887/python-rpm-macros.changes 2026-06-29 17:28:23.178004828 +0200 @@ -1,0 +2,16 @@ +Mon Jun 01 17:19:04 UTC 2026 - [email protected] + +- Update to version 20260601.4a231f4: + * fix: allow function of `%pythonXX_provides` w/o /usr/bin/python3 + * Update python version handling in default-prjconf + * Rewrite README.md to have headlines for each macro. +- Remove upstreamed better-python-provides.patch. + +------------------------------------------------------------------- +Thu May 28 17:16:48 UTC 2026 - Matej Cepl <[email protected]> + +- Add better-python-provides.patch to allow function of + `%pythonXX_provides` even without the access to + /usr/bin/python3. + +------------------------------------------------------------------- @@ -816 +831,0 @@ - Old: ---- python-rpm-macros-20260317.5e02b19.tar.xz New: ---- python-rpm-macros-20260601.4a231f4.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-rpm-macros.spec ++++++ --- /var/tmp/diff_new_pack.PgAH0w/_old 2026-06-29 17:28:24.542051123 +0200 +++ /var/tmp/diff_new_pack.PgAH0w/_new 2026-06-29 17:28:24.542051123 +0200 @@ -17,7 +17,7 @@ Name: python-rpm-macros -Version: 20260317.5e02b19 +Version: 20260601.4a231f4 Release: 0 Summary: RPM macros for building of Python modules License: WTFPL ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.PgAH0w/_old 2026-06-29 17:28:24.578052344 +0200 +++ /var/tmp/diff_new_pack.PgAH0w/_new 2026-06-29 17:28:24.582052480 +0200 @@ -1,6 +1,6 @@ -mtime: 1773745345 -commit: fe96fa02e9c616e0bc10b65be65697ad77d76106d7573d398678920d3152e7b0 -url: https://src.opensuse.org/python-interpreters/python-rpm-macros.git -revision: fe96fa02e9c616e0bc10b65be65697ad77d76106d7573d398678920d3152e7b0 +mtime: 1780582890 +commit: a5066d706e6cc04522775fd3ad65060e2d63bdb2ba625e95ee3ff33b16f9c6b9 +url: https://src.opensuse.org/python-interpreters/python-rpm-macros +revision: a5066d706e6cc04522775fd3ad65060e2d63bdb2ba625e95ee3ff33b16f9c6b9 projectscmsync: https://src.opensuse.org/python-interpreters/_ObsPrj ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.PgAH0w/_old 2026-06-29 17:28:24.618053702 +0200 +++ /var/tmp/diff_new_pack.PgAH0w/_new 2026-06-29 17:28:24.622053838 +0200 @@ -3,6 +3,5 @@ <param name="url">git://github.com/openSUSE/python-rpm-macros.git</param> <param name="changesrevision">80d37568d9732beb7fcc2cf27c5c08f9c01fade1</param></service><service name="tar_scm"> <param name="url">https://github.com/openSUSE/python-rpm-macros.git</param> - <param name="changesrevision">5e02b19cd89f4e6a0318939bcce4207ddf5751fc</param></service></servicedata> -(No newline at EOF) + <param name="changesrevision">4a231f4b9d4306c41f713ef31c60793e2c1729c8</param></service></servicedata> ++++++ build.specials.obscpio ++++++ --- old/.gitignore 2026-03-17 12:12:26.000000000 +0100 +++ new/.gitignore 2026-06-04 16:21:30.000000000 +0200 @@ -1 +1,9 @@ +.assets +_build.* +*.obscpio +*.obsinfo .osc +.pbuild +_service:* +python-rpm-macros-*-build/ +python-rpm-macros/ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-06-04 16:21:30.000000000 +0200 @@ -0,0 +1,9 @@ +.assets +_build.* +*.obscpio +*.obsinfo +.osc +.pbuild +_service:* +python-rpm-macros-*-build/ +python-rpm-macros/ ++++++ python-rpm-macros-20260317.5e02b19.tar.xz -> python-rpm-macros-20260601.4a231f4.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-rpm-macros-20260317.5e02b19/README.md new/python-rpm-macros-20260601.4a231f4/README.md --- old/python-rpm-macros-20260317.5e02b19/README.md 2026-03-17 11:59:55.000000000 +0100 +++ new/python-rpm-macros-20260601.4a231f4/README.md 2026-06-01 12:23:34.000000000 +0200 @@ -1,7 +1,8 @@ # Multi-Python, Single-Spec Macro System -This repository contains a work-in-progress macro system generator for the singlespec Python initiative. -The macro system can be used in spec files for building RPM packages. +This repository contains a work-in-progress macro system generator for +the singlespec Python initiative. The macro system can be used in spec +files for building RPM packages. The purpose of the singlespec system is to take a package for a particular flavor, and autogenerate subpackages for all the other flavors. @@ -11,7 +12,7 @@ __``<flavor>``__ is a kind of python interpreter. At this point, we recognize the following flavors: `python2`, `python3`, `python38`, `python39`, `python310`, `python311` and `pypy3`. `python3` points to the default of -coinstallable flavors `python3<M>` where `<M>` is the minor version number. The default is +co-installable flavors `python3<M>` where `<M>` is the minor version number. The default is specified not by python-rpm-macros but by the obs project definition in `%primary_python`. The flavor is used as a prefix for all flavor-specific macros. @@ -38,7 +39,7 @@ In some cases, it is only `modname` though. __pkgname__, or __subpackage name__, is internal to a spec file, and is that thing you put after -the `%package` macro. Pkgname of the package itself is an empty string. Pkgname of a +the `%package` macro. Pkgname of the package itself is an empty string. Pkgname of a `%package -n something` is at this point `-n something`, and denotes that this subpackage should not be handled by the generator. That means, if you want a subpackage to be skipped, rename it from `%package foo` to `%package -n %{name}-foo`. @@ -50,7 +51,7 @@ leaving the top-level package empty. Additionally it is possible for non-Python packages which define a subpackage -`%package -n python-modname` and corresponding `%description -n python-modname` etc., +`%package -n python-modname` and corresponding `%description -n python-modname` etc., to autogenerate all desired flavor subpackages `<flavor>-modname`. ### Build Set @@ -72,245 +73,348 @@ The following macros are considered public API: -* __`%system_python`__ - flavor that is used for generic unflavored `%python_` macros. +#### `%system_python` + +Flavor that is used for generic unflavored `%python_` macros. Currently set to `python2`. -* __`%python_for_executables`__ - flavor that is used for installing executables into `%_bindir` and +#### `%python_for_executables` + +Flavor that is used for installing executables into `%_bindir` and other files in non-flavor-specific locations. By default, set to `python3`. -* __`%pythons`__ - the build set. See above for details. +#### `%pythons` + +Current build set. See above for details. -* __`%have_<flavor>`__. Defined as 1 if the flavor is present in the build environment. - Undefined otherwise. +#### `%have_<flavor>` + +Defined as 1 if the flavor is present in the build environment. +Undefined otherwise. _Note:_ "present in build environment" does not mean "part of build set". Under some - circumstances, you can get a Python flavor pulled in through dependencies, even if you exclude it - from the build set. In such case, `%have_<flavor>` will be defined but packages will not be + circumstances, you can get a Python flavor pulled in through dependencies, even if you exclude it + from the build set. In such case, `%have_<flavor>` will be defined but packages will not be generated for it. -* __`%skip_<flavor>`__. Undefined by default. Define in order to exclude a flavor from build set. +#### `%skip_<flavor>` + +Undefined by default. Define in order to exclude a flavor from build set. _Note:_ You do not need to define `%skip_python2` for Tumbleweed. Only define, if you need to skip it for older distributions. -* __`%{python_module modname args}`__ expands to `(<flavor>-modname args)` for every - flavor. Intended as: `BuildRequires: %{python_module foo >= version}`. Supports - [rpm boolean dependencies](https://rpm.org/user_doc/boolean_dependencies.html). - If the package needs a module only for a specific Python version, you can use the special pseudo-macro - `%python` for expansion of the python-flavor within the requirement, e.g. - `BuildRequires: %{python_module python-aiocontextvars >= 0.2.2 if %python-base < 3.7}`. - (Don't define `%python` anywhere else.) +#### `%{python_module modname args}` -* __`%{python_dist_name modname}`__. Given a standardized name (i.e. dist name, name on PyPI) of `modname`, +It expands to `(<flavor>-modname args)` for every flavor. Intended as: +`BuildRequires: %{python_module foo >= version}`. Supports [rpm boolean +dependencies](https://rpm.org/user_doc/boolean_dependencies.html). If +the package needs a module only for a specific Python version, you can +use the special pseudo-macro `%python` for expansion of the +python-flavor within the requirement, e.g. `BuildRequires: +%{python_module python-aiocontextvars >= 0.2.2 if %python-base < 3.7}`. +(Don't define `%python` anywhere else.) + +#### `%{python_dist_name modname}` + +Given a standardized name (i.e. dist name, name on PyPI) of `modname`, it will convert it to a canonical format. -* __`%{python2_dist modname}`__. Given a standardized name (i.e. dist name, name on PyPI) of `modname`, +#### `%{python2_dist modname}` + +Given a standardized name (i.e. dist name, name on PyPI) of `modname`, it will convert it to a canonical format, and evaluates to python2.Ydist(CANONICAL_NAME), which is useful when listing dependencies. Intended as `(Build)Requires: %{python2_dist foo}`. -* __`%{python3_dist modname}`__. Given a standardized name (i.e. dist name, name on PyPI) of `modname`, +#### `%{python3_dist modname}` + +Given a standardized name (i.e. dist name, name on PyPI) of `modname`, it will convert it to a canonical format, and evaluates to python3.Ydist(CANONICAL_NAME), which is useful when listing dependencies. Intended as `(Build)Requires: %{python3_dist foo}`. -* __`%python_flavor`__ expands to the `%pythons` entry that is currently being processed. -Does not apply in `%prep`, `%build`, `%install` and `%check` sections. For those, check for the -pseudo-shell variable expansion of `$python` and `$python_flavor` inside the `%python_expand` macro -(see [Flavor expansion](#flavor-expansion)). +#### `%python_flavor` -* __`%python_subpackages`__ expands to the autogenerated subpackages. This should go at the end of the -main headers section. +The macro expands to the `%pythons` entry that is currently being +processed. Does not apply in `%prep`, `%build`, `%install` and `%check` +sections. For those, check for the pseudo-shell variable expansion of +`$python` and `$python_flavor` inside the `%python_expand` macro (see +[Flavor expansion](#flavor-expansion)). -* __`%python_subpackage_only`__. Undefined by default. If you want to generate `<flavor>-modname` -subpackages for a non-python main package, make sure to `%define python_subpackage_only 1` before -`%python_subpackages` and use `-n python-modname` for section headers (except for `%files`, see below). +#### `%python_subpackages` -* __`%python_enable_dependency_generator`__ expands to a define to enable automatic requires generation -of Python module dependencies using egg-info/dist-info metadata. This should go above the -`%python_subpackages` macro, preferably closer to the top of the spec. Intended usage: -`%{?python_enable_dependency_generator}`. This macro will eventually be removed when the generator -is configured to automatically run, hence the `?` at the beginning of the macro invocation. +The main work macro, which expands to the autogenerated subpackages. +This should go at the end of the main headers section. +#### `%python_subpackage_only` -#### Conditionals +Undefined by default. If you want to generate `<flavor>-modname` +subpackages for a non-python main package, make sure to `%define +python_subpackage_only 1` before `%python_subpackages` and use `-n +python-modname` for section headers (except for `%files`, see below). -These are shortcuts for `%if "%python_flavor" == "<flavor>"`. Due to how RPM evaluates the -shortcuts, they will fail when nested with other `%if` conditions. If you need to nest your -conditions, use the full `%if "%python_flavor"` spelling. +#### `%python_enable_dependency_generator` -* __`%if<flavor>`__: applies the following section only to subpackages of that particular flavor. +It expands to a definition enabling automatic requires generation of +Python module dependencies using egg-info/dist-info metadata. This +should go above the `%python_subpackages` macro, preferably closer to +the top of the spec. Intended usage: +`%{?python_enable_dependency_generator}`. This macro will eventually be +removed when the generator is configured to automatically run, hence the +`?` at the beginning of the macro invocation. -* __`%ifpycache`__: applies the following section only to subpackages of flavors that generate a -`__pycache__` directory. -* __`%<flavor>_only`__: applies the contents of the line only to subpackages of that particular flavor. +### Conditionals -* __`%pycache_only`__: applies the contents of the line only to subpackages of flavors that generate -`__pycache__` directories. Useful in filelists: `%pycache_only %{python_sitelib}/__pycache__/*` +These are shortcuts for `%if "%python_flavor" == "<flavor>"`. Due to how +RPM evaluates the shortcuts, they will fail when nested with other `%if` +conditions. If you need to nest your conditions, use the full `%if +"%python_flavor"` spelling. +#### `%if<flavor>` -#### Flavor expansion +It applies the following section only to subpackages of that particular +flavor. -The following macros expand to command lists for all flavors and move around the distutils-generated -`build` directory so that you are never running a `python39` command with a python310-generated `build` -and vice versa. +#### `%ifpycache` -##### General command expansion macros +It applies the following section only to subpackages of flavors that +generate a `__pycache__` directory. -* __`%python_exec something.py`__ expands to `$python something.py` for all flavors, where `$python` -is the basename of the flavor executable. Make sure it is in `$PATH`. +#### `%<flavor>_only` -* __`%python_expand something`__ is a more general form of the above. It performs rpm macro expansion - of its arguments for every flavor. Importantly, `$python` is not expanded by the shell, but replaced - beforehand for the current flavor, even in macros: +It applies the contents of the line only to subpackages of that +particular flavor. - - When used as command delimited by space or one of `"'\)&|;<>`, it is replaced by the path to the executable. - - When used as part of a macro name or other string, it is replaced by the current flavor name. +#### `%pycache_only` - So: - `%python_expand $python generatefile.py %{$python_sitelib}` - expands to: +It applies the contents of the line only to subpackages of flavors that +generate `__pycache__` directories. Useful in filelists: `%pycache_only +%{python_sitelib}/__pycache__/*` - ``` - python3.8 generatefile.py /usr/lib/python3.8/site-packages - python3.9 generatefile.py /usr/lib/python3.9/site-packages - python3.10 generatefile.py /usr/lib/python3.10/site-packages - ``` - etc. (plus the moving around of the `build` directory in between). +### Flavor expansion - If you want to check for the current python flavor inside `%python_expand`, either use the shell variale - `${python_flavor}` (not `$python_flavor`, `%{python_flavor}` or `%{$python_flavor}`), or append a suffix, - which is not one of the recognized delimiters listed above: +The following macros expand to command lists for all flavors and move +around the distutils-generated `build` directory so that you are never +running a `python39` command with a python310-generated `build` and vice +versa. - ```spec - %{python_expand # expanded-body: - if [ ${python_flavor} = python310 ]; then - $python command-for-py-310-only - fi - echo "We have version %{$python_version}, because we are in $python_flavor." - echo "Cannot use %{$python_flavor} because it has not enough levels of expansion." - echo "And %{python_flavor} is expanded early to the global default." - if [ $python_ = python310_ ]; then - echo "A suffix_ works as intended." - fi - } - ``` +#### `%python_exec something.py` - which expands during the python39 flavor iteration to +It expands to `$python something.py` for all flavors, where `$python` is +the basename of the flavor executable. Make sure it is in `$PATH`. - ```sh - # (.. moving build dirs ..) - python_flavor=python39 - - # expanded-body: - if [ ${python_flavor} = python310 ]; then - python3.9 command-for-py-310-only - fi - echo "We have version 3.9, because we are in python39_flavor." - echo "Cannot use %{python39_flavor} because it has not enough levels of expansion." - echo "And python310 is expanded early to the global default." - if [ python39_ = python310_ ]; then - echo "A suffix_ works as intended." - fi - ``` +#### `%python_expand something` + +It is a more general form of the above. It performs rpm macro expansion +of its arguments for every flavor. Importantly, `$python` is not +expanded by the shell, but replaced beforehand for the current flavor, +even in macros: + +- When used as command delimited by space or one of `"'\)&|;<>`, it is + replaced by the path to the executable. +- When used as part of a macro name or other string, it is replaced by + the current flavor name. + +So: +`%python_expand $python generatefile.py %{$python_sitelib}` +expands to: + +``` +python3.8 generatefile.py /usr/lib/python3.8/site-packages +python3.9 generatefile.py /usr/lib/python3.9/site-packages +python3.10 generatefile.py /usr/lib/python3.10/site-packages +``` - and so on for all flavors. +etc. (plus the moving around of the `build` directory in between). -##### Install macros +If you want to check for the current python flavor inside +`%python_expand`, either use the shell variale `${python_flavor}` (not +`$python_flavor`, `%{python_flavor}` or `%{$python_flavor}`), or +append a suffix, which is not one of the recognized delimiters listed +above: -* __`%pyproject_wheel`__ expands to - [PEP517](https://www.python.org/dev/peps/pep-0517)/[PEP518](https://www.python.org/dev/peps/pep-0518/) - build instructions for all flavors, creates wheels and places them into the flavor's `./build/` directories - (specified by `%_pyproject_wheeldir`). In case of pure wheels only one wheel is created by the first flavor, - placed into `./dist/` (`%_pyproject_anywheeldir`) and copied over to `%_pyproject_wheeldir` for all other - flavors. +```spec +%{python_expand # expanded-body: +if [ ${python_flavor} = python310 ]; then + $python command-for-py-310-only +fi +echo "We have version %{$python_version}, because we are in $python_flavor." +echo "Cannot use %{$python_flavor} because it has not enough levels of expansion." +echo "And %{python_flavor} is expanded early to the global default." +if [ $python_ = python310_ ]; then + echo "A suffix_ works as intended." +fi +} +``` -* __`%pyproject_install [wheelfile]`__ expands to install instructions for all flavors to install the created wheels. - You can also use this without `%pyproject_wheel`, if you place a pre-existing wheel into the current working dir - (deprecated), the `build/` directory of the current flavor (what `%pyproject_wheel` does), or specify - the path to the wheel file explicitly as argument to the macro (preferred), e.g `%pyproject_install %{SOURCE0}`. +which expands during the python39 flavor iteration to -* __`%python_compileall`__ precompiles all python source files in `%{python_sitelib}` and `%{python_sitearch}` -for all flavors. Generally Python 2 creates the cached byte-code `.pyc` files directly in the script directories, while -newer flavors generate `__pycache__` directories. Use this if you have modified the source files in `%buildroot` after -`%python_install` or `%pyproject_install` has compiled the files the first time. +```sh +# (.. moving build dirs ..) +python_flavor=python39 -* __`%python_build`__ expands to distutils/setuptools build instructions for all flavors using `setup.py`. +# expanded-body: +if [ ${python_flavor} = python310 ]; then + python3.9 command-for-py-310-only +fi +echo "We have version 3.9, because we are in python39_flavor." +echo "Cannot use %{python39_flavor} because it has not enough levels of expansion." +echo "And python310 is expanded early to the global default." +if [ python39_ = python310_ ]; then + echo "A suffix_ works as intended." +fi +``` -* __`%python_install`__ expands to legacy distutils/setuptools install instructions for all flavors using `setup.py`. - Note that `python setup.py install` has been deprecated by setuptools and distutils is deprecated entirely. - Consider using the PEP517 install procedure using the `%pyproject_*` macros if the package sources support it. +and so on for all flavors. -* __`%python_clone filename`__ creates a copy of `filename` under a flavor-specific name for every -flavor. This is useful for packages that install unversioned executables: `/usr/bin/foo` is copied -to `/usr/bin/foo-%{python_bin_suffix}` for all flavors, and the shebang is modified accordingly. -__`%python_clone -a filename`__ will also invoke __`%prepare_alternative`__ with the appropriate -arguments or create the libalternative configuration if `--with libalternatives` is specified. +### Install macros -* __`%python_find_lang foo`__ calls `%find_lang foo` for all flavors and creates flavor specific - files `%{python_prefix}-foo.lang`. Additional arguments of `%find_lang` are supported. The filelist - can then be used as `%files %{python_files} -f %{python_prefix}-foo.lang` in the `%files` section header. +#### `%pyproject_wheel` +It expands to +[PEP517](https://www.python.org/dev/peps/pep-0517)/[PEP518](https://www.python.org/dev/peps/pep-0518/) +build instructions for all flavors, creates wheels and places them into +the flavor's `./build/` directories (specified by +`%_pyproject_wheeldir`). In case of pure wheels only one wheel is +created by the first flavor, placed into `./dist/` +(`%_pyproject_anywheeldir`) and copied over to `%_pyproject_wheeldir` +for all other flavors. -##### Unit testing +#### `%pyproject_install [wheelfile]` -* __`%pytest`__ runs `pytest` in all flavors with appropriate environmental variables -(namely, it sets `$PYTHONPATH` to ``%{$python_sitelib}``). All paramteres to this macro are -passed without change to the pytest command. Explicit `BuildRequires` on `%{python_module pytest}` -is still required. +It expands to install instructions for all flavors to install the +created wheels. You can also use this without `%pyproject_wheel`, if you +place a pre-existing wheel into the current working dir (deprecated), +the `build/` directory of the current flavor (what `%pyproject_wheel` +does), or specify the path to the wheel file explicitly as argument to +the macro (preferred), e.g `%pyproject_install %{SOURCE0}`. -* __`%pytest_arch`__ the same as the above, except it sets ``$PYTHONPATH`` to ``%{$python_sitearch}``. +#### `%python_compileall` -* __`%pyunittest`__ and __`%pyunittest_arch`__ run `$python -m unittest` on all flavors with +The macro precompiles all python source files in `%{python_sitelib}` and +`%{python_sitearch}` for all flavors. Generally Python 2 creates the +cached byte-code `.pyc` files directly in the script directories, while +newer flavors generate `__pycache__` directories. Use this if you have +modified the source files in `%buildroot` after `%python_install` or +`%pyproject_install` has compiled the files the first time. + +#### `%python_build` + +It expands to distutils/setuptools build instructions for all flavors +using `setup.py`. + +#### `%python_install` + +It expands to legacy distutils/setuptools install instructions for all +flavors using `setup.py`. Note that `python setup.py install` has been +deprecated by setuptools and distutils is deprecated entirely. Consider +using the PEP517 install procedure using the `%pyproject_*` macros if +the package sources support it. + +#### `%python_clone filename` + +The macro creates a copy of `filename` under a flavor-specific name for +every flavor. This is useful for packages that install unversioned +executables: `/usr/bin/foo` is copied to +`/usr/bin/foo-%{python_bin_suffix}` for all flavors, and the shebang is +modified accordingly. __`%python_clone -a filename`__ will also invoke +__`%prepare_alternative`__ with the appropriate arguments or create the +libalternative configuration if `--with libalternatives` is specified. + +#### `%python_find_lang foo` + +It calls `%find_lang foo` for all flavors and creates flavor specific +files `%{python_prefix}-foo.lang`. Additional arguments of `%find_lang` +are supported. The filelist can then be used as `%files %{python_files} +-f %{python_prefix}-foo.lang` in the `%files` section header. + + +### Unit testing + +#### `%pytest` + +It runs `pytest` in all flavors with appropriate environmental variables +(namely, it sets `$PYTHONPATH` to ``%{$python_sitelib}``). All +paramteres to this macro are passed without change to the pytest +command. Explicit `BuildRequires` on `%{python_module pytest}` is still +required. + +#### `%pytest_arch` + +It is the same as the above, except it sets ``$PYTHONPATH`` to +``%{$python_sitearch}``. + +#### `%pyunittest`__ and __`%pyunittest_arch` + +It runs `$python -m unittest` on all flavors with appropriate environmental variables very similar to `%pytest` and `%pytest_arch`. -#### Alternative-related, general: +### Alternative-related, general: -* __`%prepare_alternative [-t <targetfile> ] <name>`__ replaces `<targetfile>` with a symlink to -`/etc/alternatives/<name>`, plus related housekeeping. If no `<targetfile>` is given, it is +#### `%prepare_alternative [-t <targetfile> ] <name>` + +It replaces `<targetfile>` with a symlink to `/etc/alternatives/<name>`, +plus related housekeeping. If no `<targetfile>` is given, it is `%{_bindir}/<name>`. -* __`%install_alternative [-n ]<name> [-s <sourcefile>] [-t ]<targetfile> [-p ]<priority>`__ runs the -`update-alternative` command, configuring `<sourcefile>` alternative to be `<targetfile>`, with a -priority `<priority>`. If no `<sourcefile>` is given, it is `%{_bindir}/<name>`. Can be followed by +#### `%install_alternative [-n ]<name> [-s <sourcefile>] [-t ]<targetfile> [-p ]<priority>` + +It runs the `update-alternative` command, configuring `<sourcefile>` +alternative to be `<targetfile>`, with a priority `<priority>`. If no +`<sourcefile>` is given, it is `%{_bindir}/<name>`. Can be followed by additional arguments to `update-alternatives`, such as `--slave`. -* __`%uninstall_alternative [-n ]<name> [-t ]<targetfile>`__ if uninstalling (not upgrading) the -package, remove `<targetfile>` from a list of alternatives under `<name>` +#### `%uninstall_alternative [-n ]<name> [-t ]<targetfile>` -* __`%alternative_to <file>`__ generates a filelist entry for `<file>` and a ghost entry for +If uninstalling (not upgrading) the package, remove `<targetfile>` from +a list of alternatives under `<name>` + +#### `%alternative_to <file>` + +The macro generates a filelist entry for `<file>` and a ghost entry for `basename <file>` in `/etc/alternatives` -#### Alternative-related, for Python: +### Alternative-related, for Python: + +#### `%python_alternative <file>` -* __`%python_alternative <file>`__: expands to filelist entries for `<file>`, its symlink in -`/etc/alternatives`, and the target file called `<file>-%python_bin_suffix`. -In case the file is a manpage (`file.1.gz`), the target is called `file-%suffix.1.gz`. - -* __`%python_install_alternative <name> [<name> <name>...]`__: runs `update-alternatives` -for `<name>-%{python_bin_suffix}` (unless `--with libalternatives` is enabled). -If more than one argument is present, the remaining ones are converted to `--slave` arguments. -If a `name` is in the form of `something.1` or `something.4.gz` (any number applies), it is -handled as a manpage and assumed to live in the appropriate `%{_mandir}` subdirectory, otherwise -it is handled as a binary and assumed to live in `%{_bindir}`. You can also supply a full path -to override this behavior. - -* __`%python_uninstall_alternative <name>`__: reverse of the preceding. -Note that if you created a group by specifying multiple arguments to `install_alternative`, only -the first one applies for `uninstall_alternative`. +It expands to filelist entries for `<file>`, its symlink in +`/etc/alternatives`, and the target file called +`<file>-%python_bin_suffix`. In case the file is a manpage +(`file.1.gz`), the target is called `file-%suffix.1.gz`. + +#### `%python_install_alternative <name> [<name> <name>...]` + +It runs `update-alternatives` for `<name>-%{python_bin_suffix}` (unless +`--with libalternatives` is enabled). If more than one argument is +present, the remaining ones are converted to `--slave` arguments. If +a `name` is in the form of `something.1` or `something.4.gz` (any number +applies), it is handled as a manpage and assumed to live in the +appropriate `%{_mandir}` subdirectory, otherwise it is handled as +a binary and assumed to live in `%{_bindir}`. You can also supply a full +path to override this behavior. + +#### `%python_uninstall_alternative <name>` + +It is the reverse of the preceding. Note that if you created a group by +specifying multiple arguments to `install_alternative`, only the first +one applies for `uninstall_alternative`. Each of these has a flavor-specific spelling: `%python2_alternative` etc. -#### Libalternatives-related: +### Libalternatives-related: -[Libalternatives](https://github.com/openSUSE/libalternatives) provides another way for settings alternative. -Instead of symlinks, the preferred executable is executed directly. Which executable is executed -depends on the available alternatives installed on the system and the system and/or user configuration files. -These configuration files will also be generated by the macros described above **AND** following settings in the -spec file: +[Libalternatives](https://github.com/openSUSE/libalternatives) provides +another way for settings alternative. Instead of symlinks, the preferred +executable is executed directly. Which executable is executed depends on +the available alternatives installed on the system and the system and/or +user configuration files. These configuration files will also be +generated by the macros described above **AND** following settings in +the spec file: * Enable *libalternative* by making __`--with libalternatives`__ the default: ```spec @@ -364,124 +468,187 @@ add the `%python_alternative_conf` line to make sure that alternatives for `bpython-config.5` man are packaged correctly. -#### Building and testing with flavored alternatives +### Building and testing with flavored alternatives + +#### `%python_flavored_alternatives` + +If a build tool or a test suite calls commands, which exist in several +alternatives, and you need them to call the command in the alternative +of the current flavor within an `%python_expand` block, this macro -* __`%python_flavored_alternatives`__: If a build tool or a test - suite calls commands, which exist in several alternatives, and - you need them to call the command in the alternative of the - current flavor within an `%python_expand` block, this macro - - - creates the appropriate update-alternatives symlinks in the - shuffled `build/flavorbin` directory and sets `$PATH` - accordingly, and - - selects the libalternatives priority of all installed commands - with a `libalternatives.conf` in - `XDG_CONFIG_HOME=$PWD/build/xdgflavorconfig`. +- creates the appropriate update-alternatives symlinks in the + shuffled `build/flavorbin` directory and sets `$PATH` + accordingly, and +- selects the libalternatives priority of all installed commands + with a `libalternatives.conf` in + `XDG_CONFIG_HOME=$PWD/build/xdgflavorconfig`. - The `%pytest(_arch)` and `%pyunittest(_arch)` macros include a call - of this macro before expanding to the test suite execution. +The `%pytest(_arch)` and `%pyunittest(_arch)` macros include a call +of this macro before expanding to the test suite execution. -#### Flavor-specific macros +### Flavor-specific macros In addition, the following flavor-specific macros are known and supported by the configuration: -* __`%__<flavor>`__: path to the ``<flavor>`` executable. +#### `%__<flavor>` + +The path to the ``<flavor>`` executable. + +#### `%<flavor>_pyproject_wheel` + +It expands to PEP517 instructions to build a wheel using the particular flavor. + +#### `%<flavor>_pyproject_install` -* __`%<flavor>_pyproject_wheel`__ expands to PEP517 instructions to build a wheel using the particular flavor. +It expands to PEP517 install instructions for the particular flavor. -* __`%<flavor>_pyproject_install`__ expands to PEP517 install instructions for the particular flavor. +#### `%<flavor>_build` -* __`%<flavor>_build`__ expands to `setup.py` build instructions for the particular flavor. +It expands to `setup.py` build instructions for the particular flavor. -* __`%<flavor>_install`__ expands to legacy `setup.py` install instructions for the particular flavor. +#### `%<flavor>_install` -* __`%<flavor>_fix_shebang`__ rewrites the script interpreter line in python scripts - installed into `%_bindir` to use the particular flavor. In multi-flavor expansions - the call of this macro is not required, as the script interpreter line is already - taken care of by the alternatives setup `%python_clone -a`. +It expands to legacy `setup.py` install instructions for the particular flavor. -* __`%<flavor>_fix_shebang_path path`__ rewrites the script interpreter - line in python scripts installed into `path` to use the - particular flavor. A glob like `*` can be used in the path parameter - to fix the shebang for all files in a directory. +#### `%<flavor>_fix_shebang` -* __`%<flavor>_sitelib`, `%<flavor>_sitearch`__: path to noarch (purelib) and - arch-dependent `site-packages` (platlib) directory. +It rewrites the script interpreter line in python scripts installed into +`%_bindir` to use the particular flavor. In multi-flavor expansions the +call of this macro is not required, as the script interpreter line is +already taken care of by the alternatives setup `%python_clone -a`. -* __`%<flavor>_version`__: dotted major.minor version. `2.7` for CPython 2.7. +#### `%<flavor>_fix_shebang_path path` -* __`%<flavor>_version_nodots`__: concatenated major.minor version. `27` for CPython 2.7. +It rewrites the script interpreter line in python scripts installed into +`path` to use the particular flavor. A glob like `*` can be used in the +path parameter to fix the shebang for all files in a directory. -* __`%<flavor>_bin_suffix`__: what to put after -a binary name. Binaries for CPython are called `binary-%{python_version}`, for PyPy the name -is `binary-pp%{pypy3_version}` +#### `%<flavor>_sitelib`, `%<flavor>_sitearch` -* __`%<flavor>_prefix`__: prefix of the package name. `python` for old-style distros, `python2` for -new-style. For other flavors, the value is the same as flavor name. +The path to noarch (purelib) and arch-dependent `site-packages` +(platlib) directory. -For reasons of preferred-flavor-agnosticity, aliases `python_*` are available for all of these. +#### `%<flavor>_version` -We recognize `%py_ver`, `%py2_ver` and `%py3_ver` as deprecated spellings of `%<flavor>_version`. No -such shortcut is in place for `pypy3`. Furthermore, `%py2_build`, `_install` and `_shbang_opts`, as +The dotted major.minor version. `2.7` for CPython 2.7. + +#### `%<flavor>_version_nodots` + +The concatenated major.minor version. `27` for CPython 2.7. + +#### `%<flavor>_bin_suffix` + +It is what to put after a binary name. Binaries for CPython are called +`binary-%{python_version}`, for PyPy the name is +`binary-pp%{pypy3_version}` + +#### `%<flavor>_prefix` + +It is the prefix of the package name. `python` for old-style distros, +`python2` for new-style. For other flavors, the value is the same as +flavor name. + +For reasons of preferred-flavor-agnosticity, aliases `python_*` are +available for all of these. + +We recognize `%py_ver`, `%py2_ver` and `%py3_ver` as deprecated +spellings of `%<flavor>_version`. No such shortcut is in place for +`pypy3`. Furthermore, `%py2_build`, `_install` and `_shbang_opts`, as well as `py3` variants, are recognized for Fedora compatibility. ### `%files` section -* __`%files %{python_files}`__ expands the `%files` section for all generated flavor packages of - `<flavor>-modname`. +#### `%files %{python_files}` + +It expands the `%files` section for all generated flavor packages of +`<flavor>-modname`. -* __`%files %{python_files foo}`__ expands the `%files` section for all generated flavor subpackages - of `<flavor>-modname-foo`. +#### `%files %{python_files foo}` + +It expands the `%files` section for all generated flavor subpackages of +`<flavor>-modname-foo`. For subpackages of non-python packages with `%python_subpackage_only`and `%package -n %{python_flavor}-modname`, also use `%files %{python_files modname}`. Always use the flavor-agnostic macro versions `%python_*` inside `%python_files` marked `%files` sections. -See also the Filelists section of the +See also the Filelists section of the [openSUSE:Packaging Python](https://en.opensuse.org/openSUSE:Packaging_Python#Filelists) guidelines ### Files in Repository -* __`macros` directory__: contains a list of files that are concatenated to produce the resulting -`macros.python_all` file. This directory is incomplete, files `020-flavor-$flavor` and -`040-automagic` are generated by running the compile script. +#### `macros` directory + +It contains a list of files that are concatenated to produce the +resulting `macros.python_all` file. This directory is incomplete, files +`020-flavor-$flavor` and `040-automagic` are generated by running the +compile script. + +#### `macros/001-alternatives` -* __`macros/001-alternatives`__: macro definitions for alternatives handling. These are not +The macro definitions for alternatives handling. These are not Python-specific and might find their way into `update-alternatives`. -* __`macros/010-common-defs`__: setup for macro spelling templates, common handling, preferred flavor -configuration etc. +#### `macros/010-common-defs` + +The setup for macro spelling templates, common handling, preferred +flavor configuration etc. + +#### `macros/030-fallbacks` -* __`macros/030-fallbacks`__: compatibility and deprecated spellings for some macros. +Compatibility and deprecated spellings for some macros. -* __`apply-macros.sh`__: compile macros and run `rpmspec` against first argument. Useful for examining -what is going on with your spec file. +#### `apply-macros.sh` -* __`buildset.in`__: template to generate `macros/040-buildset` for the `%pythons`, `%skip_<flavor>` and - `%python_module` macros. +It compiles macros and run `rpmspec` against first argument. Useful for +examining what is going on with your spec file. -* __`compile-macros.sh`__: the compile script. Builds flavor-specific macros, Lua script definition, +#### `buildset.in` + +This is the template to generate `macros/040-buildset` for the +`%pythons`, `%skip_<flavor>` and `%python_module` macros. + +#### `compile-macros.sh` + +The compile script. Builds flavor-specific macros, Lua script definition, and concatenates all of it into `macros.python_all`. -* __`flavor.in`__: template for flavor-specific macros. Generates `macros/020-flavor-<flavor>` for -every flavor listed in `compile-macros.sh`. +#### `flavor.in` + +The template for flavor-specific macros. Generates +`macros/020-flavor-<flavor>` for every flavor listed in +`compile-macros.sh`. + +#### `functions.lua` + +Lua function definitions used in `macros.lua` and elsewhere. In the +compile step, these are converted to a RPM macro `%_python_definitions`, +which is evaluated as part of `%_python_macro_init`. This can then be +called anywhere that we need a ready-made Lua environment. + +#### `macros.in` + +Pure-RPM-macro definitions for the single-spec generator. References and +uses the private Lua macros. The line `### LUA-MACROS ###` is replaced +with inlined Lua macro definitions. + +#### `macros.lua` + +Lua macro definitions for the single-spec generator. This is actually +pseudo-Lua: the top-level functions are not functions, and are instead +converted to Lua macro snippets. (That means that you can't call the +top-level functions from Lua. For defining pure Lua functions that won't +be available as Lua macros, use the `functions.lua` file.) + +#### `macros-default-pythons` + +The macro definitions for `%have_python2` and `%have_python3` for +systems where this is not provided by your Python installation. The spec +file uses this for SUSE <= Leap 42.3. `apply-macros` also uses it +implicitly (for now). -* __`functions.lua`__: Lua function definitions used in `macros.lua` and elsewhere. In the compile -step, these are converted to a RPM macro `%_python_definitions`, which is evaluated as part of -`%_python_macro_init`. This can then be called anywhere that we need a ready-made Lua environment. - -* __`macros.in`__: pure-RPM-macro definitions for the single-spec generator. References and uses the -private Lua macros. The line `### LUA-MACROS ###` is replaced with inlined Lua macro definitions. - -* __`macros.lua`__: Lua macro definitions for the single-spec generator. -This is actually pseudo-Lua: the top-level functions are not functions, and are instead converted to -Lua macro snippets. (That means that you can't call the top-level functions from Lua. For defining -pure Lua functions that won't be available as Lua macros, use the `functions.lua` file.) - -* __`macros-default-pythons`__: macro definitions for `%have_python2` and `%have_python3` for systems -where this is not provided by your Python installation. The spec file uses this for SUSE <= Leap 42.3. -`apply-macros` also uses it implicitly (for now). +#### `README.md` -* __`README.md`__: This file. As if you didn't know. +This file. As if you didn't know. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-rpm-macros-20260317.5e02b19/default-prjconf new/python-rpm-macros-20260601.4a231f4/default-prjconf --- old/python-rpm-macros-20260317.5e02b19/default-prjconf 2026-03-17 11:59:55.000000000 +0100 +++ new/python-rpm-macros-20260601.4a231f4/default-prjconf 2026-06-01 12:23:34.000000000 +0200 @@ -7,7 +7,7 @@ ## PYTHON MACROS BEGIN # order of %pythons is important: The last flavor overrides any operation on conflicting files and definitions during expansions, # making it the "default" in many cases --> keep the primary python3 provider at the end. -%pythons %{?!skip_python3:%{?!skip_python311:python311} %{?!skip_python312:python312} %{?!skip_python313:python313}} +%pythons %{?!skip_python3:%{?!skip_python311:python311} %{?!skip_python314:python314} %{?!skip_python313:python313}} %add_python() %{expand:%%define pythons %1 %pythons} %_without_python2 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-rpm-macros-20260317.5e02b19/flavor.in new/python-rpm-macros-20260601.4a231f4/flavor.in --- old/python-rpm-macros-20260317.5e02b19/flavor.in 2026-03-17 11:59:55.000000000 +0100 +++ new/python-rpm-macros-20260601.4a231f4/flavor.in 2026-06-01 12:23:34.000000000 +0200 @@ -15,15 +15,12 @@ %#FLAVOR#_bin_suffix %{?!_#FLAVOR#_bin_suffix:%#FLAVOR#_version}%{?_#FLAVOR#_bin_suffix} -# Check if there is a major version symlink to our flavor in the current build system. If so, we are the primary provider. -%#FLAVOR#_provides %(provides=""; \ -for flavorbin in %{_bindir}/python?; do \ - if [ $flavorbin != %__#FLAVOR# -a $(realpath $flavorbin) = %__#FLAVOR# ]; then \ - provides="$provides $(basename $flavorbin)"; \ - fi; \ -done; \ -echo ${provides# }; \ -) +# The primary Python flavor provides the unversioned python3 name. +%#FLAVOR#_provides %{lua: \ +if "#FLAVOR#" == rpm.expand("%{primary_python}") then \ + print("python3") \ +end \ +} %if#FLAVOR# %if "%{python_flavor}" == "#FLAVOR#"
