In Fedora we have multiple Python runtimes, one for each supported major
Python release. At this point that’s one for python2.x
and one for
python3.x
. If a piece of software supports python3
, it must be packaged
for python3
. If it supports python2
as well, it may be packaged for
python2
. If it supports only python2
then (obviously) it must not be
packaged for python3
.
Each runtime corresponds to a binary of the form
/usr/bin/python$MAJOR.$MINOR
. One of these python runtimes is the
“system runtime” which is what is run when invoking /usr/bin/python
.
On Fedora 27, for example, this is a link to /usr/bin/python2
(which
itself is a link to /usr/bin/python2.7
).
However, packages in Fedora MUST not depend on where /usr/bin/python
happens to point but instead MUST call the proper executable for the
needed python major version directly, either /usr/bin/python2
or
/usr/bin/python3
as appropriate. As a result of that
/usr/bin/python
(as well as /usr/bin/env python
and similar)
MUST NOT be used in shebang lines or as a dependency of a package.
All python runtimes have a virtual provide for
python(abi) = $MAJOR-$MINOR
. For example, the python-3.4
runtime
package has:
$ rpm -q --provides python3 |grep -i abi
python(abi) = 3.4
python modules using these runtimes should have a corresponding
“Requires” line on the python runtime that they are used with. This is
done automatically for files below /usr/lib[^/]*/python${PYVER}
Mirroring the policy for regular packages, the Python-version-specific subpackages of your package MUST NOT be removed in a release branch of Fedora.
Packages building for Python2 will need
BuildRequires: python2-devel
. Packages building for Python3 will
need BuildRequires: python3-devel
. Packages building for for both
will need build-time dependencies on both.
Packages MUST NOT have dependencies (either build-time or runtime) on
packages named with the unversioned python-
prefix unless no
properly versioned package exists. Dependencies on Python packages
instead MUST use names beginning with python2-
or python3-
as
appropriate.
Using a fictional module named “example”, the subpackage containing the
python2 version must provide python2-example
. This is of course
always the case if the subpackage is named python2-example
(as in
the examples below). If the subpackage has some other name then then
Provides: python2-example
must be added explicitly (but see the
%python_provide
macro below).
The python3 subpackage must provide python3-example
. However, as
the naming guidelines mandate that the python3 subpackage be named
python3-example
, this will happen automatically.
In addition, the subpackage corresponding to the current system runtime
must provide Provides: python-example
. However, the system
version of python in Fedora will almost certainly change at some point
in the future.
To avoid having to alter every python module package when this change
happens, and to allow the same spec to build for releases with different
system versions of python, a convenient %python_provide
macro is
provided. When given (as an argument) the name of the current
subpackage, it will evaluate to either the proper Provide:
line or
nothing at all as appropriate for the version of the system runtime.
Thus if the package follows the suggested subpackage naming scheme as
shown in the below example, placing this macro in the definition of each
subpackage will guarantee that the necessary Provide:
line appears
where it should, and does not appear where it shouldn’t.
If %python_provide
is called with an argument beginning with
python2-
, it will also generate a suitable Obsoletes:
line for
the unversioned python-
package. This facilitate renaming those
unversioned subpackages.
Finally, if the macro called with an argument like python-example
(no python major version in the name) then it will evaluate to either
Provides: python2-example
or Provides: python3-example
depending
on the version of the current system runtime.
Since Fedora 25, when building a Python package, RPM looks for
.dist-info
and .egg-info
files or directories in the %files
sections of all packages. If one or more are found, RPM parses them to
find the standardized name (i.e. dist name, name on PyPI) of the
packaged software, and then automatically creates two Provides:
tags
in the following format:
Provides: pythonX.Ydist(CANONICAL_STANDARDIZED_NAME)
Provides: pythonXdist(CANONICAL_STANDARDIZED_NAME)
The X
and X.Y
are the Python version used (usually 2.7 or 3.5
and higher), and between the parentheses is the name of the software in
a canonical format used by Python tools and services such as
setuptools, pip and PyPI. The canonical name is obtained by switching
the standardized name to lower case and converting all runs of
non-alphanumeric characters to single “-” characters. Example: “The $$$
Tree” becomes “the-tree”.
Starting with Fedora 26, these Provides tags can be used to list
Requires and BuildRequires of a package using the standardized names
(i.e. dist name, name on PyPI) of Python modules. To make it easier, you
can use macros %{py2_dist}
and %{py3_dist}
that accept one or
more parameters: the standardized name(s) of the desired Python
software. They will convert the name(s) to the canonical format and
create the proper pythonXdist(...)
tag(s).
In addition, you can use the %{py_dist_name} macro that simply transforms any standardized name to the canonical format.
For example:
BuildRequires: %{py2_dist PyMySQL} >= 0.7.5
# => BuildRequires: python2dist(pymysql) >= 0.7.5
Requires: %{py3_dist virtualenv pyPEG2}
# => Requires: python3dist(virtualenv) python3dist(pypeg2)
%{py_dist_name 0-._.-._.-._.-._.-._.-._.-0}
# => 0-0
The following macros are defined for you:
Macro | Normal Definition | Notes |
---|---|---|
__python | %{__python2} |
Default Python interpreter. Currently links to Python2 interpreter |
__python2 | /usr/bin/python2 | Python 2 interpreter. Also the current default python interpreter |
__python3 | /usr/bin/python3 | Python 3 interpreter |
python_provide | (Lua script) | Given a package name, evaluates to either Provides: python-example or nothing at all depending on the version of the system runtime. See here for an example. |
python_sitelib | %{python2_sitelib} |
Where pure python modules are installed for the default Python implementation |
python_sitearch | %{python2_sitearch} |
Where python extension modules that are compiled C are installed for the default Python implementation |
py2_dist | (Lua script) | Introduced in Fedora 25. Given a standardized name (i.e. dist name, name on PyPI) of Python software, it will convert it to a canonical format, and evaluates to python2dist(CANONICAL_NAME) , which is useful when listing dependencies. See above for more information. |
python2_sitelib | /usr/lib/python2.X/site-packages | Where pure python2 modules are installed |
python2_sitearch | /usr/lib64/python2.X/site-packages on x86_64
/usr/lib/python2.X/site-packages on x86
|
Where python2 extension modules that are compiled C are installed |
python3_sitelib | /usr/lib/python3.X/site-packages | Where pure python3 modules are installed |
python3_sitearch | /usr/lib64/python3.X/site-packages on x86_64
/usr/lib/python3.X/site-packages on x86
|
Where python3 extension modules that are compiled C are installed |
py3_dist | (Lua script) | Introduced in Fedora 25. Given a standardized name (i.e. dist name, name on PyPI) of Python software, it will convert it to a canonical format, and evaluates to python3dist(CANONICAL_NAME) , which is useful when listing dependencies. See above for more information. |
py_byte_compile | (script) | Defined in python3-devel. See the byte compiling section for usage |
python3_version | 3.X | Defined in python3-devel. Useful when running programs with Python version in filename, such as nosetest-%{python3_version} |
python3_version_nodots | 3X | Defined in python3-devel since Fedora 21 / Python 3.4. Useful when listing files explicitly in %files section , such as %{python3_sitelib}/foo/*.cpython-%{python3_version_nodots}.pyo |
py_dist_name | (Lua script) | Introduced in Fedora 25. Given a standardized name (i.e. dist name, name on PyPI) of Python software, it will convert it to a canonical format. See above for more information. |
During %install
or when listing %files
you can use the
python2_sitearch
and python2_sitelib
macros to specify where the
installed modules are to be found. For instance:
%files
# A pure python2 module
%{python2_sitelib}/foomodule/
# A compiled python2 extension module
%{python2_sitearch}/barmodule/
# A compiled python3 extension module
%{python3_sitearch}/bazmodule/
Use of the macros has several benefits:
python2_sitelib
moves into %{_datadir}
).When packaging python modules, several types of files are included:
.py
source files.pyc
and *.pyo
byte compiled files__pycache__
directory in most cases).The source files must be included in the same package as the byte compiled versions.
Python will automatically try to byte compile files when it runs in
order to speed up startup the next time it is run. These files are saved
in files with the extension of .pyc (compiled python) or .pyo (optimized
compiled python). With current versions of python 3, these files will be
located inside a directory named __pycache__
. Older versions of
python will simply place them alongside the .py files.
The .pyc and .pyo files contain byte code that is portable across OSes.
If you do not include them in your packages, python will try (and
generally fail) to create them when the user runs the program. If the
system administrator runs the program, then the files will be
successfully written, causing stray .pyc and .pyo files which will not
be removed when the package is removed. To prevent that the byte
compiled files need to be compiled and included in the %files
section. Normally, byte compilation is done for you by the
brp-python-bytecompile
script. This script runs after the
%install
section of the spec file has been processed and byte
compiles any .py files that it finds (this recompilation puts the proper
filesystem paths into the modules otherwise tracebacks would include the
%{buildroot}
in them).
You must include in your package the .pyc and .pyo files. If the build process creates a __pycache__ directory in a subdirectory of %{python3_sitearch} or %{python3_sitelib}, you must also include all items in the __pycache__ directory. (You should not include the directories %{python3_sitearch}/__pycache__ or %{python3_sitelib}/__pycache__ because they are already owned by the python3-libs package.)
All that you need to do is include the files in the %files
section
(replacing %{python3_sitelib} with the appropriate macro for your
package):
%files
%{python3_sitelib}/foo/
or, if the python code installs directly into %{python3_sitelib}:
%files
%{python3_sitelib}/foo.py
%{python3_sitelib}/__pycache__/*
Fedora packages running with python < 3.5 (including any version of
python 2) must not invoke python with the -OO
option or set the
environment variable PYTHONOPTIMIZE
to 2 or greater. (Using -O or
PYTHONOPTIMIZE
less than 2 is fine, though unnecessary.)
Similarly, any .pyo
shipped in a Fedora package for python < 3.5
must not have been byte compiled using optimization level 2 or
higher.
For more details on the internals of byte compilation, please see the appendix.
Many times when you package a python module you will want to create a module for python2 and a module for python3. Both versions should be built from the same SRPM. An exception to this would be if the two versions are distributed as separate archives and do not follow the same release schedule.
The following is a very simple spec file for a module building for both python2 and python3. It builds both versions in the same directory; this is possible because the build products for different versions of Python usually do not conflict.
There are cases where it is not possible to build in a single directory.
Most commonly this happens when the sources are modified during the
build process to convert them from python2 to python3 using the the
2to3
tool. In that case, please see the
appendix.
As you can see in the %install
section below, the order in which you
do the python2 versus python3 install can sometimes matter. You need to
be aware of when the install is writing to the same file in both
packages (in this example, a script in %{_bindir}
and make sure that
you’re getting the version you expect.
%global srcname example
%global sum An example python module
Name: python-%{srcname}
Version: 1.2.3
Release: 1%{?dist}
Summary: %{sum}
License: MIT
URL: https://pypi.python.org/pypi/%{srcname}
Source0: https://files.pythonhosted.org/packages/source/e/%{srcname}/%{srcname}-%{version}.tar.gz
BuildArch: noarch
BuildRequires: python2-devel python3-devel
%description
An python module which provides a convenient example.
%package -n python2-%{srcname}
Summary: %{sum}
%{?python_provide:%python_provide python2-%{srcname}}
%description -n python2-%{srcname}
An python module which provides a convenient example.
%package -n python3-%{srcname}
Summary: %{sum}
%{?python_provide:%python_provide python3-%{srcname}}
%description -n python3-%{srcname}
An python module which provides a convenient example.
%prep
%autosetup -n %{srcname}-%{version}
%build
%py2_build
%py3_build
%install
# Must do the python2 install first because the scripts in /usr/bin are
# overwritten with every setup.py install, and in general we want the
# python3 version to be the default.
# If, however, we're installing separate executables for python2 and python3,
# the order needs to be reversed so the unversioned executable is the python2 one.
%py2_install
%py3_install
%check
%{__python2} setup.py test
%{__python3} setup.py test
# Note that there is no %%files section for the unversioned python module if we are building for several python runtimes
%files -n python2-%{srcname}
%license COPYING
%doc README.rst
%{python2_sitelib}/*
%files -n python3-%{srcname}
%license COPYING
%doc README.rst
%{python3_sitelib}/*
%{_bindir}/sample-exec
%changelog
The python 2 and python 3 stacks are intended to be fully-installable in parallel. When generalizing the package for both python 2 and python 3, it is important to ensure that two different built packages do not attempt to place different payloads into the same path.
/usr/bin
¶Many existing python packages install executables into /usr/bin
.
For example if we have a console_scripts
in a setup.py
shared
between python 2 and python 3 builds: these will spit out files in
/usr/bin/
, and these will collide.
For example python-coverage
has a setup.py
that contains:
entry_points = {
'console_scripts': [
'coverage = coverage:main',
]
},
which thus generates a /usr/bin/coverage
executable (this is a
python script that runs another python script whilst generating
code-coverage information on the latter).
Similarly for the ‘scripts’ clause; see e.g. python-pygments
:
Pygments-1.1.1/setup.py
has:
scripts = ['pygmentize'],
which generates a /usr/bin/pygmentize
(this is a python script that
leverages the pygments syntax-highlighting module, giving a simple
command-line interface for generating syntax-highlighted files)
If the executables provide the same functionality independent of whether they are run on top of Python 2 or Python 3, then only the Python 3 version of the executable should be packaged. Transitioning from python2 to python3 is left to individual package maintainers except for packages in Fedora’s critical path. For these, we want to port to python3 versions in the same Fedora release if possible.
Examples of this:
/usr/bin/pygmentize
ought to generate the same output regardless
of whether it’s implemented via Python 2 or Python 3, so only one
version needs to be shipped.If the executables provide different functionality for Python 2 and Python 3, then both versions should be packaged.
Examples of this:
/usr/bin/coverage
runs a python script, augmenting the
interpreter with code-coverage information. Given that the
interpreter itself is the thing being worked with, it’s reasonable to
package both versions of the executable./usr/bin/bpython
augments the interpreter with a “curses”
interface. Again, it’s reasonable to package both versions of this./usr/bin/easy_install
installs a module into one of the Python
runtimes: we need a version for each runtime.Many executables already contain a -MAJOR.MINOR
suffix, for example
/usr/bin/easy_install-3.4
. These obviously can be used as-is, as
they won’t conflict.
For other executables, the general rule is:
-X
and -X.Y
suffix (python runtime major version, or python
runtime major.minor version), unless upstream already provides
appropriately versioned executables without the dash./usr/bin/coverage-3
and /usr/bin/coverage-3.4
(assuming python3 is currently version 3.4), while the python2
version must provide /usr/bin/coverage
,
/usr/bin/coverage-2
and /usr/bin/coverage-2.7
(assuming
python2 version 2.7)./usr/bin/coverage-v1.2-3
and /usr/bin/coverage-v1.2-3.4
for python3-coverage1.2 compat package.See this thread and a newer thread 1 for discussions of this.
Please see the Python eggs guidelines for information specific to Python eggs.
The following briefly summarizes the guidelines for reviewers to go over:
%python_provide
macro.%python_provide python-$module
so that the current default python
is provided from the unversioned python package.RPM’s dependency generator can often throw in additional dependencies and will often think packages provide functionality contrary to reality. To fix this, the dependency generator needs to be overriden so that the additional dependencies can be filtered out. See Packaging:AutoProvidesAndRequiresFiltering for details.