GithubHelp home page GithubHelp logo

python-rpm-macros's Introduction

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.

The purpose of the singlespec system is to take a package for a particular flavor, and autogenerate subpackages for all the other flavors.

Terminology

<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 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. Some macros are redefined with "short" flavor for compatibility reasons, such as py3 for python3. All of them have a "long" form too.

For compatibility reasons you see sometimes python. In most places, using python is either a redefinition of python2, or an alternative for "flavor-agnostic". Conditionals are in place to switch python to mean python3 in the future.

The name of the binary in %_bindir (/usr/bin) is the name of the flavor with an addtional . between the major and minor version number, in case the latter is part of the flavor name:

  • /usr/bin/python2
  • /usr/bin/python3
  • /usr/bin/python3.8
  • /usr/bin/python3.10
  • ...

modname is the PyPI name, or, if the package in question is not on PyPI, the moniker that we chose to stand in for it.

Packages adhering to the SUSE Python module naming policy are usually called <flavor>-modname. 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 %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.

The purpose of the singlespec system is to take a package called <flavor>-modname for a particular flavor, and autogenerate subpackages for all the other flavors.

Alternately, it is to take package python-modname and generate subpackages for all flavors, 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., to autogenerate all desired flavor subpackages <flavor>-modname.

Build Set

The default build set is listed in the %pythons macro. Every entry in %pythons generates a requirement in %python_module, a subpackage from %python_subpackages (unless the top-level spec file is for that flavor), and an additional run of loops like %python_build, _install, _exec and _expand.

To control the build set, you can either completely redefine %pythons, or exclude particular flavor(s) by defining %skip_<flavor>. For example, if you %define skip_python2 1, then Python 2 will be excluded from the default build set. (Python 2 is not in the default build set of Tumbleweed and SLE/Leap >= 15.4)

Skip-macros are intended for per-package use only. Never define a skip-macro in prjconf or in any other sort of global config. Instead, redefine %pythons.

Macros

The following macros are considered public API:

  • %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 other files in non-flavor-specific locations. By default, set to python3.

  • %pythons - the build set. See above for details.

  • %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 generated for it.

  • %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. 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, 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, 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).

  • %python_subpackages expands to the autogenerated subpackages. This should go at the end of the main headers section.

  • %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_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.

