Red Hat Training

A Red Hat training course is available for RHEL 8

Chapter 41. Packaging Python 3 RPMs

Most Python projects use Setuptools for packaging, and define package information in the setup.py file. For more information about Setuptools packaging, see the Setuptools documentation.

You can also package your Python project into an RPM package, which provides the following advantages compared to Setuptools packaging:

  • Specification of dependencies of a package on other RPMs (even non-Python)
  • Cryptographic signing

    With cryptographic signing, content of RPM packages can be verified, integrated, and tested with the rest of the operating system.

41.1. SPEC file description for a Python package

A SPEC file contains instructions that the rpmbuild utility uses to build an RPM. The instructions are included in a series of sections. A SPEC file has two main parts in which the sections are defined:

  • Preamble (contains a series of metadata items that are used in the Body)
  • Body (contains the main part of the instructions)

An RPM SPEC file for Python projects has some specifics compared to non-Python RPM SPEC files. Most notably, a name of any RPM package of a Python library must always include the prefix determining the version, for example, python3 for Python 3.6, python38 for Python 3.8, or python39 for Python 3.9.

Other specifics are shown in the following SPEC file example for the python3-detox package. For description of such specifics, see the notes below the example.

%global modname detox                                                           1

Name:           python3-detox                                                   2
Version:        0.12
Release:        4%{?dist}
Summary:        Distributing activities of the tox tool
License:        MIT
URL:            https://pypi.io/project/detox
Source0:        https://pypi.io/packages/source/d/%{modname}/%{modname}-%{version}.tar.gz

BuildArch:      noarch

BuildRequires:  python36-devel                                                  3
BuildRequires:  python3-setuptools
BuildRequires:  python36-rpm-macros
BuildRequires:  python3-six
BuildRequires:  python3-tox
BuildRequires:  python3-py
BuildRequires:  python3-eventlet

%?python_enable_dependency_generator                                            4

%description

Detox is the distributed version of the tox python testing tool. It makes efficient use of multiple CPUs by running all possible activities in parallel.
Detox has the same options and configuration that tox has, so after installation you can run it in the same way and with the same options that you use for tox.

    $ detox

%prep
%autosetup -n %{modname}-%{version}

%build
%py3_build                                                                      5

%install
%py3_install

%check
%{__python3} setup.py test                                                      6

%files -n python3-%{modname}
%doc CHANGELOG
%license LICENSE
%{_bindir}/detox
%{python3_sitelib}/%{modname}/
%{python3_sitelib}/%{modname}-%{version}*

%changelog
...
1
The modname macro contains the name of the Python project. In this example it is detox.
2
When packaging a Python project into RPM, the python3 prefix always needs to be added to the original name of the project. The original name here is detox and the name of the RPM is python3-detox.
3
BuildRequires specifies what packages are required to build and test this package. In BuildRequires, always include items providing tools necessary for building Python packages: python36-devel and python3-setuptools. The python36-rpm-macros package is required so that files with /usr/bin/python3 interpreter directives are automatically changed to /usr/bin/python3.6.
4
Every Python package requires some other packages to work correctly. Such packages need to be specified in the SPEC file as well. To specify the dependencies, you can use the %python_enable_dependency_generator macro to automatically use dependencies defined in the setup.py file. If a package has dependencies that are not specified using Setuptools, specify them within additional Requires directives.
5
The %py3_build and %py3_install macros run the setup.py build and setup.py install commands, respectively, with additional arguments to specify installation locations, the interpreter to use, and other details.
6
The check section provides a macro that runs the correct version of Python. The %{__python3} macro contains a path for the Python 3 interpreter, for example /usr/bin/python3. We recommend to always use the macro rather than a literal path.

41.2. Common macros for Python 3 RPMs

In a SPEC file, always use the macros that are described in the following Macros for Python 3 RPMs table rather than hardcoding their values.

In macro names, always use python3 or python2 instead of unversioned python. Configure the particular Python 3 version in the BuildRequires of the SPEC file to python36-rpm-macros, python38-rpm-macros, or python39-rpm-macros.

Table 41.1. Macros for Python 3 RPMs

MacroNormal DefinitionDescription

%{__python3}

/usr/bin/python3

Python 3 interpreter

%{python3_version}

3.6

The full version of the Python 3 interpreter.

%{python3_sitelib}

/usr/lib/python3.6/site-packages

Where pure-Python modules are installed.

%{python3_sitearch}

/usr/lib64/python3.6/site-packages

Where modules containing architecture-specific extensions are installed.

%py3_build

 

Runs the setup.py build command with arguments suitable for a system package.

%py3_install

 

Runs the setup.py install command with arguments suitable for a system package.

41.3. Automatic provides for Python RPMs

When packaging a Python project, make sure that the following directories are included in the resulting RPM if these directories are present:

  • .dist-info
  • .egg-info
  • .egg-link

From these directories, the RPM build process automatically generates virtual pythonX.Ydist provides, for example, python3.6dist(detox). These virtual provides are used by packages that are specified by the %python_enable_dependency_generator macro.