Conditionals

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>: applies the following section only to subpackages of that particular flavor.

  • %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.

  • %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__/*

Flavor expansion

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.

General command expansion macros
  • %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.

  • %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:

    • 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
    

    etc. (plus the moving around of the build directory in between).

    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:

    %{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
    }

    which expands during the python39 flavor iteration to

    # (.. 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

    and so on for all flavors.

Install macros
  • %pyproject_wheel expands to PEP517/PEP518 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.

  • %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}.

  • %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.

  • %python_build expands to distutils/setuptools build instructions for all flavors using setup.py.

  • %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.

  • %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.

  • %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.

Unit testing
  • %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.

  • %pytest_arch the same as the above, except it sets $PYTHONPATH to %{$python_sitearch}.

  • %pyunittest and %pyunittest_arch run $python -m unittest on all flavors with appropriate environmental variables very similar to %pytest and %pytest_arch.

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 %{_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 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>

  • %alternative_to <file> generates a filelist entry for <file> and a ghost entry for basename <file> in /etc/alternatives

Alternative-related, for Python:

  • %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.

Each of these has a flavor-specific spelling: %python2_alternative etc.

Libalternatives-related:

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:

    %if 0%{?suse_version} > 1500
    %bcond_without libalternatives
    %else
    %bcond_with libalternatives
    %endif

    This example shows that libalternatives is available for TW only.

  • Require the alts package during build and runtime:

    %if %{with libalternatives}
    Requires:       alts
    BuildRequires:  alts
    %else
    Requires(post): update-alternatives
    Requires(postun):update-alternatives
    %endif
  • Group entries using %python_group_libalternatives (similar to what would have been installed as master and slaves in %python_install_alternatives, but without the manuals, as these do not go into group= entries)

    %install
    ...
    %python_clone -a %{buildroot}/%{_bindir}/cmd1
    %python_clone -a %{buildroot}/%{_binddir}/cmd2
    %python_clone -a %{buildroot}/%{_mandir}/man1/cmd1.1
    %python_group_libalternatives cmd1 cmd2
  • Cleanup old update-alternatives entries during a transition update to libalternatives:

    %pre
    # removing old update-alternatives entries
    %python_libalternatives_reset_alternative <name>

    The argument <name> is the same used for calling %python_uninstall_alternative.

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

    • 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.

Flavor-specific macros

In addition, the following flavor-specific macros are known and supported by the configuration:

  • %__<flavor>: path to the <flavor> executable.

  • %<flavor>_pyproject_wheel expands to PEP517 instructions to build a wheel using the particular flavor.

  • %<flavor>_pyproject_install expands to PEP517 install instructions for the particular flavor.

  • %<flavor>_build expands to setup.py build instructions for the particular flavor.

  • %<flavor>_install expands to legacy setup.py install instructions for the particular flavor.

  • %<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.

  • %<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>_sitelib, %<flavor>_sitearch: path to noarch (purelib) and arch-dependent site-packages (platlib) directory.

  • %<flavor>_version: dotted major.minor version. 2.7 for CPython 2.7.

  • %<flavor>_version_nodots: concatenated major.minor version. 27 for CPython 2.7.

  • %<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>_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.

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 foo} expands the %files section for all generated flavor subpackages of <flavor>-modname-foo.

For subpackages of non-python packages with %python_subpackage_onlyand %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 openSUSE:Packaging Python 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/001-alternatives: 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/030-fallbacks: 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.

  • buildset.in: 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.

  • 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: This file. As if you didn't know.

python-rpm-macros's People

Contributors

antlarr avatar bmwiedemann avatar bnavigator avatar conan-kudo avatar danigm avatar dcermak avatar dimstar77 avatar dirkmueller avatar jarus avatar manueljacob avatar matejcik avatar mcepl avatar meggycal avatar pgajdos avatar s-t-e-v-e-n-k avatar scarabeusiv avatar schubi2 avatar toabctl avatar tomschr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-rpm-macros's Issues

Implement macros for PEP 518 & PEP 517 build systems

See https://bugzilla.redhat.com/1685582 and there particularly links to https://discuss.python.org/t/pep-517-build-frontends-to-inform-users-about-wheel-basename/1026 and pypa/pip#6377

The first draft of proposed macros is

%pyproject_wheel: <flags...> %{__python3} -m pip wheel --no-deps --use-pep517 --no-build-isolation --progress-bar off --verbose .
+ conditional --global-option and --build-option based on %{?py_setup_args} and/or other macros.

%pyproject_install: %{__python3} -m pip install --root %{buildroot}  --strip-file-prefix %{buildroot} --no-deps  --progress-bar off *.whl

%pyx_compile problems when only one flavour is enabled

%py_compile and %py3_compile should disable themselves based on the have/skip rules.

Or maybe they should be used indirectly via something like %python_expand %{$python_compile} %{buildroot}%{$python_sitelib}

An example of the problem is
https://build.opensuse.org/package/show/devel:languages:python:flask/python-Flask-RESTful

When running a project config with only flavour python3, the use of %py_compile fails.

I havent been able to find a syntax which works at https://build.opensuse.org/package/show/home:jayvdb:py3only/python-Flask-RESTful

If it is possible, lets document it somewhere.

Error in libalternatives filelist produced by the %python_alternative macro

From Staging:N:

### [install check & file conflicts for x86_64]

found conflict of libalternatives-unit-test-helper-1.2+3.b848aad-2.1.x86_64 with python36-Babel-2.9.1-1.2.noarch
  /usr/share/libalternatives [mode mismatch: d755 root:root, d000 root:root]

found conflict of libalternatives-unit-test-helper-1.2+3.b848aad-2.1.x86_64 with python36-CherryPy-18.6.1-1.2.noarch
  /usr/share/libalternatives [mode mismatch: d755 root:root, d000 root:root]

found conflict of libalternatives-unit-test-helper-1.2+3.b848aad-2.1.x86_64 with python36-Flask-2.0.2-1.1.noarch
  /usr/share/libalternatives [mode mismatch: d755 root:root, d000 root:root]

...

I think you have to remove the %ghost from the /usr/share/libalternatives directory entries here:

print(rpm.expand("%ghost %dir %{_datadir}/libalternatives\\\n")) \
print(rpm.expand("%ghost %dir %{_datadir}/libalternatives/" .. name .. "\\\n")) \

@schubi2, @mcepl: Please implement and test. I don't have the time right now.

This issue blocking Staging:N and the current state of d:l:p* without the new python-rpm-macros required but not available is a suboptimal situation.

python to python-singlespec migration causes file conflicts

In a case we happen to have binary in _bindir we get a conflict later on:

found conflict of python-xmldiff-0.6.10-13.14.x86_64 with python3-xmldiff-2.3-199.1.noarch:

  • /usr/bin/xmldiff

This can be handled per package by all the variants adding:
Conflicts: %{oldpython}-whatever < %{version}-%{release}

Question is wether we should do it in macros or have it done individualy per package.

build loop does not execute additional commands

The way %install and %build are replaced to loop for building with Python 2 and Python 3 does not execute additional commands.

For example:

%install
%python_install
mkdir -p %{buildroot}%{python_sitelib}/foo

will result in mkdir being executed only once. Since Python 2 gets built first "foo" then happens to be in python2_sitelib.

PYTHONPATH fix breaks many packages

Some fallout from #45 (503823c):

While not adding an empty PYTHONPATH is certainly the correct way to do, a bunch of packages erroneously relied on it and need to be fixed. See all the failing python packages imported from Minimal... into Staging:B right now.

%pyproject* expansion also broken

More fallout from #45:

python-tox in Staging:B:

%install
export LANG=en_US.UTF8
%pyproject_install
[   21s] + LANG=en_US.UTF8
[   22s] + '%{python_expand' -mpip wheel --no-deps '%{?py_setup_args:--build-option' '%{py_setup_args}}' --use-pep517 --no-build-isolation --progress-bar off --verbose . '}'
[   22s] /var/tmp/rpm-tmp.5Qrc8M: line 34: fg: no job control

Create macro for python compile with multiversion in mind.

%if 0%{?have_python2} && ! 0%{?skip_python2}
%py_compile %{buildroot}%{python2_sitelib}/jaraco/
%py_compile -O %{buildroot}%{python2_sitelib}/jaraco/
%endif

%if 0%{?have_python3} && ! 0%{?skip_python3}
%py3_compile %{buildroot}%{python3_sitelib}/jaraco/
%py3_compile -O %{buildroot}%{python3_sitelib}/jaraco/
%endif

^ The above is way too hidious and we should create a wrapper that would do that with all pythons in mind.

PEP517/PEP518 macros for non-pure packages fail on undetected platforms

Axel Braun showed me this:
https://build.opensuse.org/package/live_build_log/devel:languages:python/python-pendulum/openSUSE_Tumbleweed/x86_64

%install
%pyproject_install
[   25s] + python3.6 -mpip install --root /home/abuild/rpmbuild/BUILDROOT/python-pendulum-2.1.2-14.34.x86_64 --disable-pip-version-check --no-compile --no-deps --progress-bar off pendulum-2.1.2-cp36-cp36m-manylinux_2_32_x86_64.whl pendulum-2.1.2-cp38-cp38-manylinux_2_32_x86_64.whl
[   25s] ERROR: pendulum-2.1.2-cp36-cp36m-manylinux_2_32_x86_64.whl is not a supported wheel on this platform.
[   25s] error: Bad exit status from /var/tmp/rpm-tmp.HOVHRk (%install)

%{$python_flavor}?

The Readme states:

%python_flavor expands to the %pythons entry that is currently being processed.
Does not apply in %prep, %build, %install and %check sections, except when evaluated as %{$python_flavor} in %python_expand.

That does not seem to hold true:

%python_expand echo %{$python_flavor} $python_flavor ${python_flavor} in either %prep or %build expands to:

[    6s] ++ '[' -f _current_flavor ']'
[    6s] ++ true
[    6s] + python_flavor=
[    6s] + '[' -z '' ']'
[    6s] + python_flavor=tmp
[    6s] + '[' tmp '!=' python3 ']'
[    6s] + '[' -d build ']'
[    6s] + '[' -d _build.python3 ']'
[    6s] + echo python3
[    6s] + echo '%{python3_flavor}' python3_flavor tmp
[    6s] %{python3_flavor} python3_flavor tmp

And in %install:

[   87s] ++ '[' -f _current_flavor ']'
[   87s] ++ cat _current_flavor
[   87s] + python_flavor=python3
[   87s] + '[' -z python3 ']'
[   87s] + '[' python3 '!=' python3 ']'
[   87s] + echo python3
[   87s] + echo '%{python3_flavor}' python3_flavor python3
[   87s] %{python3_flavor} python3_flavor python3

%have_<flavor> is not produced for non primary python3 flavors.

The README says:

%have_<flavor>. Defined as 1 if the flavor is present in the build environment. Undefined otherwise.

But the specfiles for the python interpreters do this:

# RPM macros
%if %{primary_interpreter}
mkdir -p %{buildroot}%{_rpmconfigdir}/macros.d/
install -m 644 %{SOURCE7} %{buildroot}%{_rpmconfigdir}/macros.d/ # macros.python3
%endif

And macros.python3 only has

%have_python3   1

So we never get %have_python38 and so on.

This needs to be fixed in the specfiles, as the these definitions are not from python-rpm-macros (unless 0%{?suse_version} < 1330 )

Latest Tumbleweed snapshot broke macros for python3 coinstall

TW snapshot 20210110 introduced rpm 4.16.0

Since then, Staging:N has a failure in python-zope.proxy:

%files %{python_files devel}
%dir %{python_sysconfig_path include}/zope.proxy
%{python_sysconfig_path include}/zope.proxy/*
%{python_sitearch}/zope/proxy/proxy.h
%endif
[   22s] Processing files: python36-zope.proxy-devel-4.3.5-0.x86_64
[   22s] error: Directory not found: /home/abuild/rpmbuild/BUILDROOT/python-zope.proxy-4.3.5-0.x86_64/zope.proxy
[   22s] error: File not found: /home/abuild/rpmbuild/BUILDROOT/python-zope.proxy-4.3.5-0.x86_64/zope.proxy/*
[   22s] 
[   22s] 
[   22s] RPM build errors:
[   22s]     Directory not found: /home/abuild/rpmbuild/BUILDROOT/python-zope.proxy-4.3.5-0.x86_64/zope.proxy
[   22s]     File not found: /home/abuild/rpmbuild/BUILDROOT/python-zope.proxy-4.3.5-0.x86_64/zope.proxy/*
[   22s] 
[   22s] greinerT450s failed "build python-zope.proxy.spec" at Mon Jan 11 21:11:12 UTC 2021.
[   22s] 

The buildroot was: /var/tmp/build-root/standard-x86_64
greiner@greinerT450s:~/src/osc/home:bnavigator:branches:openSUSE:Factory:Staging:N/python-zope.proxy/ > osc shell
abuild@greinerT450s:~> rpm --eval '%{python3_sysconfig_path include}'
/usr/include/python3.8
abuild@greinerT450s:~> rpm --eval '%{python36_sysconfig_path include}'
/usr/include/python3.6m
abuild@greinerT450s:~> rpm --eval '%{python38_sysconfig_path include}'
/usr/include/python3.8
abuild@greinerT450s:~> rpm --eval '%{python_sysconfig_path include}'
sh: line 0: fg: no job control

abuild@greinerT450s:~>

As the package in Factory and d:l:p builds fine (otherwise rpm would not have made it through Staging:A), there seems to be some problem with the new macros.

PYTHONPATH is not correctly expanded in %pytest_arch and %pytest

When is PYTHONPATH empty, it is incorrectly expanded with : and build fails.

Example from spec file:

%check
%pytest_arch

Result:

[3s] + PYTHONPATH=:/home/abuild/rpmbuild/BUILDROOT/python-iwlib-1.6.2-0.x86_64/usr/lib64/python2.7/site-packages

PYTHONPATH is starting with :.

Workaround from spec file:

%check
PYTHONPATH=something
%pytest_arch

Result of workaround:

[    4s] + PYTHONPATH=something:/home/abuild/rpmbuild/BUILDROOT/python-iwlib-1.6.2-0.x86_64/usr/lib64/python2.7/site-packages

Probably related to #29
Part PYTHONPATH=$PYTHONPATH:%{buildroot}%{$python_sitearch} on line:

%pytest_arch(+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=) %{lua: local args = rpm.expand("%**") print(rpm.expand("%{python_expand PYTHONPATH=$PYTHONPATH:%{buildroot}%{$python_sitearch} py.test-%{$python_bin_suffix} --ignore=_build.python2 --ignore=_build.python3 --ignore=_build.pypy3 -v " .. args .. "}")) }

Request to bring %python_compileall to python-rpm-macros

https://bugzilla.suse.com/show_bug.cgi?id=1189386

When implementing jsc#SLE-18648, we encounter a build problem that python-jupyter-core (required by graphical component) needs the mentioned macro to build. I tested the following commit should be enough for the requirement:

https://build.opensuse.org/package/view_file/home:yfjiang:home:yfjiang:gnome:stable41:infra/python-rpm-macros/db2f650ee3308f4bc0220ed43ed923773857b100.patch?expand=1

The bug is to request for a porting of the feature to sle-15-sp4:ga.

Provides: python3-foo for multiple python3 flavors

Some dumb questions, I am sure you have thought about this but I don't see anything in the macros:

This may eventually build fully for Staging:N. But when it goes into the Tumbleweed repository, what will happen for users? Won't all python3-foo packages cease to exist? Don't we need the python3?-foo packages have a Provides: and Obsoletes:, for distribution updates to work? And as a result of that, will the python36-foo and python38-foo create numerous "have choice" unresolvables in the openSUSE Build System and yast/zypper?

Originally posted by @bnavigator in #65 (comment)

python3 only is broken

The docs say that this:

%undefine have_python2

results in no python2 packages. It doesn't build, but the files are added nevertheless:

File not found: /home/abuild/rpmbuild/BUILDROOT/mypy-0.510-0.x86_64/usr/lib/python2.7/site-packages/*

No %python2_clone and %python3_clone

For most macros, there is a %python_foo version and a corresponding %python2_foo and %python3_foo version. The only exception I have noticed is %python_clone, which does not have a corresponding %python2_clone or %python3_clone. This would be useful in packages where the python2 and python3 versions have to be packaged separately (generally because the latest version is python3-only), but where we still have conflicting files between the two packages.

python_module from prjconf trumps everything.

Something I found out while trying to make #88 work inside the rpmbuild:

%python_module is defined multiple times:

  • In the prjconf (most of the time inherited from openSUSE:Factory)
  • a duplicate of it in buildset.in, written into 040-buildset
  • in macros.lua, written into 050-automagic

buildset.in has this comment:

# This method for generating python_modules gets too deep to expand at about 5 python flavors.
# It is replaced by a Lua macro in macros.lua

Line 3 is not true. The Lua macro from macros.lua is never called. %python_module is always using the code from the prjconf. It still works, because we are below "about 5 python flavors".

pypy3 bin suffixes

I have a working pypy3 v7.1.1, and am now putting it through its paces and tidying up.

https://build.opensuse.org/package/show/home:jayvdb:pypy/pypy3
https://build.opensuse.org/project/prjconf/home:jayvdb:pypy

Currently the packages are busted as I am working on the purelib/platlib problem, but it was doing ok. Previous set of working packages can be seen at

https://download.opensuse.org/repositories/home:/jayvdb:/pypy/openSUSE_Tumbleweed/noarch/

Besides the other "Python 3" only issues raised here recently, some of which effect pypy3 also (esp py_ver), the stand-out problem with pypy3 is that the "bin suffix" are sometimes pp3.6 and othertimes -3.6 , in the same build. So for the nose package, I added %{_bindir}/nosetests-3.6 to the %files as a hack to get it green.

I put "bin suffix" in quotes as I am not suggesting the bin_suffix macros have different values thoughout a single build - something else is likely at play. Possibly the clone macro is not using the bin suffix macro, or something like that.

-3.6 would definitely be wrong. pp3.6 is a bit odd, but it is as good a choice as any I suppose.

issues with %pythons definition for older openSUSE distributions

In an attempt to build python packages with %pythons build requirements, I tried to define this macro correctly, but failed so far.

  1. attempt:
    no %pythons definition results in: nothing provides %{pythons} for Leap 42.* and below

  2. attempt:

%if 0%{?suse_version} <= 1320
Macros:
%pythons %{?!skip_python2:python2} %{?!skip_python3:python3}
:Macros
%endif

results in: nothing provides python2 for 13.2 and 42.1, although python-base has /usr/bin/python2, but proably isn't providing it directly. While at it, an additional FileProvides: /usr/bin/python2 python-base doesn't cut it as well.

  1. attempt:
%if 0%{?suse_version} <= 1320
Macros:
%pythons %{?!skip_python2:python} %{?!skip_python3:python3}
:Macros
%endif

results in:

[   31s] + exec rpmbuild -ba --define '_srcdefattr (-,root,root)' --nosignature --define '_build_create_debug 1' --define 'disturl obs://build.opensuse.org/home:frispete:python-testing/openSUSE_13.2/0a3a43f2eb669db8996f9a1ec0207fae-python-hypothesis' /home/abuild/rpmbuild/SOURCES/python-hypothesis.spec
[   31s] error: Package already exists: %package -n python-hypothesis

That one is the most disturbing one. It looks like the %pythons macro interferes with %python_subpackages here for 13.2 and 42.1.

I'm running out of ideas right now. I can remove that requirement in the spec of course, or protect it with a conditional, but a proper fix would be preferable.

I've setup a test repo here, where I try to build python-hypothesis without manual intervention.

Any hints are much appreciated.

How to set environment variables for specific flavors?

I want to package a project that links against boost_python and uses the environment variable BOOST_PYTHON_LIB to determine the shared library to link against.

I tried using something like

%build
export CFLAGS="%{optflags}"
%if "%{python_flavor}" == "python2"
export BOOST_PYTHON_LIB="boost_python-py2_7"
%else
export BOOST_PYTHON_LIB="boost_python-py3"
%endif
%python_build

to build the package but the python3 version is linked against boost_python-py2_7. I guess that the if is only evaluated once and not in the %python_build loop.

How can I achieve a correct evaluation and exporting of environment variables for all flavors?

%pytest expansion broken

Now that the new version is in Staging:B, it breaks stuff:

package python-jedi:

%check
export PYTHONDONTWRITEBYTECODE=1
export LANG="en_US.UTF-8"
skiptests="test_venv_and_pths"
skiptests+=" or test_sqlite3_conversion"
# some architectures are too slow for these optimizer devel checks
skiptests+=" or test_speed"
# fails on some architectures
skiptests+=" or test_init_extension_module"
%if 0%{?suse_version} == 1500
  # the python 2 pytest test discovery in Leap 15 and SLE15
  # trips on purposely placed syntax errors in test/completion/imports.py
  %define pytestignore --ignore test/__init__.py
%endif
%pytest -k "not ($skiptests)" %{?pytestignore}

(Yes, I also realize now that explicit PYTHONDONTWRITEBYTECODE=1 is not necessary anymore as it is included into the macro now)

https://build.opensuse.org/request/show/816146

[   17s] + '%{python_expand' 'PYTHONPATH=%{buildroot}%{}' PYTHONDONTWRITEBYTECODE=1 'pytest-%{}' --ignore=_build.python2 --ignore=_build.python3 --ignore=_build.pypy3 -v -k 'not (test_venv_and_pths or test_sqlite3_conversion or test_speed or test_init_extension_module)}'
[   17s] /var/tmp/rpm-tmp.eeY0JZ: line 37: fg: no job control

Maybe #45?

Macros to compile files

Ideally recompiling python files shouldn't be necessary. However, with the new policy of requires python-specific shebangs, recompiling python files has become pretty common. So it would be great if there was a macro to handle that automatically.

pkg build issue on OBS, while fine when built locally

Hi Ben,

sorry for not being of any help with your ambitious multi flavor changes. I'm in the process of changing my primary job, and that limits my fun work significantly ATM.

Before start tackling projects with huge amounts of failing python packages, I decided to look at low hanging fruits, and here's (a good?) one: ptex build. Of course, I also tried to build against devel:languages:python:Factory/python-rpm-macros, but that didn't change the outcome. A local build is fine, while an OBS build fails with:

[   19s] + exec rpmbuild -ba --define '_srcdefattr (-,root,root)' --nosignature --define '_build_create_debug 1' --define 'disturl obs://build.opensuse.org/home:frispete:blender/openSUSE_Tumbleweed/e6bb4caa8d82415798a8b34c0ddb1357-ptex' /home/abuild/rpmbuild/SOURCES/ptex.spec
[   19s] setting SOURCE_DATE_EPOCH=1594252800
[   19s] error: Failed build dependencies:
[   19s] 	python36-packaging is needed by ptex-2.3.2-5.17.x86_64

Obviously, OBS fails to expand %{python_module packaging} correctly. In fact, not a single python36 package is pulled.

Do we really need to redefine %python_module in each and every prjconf somehow?

%python_uninstall_alternative not capable of manpages

%python_install_alternative can handle manpages fine:

> rpmspec -E '%python_install_alternative pyblake2.1'
update-alternatives --install /usr/share/man/man1/pyblake2.1.gz pyblake2.1.gz /usr/share/man/man1/pyblake2-2.7.1.gz 27

But %python_uninstall_alternative can't:

> rpmspec -E '%python_uninstall_alternative pyblake2.1'
if [ ! -e "/usr/bin/pyblake2.1-2.7" ]; then 
    update-alternatives --quiet --remove "pyblake2.1" "/usr/bin/pyblake2.1-2.7" 
fi 

It refers to /usr/bin/

pytest macros missing export on PYTHONPATH?

I just tried to use the %pytest_arch macro for the python-typed-ast package, but it failed with

[   37s] + PYTHONPATH=:/home/abuild/rpmbuild/BUILDROOT/python-typed-ast-1.4.1-0.x86_64/usr/lib64/python3.8/site-packages
[   37s] + PYTHONDONTWRITEBYTECODE=1
[   37s] + py.test-3.8 --ignore=_build.python2 --ignore=_build.python3 --ignore=_build.pypy3 -v
[   37s] ============================= test session starts ==============================
[   37s] platform linux -- Python 3.8.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/bin/python3
[   37s] cachedir: .pytest_cache
[   37s] rootdir: /home/abuild/rpmbuild/BUILD/typed_ast-1.4.1
[   38s] collecting ... collected 0 items / 1 error
[   38s] 
[   38s] ==================================== ERRORS ====================================
[   38s] __________________ ERROR collecting ast3/tests/test_basics.py __________________
[   38s] ImportError while importing test module '/home/abuild/rpmbuild/BUILD/typed_ast-1.4.1/ast3/tests/test_basics.py'.
[   38s] Hint: make sure your test modules/packages have valid Python names.
[   38s] Traceback:
[   38s] ast3/tests/test_basics.py:5: in <module>
[   38s]     from typed_ast import _ast3
[   38s] E   ImportError: cannot import name '_ast3' from 'typed_ast' (/home/abuild/rpmbuild/BUILD/typed_ast-1.4.1/typed_ast/__init__.py)
[   38s] !!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
[   38s] =============================== 1 error in 0.10s ===============================

However, executing the same commands with export PYTHONPATH=... works fine. Is this only a problem in this package or maybe in general?

.spec file names not handled in some cases

In OBS, .spec files can be named $package_container_name.spec.$repo_name. That needs to be handled. Otherwise the error is:

error: line 30: Unknown tag: bad spec python-debtcollector.spec

Python subpackages of other packages in custom Leap repos

This mailinglist post reports that using %if 0%{?python38_version_nodots} is not a viable method to check if we have multiflavor subpackage support.

It probably affects at least these packages, taken from #66 (comment):

package SR to devel project SR to Factory
libpfm sr#881352 sr#882196
miniupnpc sr#881353 sr#881375
net-snmp sr#881354 sr#891838
qpid-proton sr#881355 sr#881406
protobuf sr#881351 sr#881373
javapackages-tools-extras (python-javapackages) sr#881357 sr#881405
subunit sr#881358 sr#881374
gpgme sr#882036 sr#882039
gaupol : python-aeidon sr#881349 sr#881368
xapian-bindings sr#881359 no reaction in 2 months. server:search not affected because they do not inherit a recent version of python-rpm-macros

%python_module problems when flavors python2 and python3 are disabled

I have a hacky project conf which eliminates py2 from the project
https://build.opensuse.org/project/prjconf/home:jayvdb:py3only

The most obvious ugly side effect is py2-only packages become "unresolvable" (great!), but the reason is "nothing provides STOP-setuptools, nothing provides MACRO"
e.g.
https://build.opensuse.org/project/monitor/home:jayvdb:py3only?arch_x86_64=1&defaults=0&repo_openSUSE_Tumbleweed=1&unresolvable=1
currently bz2file, ipykernel & ipython

I guess the nothing provides STOP-setuptools is caused by https://github.com/openSUSE/python-rpm-macros/blob/d9968ab7b3c753a3cc82ec0b1d8fab1a249a09c1/buildset.in

%python_module_iter(a:) %{-a*}-%{args} %{expand:%%{?!python_module_iter_%1:%%{python_module_iter -a %*}}}
%python_module_iter_STOP stop
%python_module() %{expand:%%define args %{**}} %{expand:%%{python_module_iter -a %{pythons} STOP}}

If there isnt an easy way around that, I guess it could be made a bit prettier by replacing STOP with py0

"nothing provides MACRO" may be the same cause; i'm not sure.

%license marco not working

For OpenStack packaging, we use the %license macro (together with %_defaultlicensedir %_defaultdocdir ).
Building a package with that macro leads to:

...
[    1s] [6/131] keeping python-rpm-macros-2017.05.09.fc237de-45.1
...
[    3s] Processing files: python-oslosphinx-4.12.0-0.noarch
[    3s] Executing(%doc): /bin/sh -e /var/tmp/rpm-tmp.KoxhO9
[    3s] + umask 022
[    3s] + cd /home/abuild/rpmbuild/BUILD
[    3s] + cd oslosphinx-4.12.0
[    3s] + DOCDIR=/home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python-oslosphinx
[    3s] + export DOCDIR
[    3s] + /usr/bin/mkdir -p /home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python-oslosphinx
[    3s] + cp -pr README.rst /home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python-oslosphinx
[    3s] + exit 0
[    3s] Executing(%license): /bin/sh -e /var/tmp/rpm-tmp.QnqJd2
[    3s] + umask 022
[    3s] + cd /home/abuild/rpmbuild/BUILD
[    3s] + cd oslosphinx-4.12.0
[    3s] + LICENSEDIR=/home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python-oslosphinx
[    3s] + export LICENSEDIR
[    3s] + /usr/bin/mkdir -p /home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python-oslosphinx
[    3s] + cp -pr LICENSE /home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python-oslosphinx
[    3s] + exit 0
[    3s] warning: File listed twice: /usr/share/doc/packages/python-oslosphinx
[    3s] warning: File listed twice: /usr/share/doc/packages/python-oslosphinx/README.rst
[    4s] Provides: python-oslosphinx = 4.12.0-0 python2-oslosphinx = 4.12.0-0
[    4s] Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
[    4s] Requires: python(abi) = 2.7
[    4s] Processing files: python3-oslosphinx-4.12.0-0.noarch
[    4s] error: File must begin with "/": Apache-2.0
[    4s] error: File must begin with "/": LICENSE
[    4s] Executing(%doc): /bin/sh -e /var/tmp/rpm-tmp.EkFw0U
[    4s] + umask 022
[    4s] + cd /home/abuild/rpmbuild/BUILD
[    4s] + cd oslosphinx-4.12.0
[    4s] + DOCDIR=/home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python3-oslosphinx
[    4s] + export DOCDIR
[    4s] + /usr/bin/mkdir -p /home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python3-oslosphinx
[    4s] + cp -pr README.rst /home/abuild/rpmbuild/BUILDROOT/python-oslosphinx-4.12.0-0.x86_64/usr/share/doc/packages/python3-oslosphinx
[    4s] + exit 0
[    4s] 
[    4s] 
[    4s] RPM build errors:
[    4s]     File listed twice: /usr/share/doc/packages/python-oslosphinx
[    4s]     File listed twice: /usr/share/doc/packages/python-oslosphinx/README.rst
[    4s]     File must begin with "/": Apache-2.0
[    4s]     File must begin with "/": LICENSE
[    4s] 
[    4s] basilikum failed "build python-oslosphinx.spec" at Tue May 30 16:19:22 UTC 2017.
[    4s] 

%python_subpackages has unterminated body

Building on OBS target SLE_11_SP4 results in the following error. Not sure if this can be fix here, or needs OBS configuration, or both.

[   48s] Preparing packages for installation...
[   48s] python-rpm-macros-2017.08.09.32550d0-53.1
[   48s] ... running 01-check-debuginfo
[   48s] ... testing for empty debuginfo packages
[   48s] ... running 02-check-gcc-output
[   48s] ... testing for serious compiler warnings
[   48s]     (using /usr/lib/build/checks-data/check_gcc_output)
[   48s]     (using //.build.log)
[   48s] ... running 03-check-binary-kernel-log
[   48s] ... running 04-check-filelist
[   48s] ... checking filelist
[   48s] error: Macro %python_subpackages has unterminated body
[   48s] error: Macro %python_subpackages has unterminated body
[   48s] error: Macro %python_subpackages has unterminated body
[   49s] error: Macro %python_subpackages has unterminated body
[   49s] error: Macro %python_subpackages has unterminated body
[   49s] error: Macro %python_subpackages has unterminated body
[   49s] python-rpm-macros-2017.08.09.32550d0-53.1.noarch.rpm: directories not owned by a package:
[   49s]  - error: Macro %python_subpackages has unterminated body
[   49s] error: Macro %python_subpackages has unterminated body
[   49s] 
[   49s] cloud112 failed "build python-rpm-macros.spec" at Mon Oct  9 12:37:15 UTC 2017.

The same checks do not appear to be run on the SLE_10_SDK target.

update-alternatives priorities

Currently, the priority of u-a controlled executables is derived from %python_version_nodots:

function python_install_alternative(flavor)
local prio = rpm.expand("%" .. flavor .. "_version_nodots")

This currently makes the -3.9 alternatives the default. I imagine users and packagers would expect the primary python3 flavor to have the highest prio.

Package requiring /usr/bin/python33

The package mypy has a dependency on /usr/bin/python33. I do not have a clue where this addition 3 comes from.

> rpm -qRp /var/tmp/build-root/openSUSE_Tumbleweed-x86_64/home/abuild/rpmbuild/RPMS/noarch/python3-mypy-0.520-0.noarch.rpm
/usr/bin/python3
/usr/bin/python33
python(abi) = 3.6
python3-typed-ast >= 1.0.3
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PartialHardlinkSets) <= 4.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsLzma) <= 4.4.6-1

Document #90

I totally forgot to document #90 in the README and wiki. Sorry. Opening this issue to keep track of it.

Handle %find_lang

Hello,

I see the following warnings:

[   62s] python-djangorestframework.noarch: W: file-not-in-%lang /usr/lib/python2.7/site-packages/rest_framework/locale/ja/LC_MESSAGES/django.mo
[   62s] python-djangorestframework.noarch: W: file-not-in-%lang /usr/lib/python2.7/site-packages/rest_framework/locale/ko_KR/LC_MESSAGES/django.mo
[   62s] python-djangorestframework.noarch: W: file-not-in-%lang /usr/lib/python2.7/site-packages/rest_framework/locale/mk/LC_MESSAGES/django.mo

At the same time there is no way to handle this following https://en.opensuse.org/openSUSE:Packaging_Conventions_RPM_Macros#.25find_lang

-f %{name}.lang leads to conflict between python{2,3}- packages

%python_subpackages and %python_files equivalent for packages 'foo' defining subpackage 'pythonXY-foo'

We need a macro equivalent of the %python_subpackages and %python_files pair for applications and libraries, which are not primarily python modules. Many such packages manually define a python2-foo and python3-foo but fail with multiple python3 flavors. e.g. libpfm

Alternatively, the %python_subpackages macro could leave packages foo as is and only rewrite subpackage definitions marked accordingly. Right now it fails with

if is_called_python and not python_files then
-- kingly hack. but RPM's native %error does not work.
local errmsg =
'error: Package with "python-" prefix must not contain unmarked "%files" sections.\n' ..
'error: Use "%files %python_files" or "%files %{python_files foo} instead.\n'
io.stderr:write(errmsg)
if used in a package not prefixed with python. Making everything multibuild as in sr#844480 is not really feasible.

Handle .desktop and appdata.xml files

It would be nice if there was a way to handle .desktop and appdata.xml files.

%python_clone could easily handle changing things like the executable and icon. However, there are things like the name and comment that probably would need to be changed as well, but there is no reliable automated way to do that, so a dedicated macro might be necessary.

%{py_ver} problems when only one flavour is enabled

Like #33 , I have a hacky conf which has py2 disabled - so only py3 is enabled.

The result is mostly good, but there are a few times when the macros are behaving oddly.

python-botocore.spec currently uses

%files %{python_files}
%doc README.rst
%license LICENSE.txt
%{python_sitelib}/botocore/
%{python_sitelib}/botocore-%{version}-py%{py_ver}.egg-info

Somehow the %{py_ver} is expanded to PYTHON-NOT-FOUND:

[   64s] RPM build errors:
[   64s]     File not found: /home/abuild/rpmbuild/BUILDROOT/python-botocore-1.12.213-2.1.x86_64/usr/lib/python3.7/site-packages/botocore-1.12.213-pyPYTHON-NOT-FOUND.egg-info
[   64s] 

This also occurs at
https://build.opensuse.org/package/live_build_log/home:jayvdb:py3only/python-pytest-translations/openSUSE_Tumbleweed/x86_64

%python_exec is broken with multiple python3 flavours

So, for example, in python-attr SPEC file we have:

%check 
%python_exec dry_attr.py

which unfortunately expands to:

[   17s] Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.jJGuqZ
[   17s] + umask 022
[   17s] + cd /home/abuild/rpmbuild/BUILD
[   17s] + cd attr-0.3.1
[   17s] ++ '[' -f _current_flavor ']'
[   17s] ++ cat _current_flavor
[   17s] + python_flavor=python38
[   17s] + '[' -z python38 ']'
[   17s] + '[' python38 '!=' python36 ']'
[   17s] + '[' -d build ']'
[   17s] + mv build _build.python38
[   17s] + '[' -d _build.python36 ']'
[   17s] + mv _build.python36 build
[   17s] + echo python36
[   17s] + %__/usr/bin/python3.6 dry_attr.py

%pyunittest{,_arch} discover doesn't work

@s-t-e-v-e-n-k As the macro stands right now

%pyunittest discover

generates (abbreviated) $python -munittest -v discover, which is incorrect, because then unittest starts to search for -v module. The correct call is $python -munittest discover -v. Macro should make sure that the -v argument is always in the last position of the generated code.

Hmm, that actually doesn’t work either, because then %pyunittest test lead to $python -munittest test -v and that is broken as well (it should be $python -munittest -v test).

So, we have to probably actively search for discover keyword and modify our behaviour accordingly.

%pytest macro refuses to take argument with underscore

Test case: %pytest --cov=colcon_core --cov-branch

The macro appears to stumble over the underscore.
Locally overriding the macro to extend its argument expression (...-_=) resolves this.

Any reason this macro is so strict?

rpmlint is not happy with the current libalternatives handling

[  300s] python36-evtx.noarch: E: update-alternatives-requirement-missing
[  300s] python38-evtx.noarch: E: update-alternatives-requirement-missing
[  300s] python39-evtx.noarch: E: update-alternatives-requirement-missing
[  300s] The package does not have update-alternatives in Requires(post) or
[  300s] Requires(postun). This is needed for the proper scriptlet execution.
[  300s] 
[  300s] python36-evtx.noarch: E: update-alternatives-post-call-missing
[  300s] python38-evtx.noarch: E: update-alternatives-post-call-missing
[  300s] python39-evtx.noarch: E: update-alternatives-post-call-missing
[  300s] The package does not call update-alternatives --install in post phase to
[  300s] install all the configuration.
[  300s] 
> rpm -q --scripts python38-evtx-0.6.1-31.1.noarch.rpm
warning: python38-evtx-0.6.1-31.1.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID 3d51bceb: NOKEY
preinstall scriptlet (using /bin/sh):
# If libalternatives is used: Removing old update-alternatives entries.
for c in dump dump_chunk_slack eid_record_numbers extract_record filter_records info record_structure structure templates; do
  

if [ 1 -eq 1 ] ; then 
if [ "$1" -gt 0 ] && [ -f /usr/sbin/update-alternatives ]; then 
    update-alternatives --quiet --remove "evtx_$c.py" "/usr/bin/evtx_$c.py-3.8" 
fi 
fi 

done
postinstall scriptlet (using /bin/sh):
for c in dump dump_chunk_slack eid_record_numbers extract_record filter_records info record_structure structure templates; do
   
mkdir -p /usr/share/libalternatives/evtx_$c.py
echo binary=/usr/bin/evtx_$c.py-3.8 >/usr/share/libalternatives/evtx_$c.py/1038.conf
echo group=evtx_$c.py >>/usr/share/libalternatives/evtx_$c.py/1038.conf

done
postuninstall scriptlet (using /bin/sh):
for c in dump dump_chunk_slack eid_record_numbers extract_record filter_records info record_structure structure templates; do
  

if [ ! -e "/usr/bin/evtx_$c.py-3.8" ] && [ -f /usr/sbin/update-alternatives ]; then 
    update-alternatives --quiet --remove "evtx_$c.py" "/usr/bin/evtx_$c.py-3.8" 
fi 

done

You have to either adjust rpmlint or not install any update-alternatives call into %post and %postun at all.

https://github.com/rpm-software-management/rpmlint/blob/90c84aede91f999c4b4cbd0c3c73d5aa96f54f0f/rpmlint/checks/AlternativesCheck.py#L130

Originally posted by @bnavigator in #115 (comment)

export PYTHONPATH and --import-mode=append required for successful python builds

I wanted to update the package python-zstandard to the latest version 0.17.0:
https://build.opensuse.org/package/show/home:AdaLovelace:branches:devel:languages:python/python-zstandard

It can not find successful integrated builds of the own module 'zstandard.backend_c' because PYTHONPATH is pointing to the the wrong directory, which is not used by the zstandard building process.
That is the reason that these new features with integrated modules can not be used.

That can be fixed with expanding PYTHONPATH with an export in the pytest section inside of the python-rpm-macros.

The second problem is that the tests can not run successfully without "--import-mode=append" after pytest in "osc chroot".
Do we want to have that as a default for all python packages or is there any solution how to expand our macros in the spec file with such options?

%pytest is emitting Python 2 bytecode into Python 3 site-packages

I am told at https://build.opensuse.org/request/show/691930 that I should create an issue.

There are a few isolated cases where pytest puts Python 2 bytecode into the Python 3 site-packages, and the opposite also occurs. pytest also deposits foo.PYTEST files into site-packages occasionally.

The problem is pytest itself, and the religious fervor of the use of the %pytest macro is just making this occur more often.

The only guaranteed way to make the macro not do this, would be PYTHONDONTWRITEBYTECODE=1 etc, or by forcing pytest to not look in the buildroot (i.e. emulate setup.py pytest).

It should be ok to set PYTHONDONTWRITEBYTECODE=1 as the existing bytecode should already exist, but there may be side-effects of not allowing pytest to create the foo.PYTEST files. I couldnt find much info about those foo.PYTEST files. I think a peek in pytest codebase is needed to understand them.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.