Paketbaurichtlinien für Python (201x-Ära)
|
Diese Richtlinien wurde durch eine neuere Version ersetzt. Sie dienen als historische Referenz für Pakete, die den neuen Richtlinien noch nicht entsprechen. |
Python-Versionunterstützung
In Fedora gibt es mehrere Python-Laufzeitumgebungen, eine für jede unterstützte Hauptversion von Python. Aktuell sind das eine für Python 3.x und eine für Python 2.7. Der Python-2-Stack wird jedoch aus Fedora entfernt und ist als veraltet gekennzeichnet. Die offizielle Unterstützung für den Python-2-Interpreter durch die Entwickler endet 2020. Software, die Python 3 unterstützt, muss für Python 3 paketiert werden. Software, die Python 2 verwendet, darf ohne Ausnahme von FESCo nicht neu in Fedora paketiert werden.
Richtlinien zur Pflege bereits bestehender Python2-Pakete finden Sie im Anhang.
Mehrere Python-Laufzeitumgebungen
In Fedora ist /usr/bin/python, sofern es installiert ist, ein symbolischer Link zu /usr/bin/python3. In früheren Versionen war es ein symbolischer Link zu /usr/bin/python2.
Pakete in Fedora DÜRFEN NICHT /usr/bin/python verwenden. Stattdessen MÜSSEN Pakete für Python 3 /usr/bin/python3 verwenden (auch wenn die Upstream-Version sowohl Python 2 als auch 3 unterstützt). Daher DÜRFEN /usr/bin/python (sowie /usr/bin/env python und ähnliche) NICHT in Shebang-Zeilen oder als Paketabhängigkeit verwendet werden. Jegliche Verwendung von nicht versionierten ausführbaren Python-Dateien in Shebang-Zeilen führt zu einem Baufehler. Diese Shebangs MÜSSEN korrigiert werden (z.B. durch Verwendung des Makros %py3_shebang_fix in der Spec-Datei). Falls die Prüfungen deaktiviert werden müssen, finden Sie weitere Informationen unter Shebang-Zeilen.
Alle Python-Laufzeitumgebungen bieten ein virtuelles „Provides“ für python(abi) = $MAJOR.$MINOR. Beispielsweise bietet das Python 3.7-Laufzeitpaket Folgendes:
$ rpm -q --provides python3 | grep abi python(abi) = 3.7
Python-Module, die diese Laufzeitumgebungen verwenden, benötigen eine entsprechende „Requires“-Zeile in der Python-Laufzeitumgebung, mit der sie verwendet werden. Dies geschieht automatisch für Dateien unterhalb von /usr/lib[^/]*/python${PYVER}.
Analog zur Vorgehensweise bei regulären Paketen dürfen die Python-versionsspezifischen Teilpakete Ihres Pakets in einem Release-Zweig von Fedora NICHT entfernt werden.
Benennung
Das Quellpaket einer Python-Bibliothek muss mit dem Präfix python- benannt werden. Ein gebautes Paket hingegen muss die Hauptversion von Python im Namen enthalten und verwendet daher das Präfix python3-. Dies wird durch Hinzufügen eines Teilpakets erreicht. Siehe Beispiel unten.
Diese Regel gilt nicht für Anwendungen.
Das Zeichen ` in Namen von erstellten Paketen (d.h. Nicht-SRPM-Paketen), die Verzeichnisse `.dist-info` oder `.egg-info` enthalten, ist für <<Python Extras>> reserviert und darf nicht anderweitig verwendet werden. Das Zeichen ` aktiviert die automatische Abhängigkeitsgenerierung für Extras. Ersetzen Sie alle `-Zeichen im Namen des Upstream-Pakets durch `-` oder lassen Sie sie am Namensanfang weg. Ausnahmsweise sind `-Zeichen am Ende des Namens zulässig.
Abhängigkeiten
Für Python 3 erstellte Pakete benötigen BuildRequires: python3-devel. Die meisten benötigen außerdem BuildRequires: python3-setuptools. Im Zweifelsfall prüfen Sie die Datei setup.py auf den Import von setuptools.
Pakete DÜRFEN KEINE Abhängigkeiten (weder zur Bau- noch zur Laufzeit) von Paketen mit dem versionierten Präfix python- aufweisen. Abhängigkeiten von Python-Paketen müssen stattdessen Namen verwenden, die mit python3- beginnen.
Automatisch generierte Abhängigkeiten
Pakete KÖNNEN den automatischen Python-Abhängigkeitsgenerator verwenden. Dieser Generator nutzt die Metadaten von Egg/Dist-Dateien (z.B. setuptool’s install_requires), um die Abhängigkeiten des Pakets zu bestimmen. Der Generator analysiert die installierten Metadaten aus /usr/lib(64)?/pythonX.Y/site-packages/[^/]+.(egg|dist)-info/requires.txt, daher funktioniert er nicht mit Software, die die einfachen Distutils verwendet.
Dies erzeugt Laufzeitabhängigkeiten im Format pythonX.Ydist(foo). Sollten die generierten Abhängigkeiten nicht korrekt sein, können weitere manuell hinzugefügt werden. Um einige Abhängigkeiten zu entfernen, kann ein Paketierer die upstreamseitig bereitgestellten Metadaten (üblicherweise in der Datei setup.py angegeben) im Abschnitt %prep der Spec-Datei ändern oder auf die Filterung dieser Abhängigkeiten zurückgreifen.
Der Paketierer MUSS die generierten Abhängigkeiten auf Korrektheit prüfen. Alle Abhängigkeiten MÜSSEN in der Zielversion von Fedora auflösbar sein.
Beispielsweise enthält das Upstream-Paket „notebook“ (Stand: Version 5.6.0):
install_requires = [
'jinja2',
'tornado>=4',
'pyzmq>=17',
'ipython_genutils',
'traitlets>=4.2.1',
'jupyter_core>=4.4.0',
'jupyter_client>=5.2.0',
'nbformat',
'nbconvert',
'ipykernel',
'Send2Trash',
'terminado>=0.8.1',
'prometheus_client'
],
Dies sind die sich ergebenden Abhängigkeiten:
python3.7dist(ipykernel) python3.7dist(ipython-genutils) python3.7dist(jinja2) python3.7dist(jupyter-client) >= 5.2 python3.7dist(jupyter-core) >= 4.4 python3.7dist(nbconvert) python3.7dist(nbformat) python3.7dist(prometheus-client) python3.7dist(pyzmq) >= 17 python3.7dist(send2trash) python3.7dist(terminado) >= 0.8.1 python3.7dist(tornado) >= 4 python3.7dist(traitlets) >= 4.2.1
Beachten Sie, dass alle Suffixe .0 aus Versionsnummern entfernt werden, um dem Verhalten von Python-Werkzeugen zu entsprechen. (PEP 440 legt fest, dass X.Y und X.Y.0 als gleichwertig behandelt werden.)
Dieser Generator ist in Fedora standardmäßig aktiviert. Wenn ein Paketierer den Generator explizit deaktivieren möchte, weil die Upstream-Metadaten nicht anwendbar sind, SOLLTE er dies explizit durch Hinzufügen folgender Zeile tun:
%{?python_disable_dependency_generator}
Obwohl diese Anweisung an beliebiger Stelle in der Spec-Datei verwendet werden kann, empfehlen wir, sie direkt vor die %description-Deklaration des Hauptpakets zu setzen.
Python-Extras
Python-Extras sind eine Möglichkeit für Python-Projekte, anzugeben, dass zusätzliche Abhängigkeiten für zusätzliche Funktionalitäten erforderlich sind.
Beispielsweise hat requests mehrere Standardabhängigkeiten (z.B. urllib3). Es deklariert aber auch ein extra namens requests[security], das zusätzliche Abhängigkeiten auflistet (z.B. cryptography). Im Gegensatz zu RPM-Teilpaketen können Extras nur zusätzliche Abhängigkeiten, aber keine zusätzlichen Dateien angeben. Das Hauptpaket funktioniert auch ohne die optionale Abhängigkeit, allerdings mit eingeschränkter Funktionalität.
Python-Tools behandeln Extra als virtuelle Pakete. Wenn ein Benutzer beispielsweise pip install requests[security] ausführt oder ein Projekt installiert, das von requests[security] abhängt, werden sowohl requests als auch cryptography installiert.
Ab Fedora 33 werden Extras üblicherweise durch Pakete ohne Dateien bereitgestellt. Anstelle von eckigen Klammern verwenden Fedora-Paketnamen üblicherweise das Pluszeichen +, um den Paketnamen vom Namen des extra zu trennen, z.B. würde das Paket python3-requests+security heißen. Das Pluszeichen ist in RPM-Paketnamen zulässig, jedoch weder in kanonischen Python-Projektnamen noch in Bezeichnern von Extras.
Python-Pakete SOLLTEN Provides für alle Extras enthalten, die das Upstream-Projekt angibt, außer solchen, die für andere Pakete nicht nützlich sind (z. B. Bau-/Entwicklungsabhängigkeiten, üblicherweise dev, doc oder test genannt).
Ein Paket, das ein Python-Extra bereitstellt, MUSS python3dist(…[…]) und python3.Xdist(…[…]) als „Provide“ bereitstellen, beispielsweise python3.9dist(requests[security]). Diese Abhängigkeiten SOLLTEN mithilfe des automatischen Abhängigkeitsgenerators erzeugt werden.
Ein Paket, das ein Python-Extra bereitstellt, MUSS das Hauptpaket des Extras mit exakter NEVR-Angabe benötigen.
Ein Teilpaket, das hauptsächlich ein Python-Extra bereitstellt, SOLLTE benannt werden, indem ein + und der Name des Extras an den Namen des Hauptpakets angehängt wird. Zum Beispiel: python3-requests+security.
Die einfachste Möglichkeit, ein Extra bereitzustellen, besteht in der Verwendung eines separaten Teilpakets ohne Dateien (eines „Metapakets“). Dieser Vorgang lässt sich mit dem Makro %python_extras_subpkg automatisieren.
Alternativer Ansatz: Wenn ein Extra in einer Distribution immer nützlich ist, kann es im Hauptpaket enthalten sein. Sind mehrere Extras zusammengehörig, können sie in einem einzigen Teilpaket bereitgestellt werden. Ein eigenes Teilpaket pro Extra ermöglicht es jedoch, den automatischen Abhängigkeitsgenerator zu verwenden, um sicherzustellen, dass die Abhängigkeiten der Extras mit denen des Hauptpakets übereinstimmen. Wenn Sie ein eigenes Teilpaket erstellen und es immer/üblicherweise installieren möchten, können Sie es im Hauptpaket als Requires/Recommends/Suggests angeben.
Der Abhängigkeitsgenerator für Extras wird aktiviert, wenn Folgendes zutrifft:
-
Das Paket muss das Verzeichnis
.egg-info/.dist-infoenthalten, üblicherweise als%ghost. -
Der Paketname muss mit
+EXTRAenden (wobeiEXTRAder Name des Extras ist).
As an example, the extra subpackage for requests[security] can be specified using the %python_extras_subpkg convenience macro as follows. The macro takes the main package name and name(s) of the extra(s) as well as path to the .egg-info or .dist-info directory:
%{?python_extras_subpkg:%python_extras_subpkg -n python3-requests -i %{python3_sitelib}/*.egg-info security}
For this case, the extras dependency generator will read upstream metadata from the .egg-info directory. If it finds that the security extra has a dependency on cryptography, it will generate Requires: python3.Xdist(cryptography), Provides: python3dist(requests[security]) (and the corresponding python3.Xdist variant).
If you need additional features that the %python_extras_subpkg macro does not cover, you will need to write the subpackage sections manually. Such features can be, for example:
-
Obsoleting/providing other names (e.g. obsoleted extras packages)
-
Manual strong or weak dependencies on other (possibly non-Python) packages
-
Including files excluded from the main package (if such files only make sense with the extra and the base package does not fail without them)
As an example of what you need to write in these cases, the %python_extras_subpkg macro invocation above expands to the following:
%package -n python3-requests+security
Summary: Metapackage for python3-requests: security extras
Requires: python3-requests = %{?epoch:%{epoch}:}%{version}-%{release}
%description -n python3-requests+security
This is a metapackage bringing in security extras requires for python3-requests.
It contains no code, just makes sure the dependencies are installed.
%files -n python3-requests+security
%ghost %{python3_sitelib}/*.egg-info
Note that the dependency generator does not add a dependency on the main package (the Requires: python3-setuptools_scm = ... above). If you are not using the %python_extras_subpkg macro, you need to add it manually.
The %python_extras_subpkg can take multiple extras names to generate multiple packages. For more options, see the change proposal which introduced this.
|
Provides
For any module foo intended to be used in Python 3 with import foo, the package that includes it should provide python3-foo. This is of course always the case if the subpackage is named python3-foo (as in the examples below). If the subpackage has some other name, then Provides: python3-foo should be added explicitly (via %py_provides python3-foo, see below).
Das Makro %py_provides
All packages that provide python3-... (for any ...) SHOULD also provide python-... and python3.X-.... Starting from Fedora 33, most of the Python packages named python3-... will provide such names automatically via the dependency generator in /usr/lib/rpm/fileattrs/pythonname.attr.
Any manually added virtual provides of python3-... SHOULD be done via the %py_provides macro.
Anstelle von:
Provides: python3-pkg_resources = %{version}-%{release}
tun Sie Folgendes:
%py_provides python3-pkg_resources
Optional kann eine benutzerdefinierte epoch:version-release als zweites Argument für %py_provides angegeben werden.
Bei älteren Versionen als Fedora 33 oder (aus technischen Gründen) bei Paketen ohne Dateien ist es notwendig, %py_provides auch für Paketnamen zu verwenden:
%package -n python3-%{srcname}
Summary: %{summary}
%py_provides python3-%{srcname}
Packagers SHOULD try to remove explicit %py_provides calls for package names, but MAY preserve them if they aim for compatibility with older releases or packages without files.
Historically, there was %python_provide macro with similar but different semantics. It still works for compatibility reasons but it is deprecated and SHOULD NOT be used and packagers SHOULD replace is with appropriate %py_provides call.
|
Automatische Provides mit einem standardiserten Namen
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: python3.Ydist(CANONICAL_STANDARDIZED_NAME) Provides: python3dist(CANONICAL_STANDARDIZED_NAME)
The 3.Y is the Python version used (usually 3.6 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”.
Requires und BuildRequires mitt standardisierten Namen
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 the %{py3_dist} macro that accept one or more parameters: the standardized name(s) of the desired Python software. It will convert the name(s) to the canonical format and create the proper python3dist(...) tag(s).
In addition, you can use the %{py_dist_name} macro that simply transforms any standardized name to the canonical format.
Beispielsweise:
BuildRequires: %{py3_dist PyMySQL} >= 0.7.5
# => BuildRequires: python3dist(pymysql) >= 0.7.5
Requires: %{py3_dist virtualenv pyPEG2}
# => Requires: python3dist(virtualenv) python3dist(pypeg2)
%{py_dist_name 0-._.-._.-._.-._.-._.-._.-0}
# => 0-0
Quelldateien aus dem PyPI
When packaging software which is available from PyPI, you can make use of the %pypi_source macro. This macro accepts from zero to three arguments and evaluates to an appropriate URL for the source file on PyPI. The arguments are:
-
The name of the PyPI project. Defaults to
%srcnameif defined, or to%pypi_nameif defined, or to%name(the package name). -
The version of the PyPI project. Defaults to
%version(the package version) with any~characters removed (used for alpha/beta/dev versions in RPM version but not in Python package version). -
The file extension to use. Defaults to
tar.gz.
In den meisten Fällen ist es nicht notwendig, Argumente anzugeben.
Makros
The following macros are defined for you in all supported Fedora and EPEL releases:
| Macro | Expanded path | Notes |
|---|---|---|
|
(Error) |
Don’t use this macro without redefining it. Defining it changes the meaning of other "unversioned" Python macros such as |
|
|
Python 3 interpreter. Redefining this macro changes all the |
|
|
Python 3 interpreter. Use this macro in spec files. |
|
(Lua script) |
See [The %py_provides macro] for detailed explanation. |
|
|
Where pure python3 modules are installed. |
|
|
Where python3 extension modules (e.g. C compiled) are installed. |
|
(script) |
See byte-compiling section for usage. |
|
|
Python 3 version. Useful when running programs with Python version in filename, such as |
|
|
Python 3 version without dots. Useful when listing files explicitly in %files section, such as |
|
|
The platform name used in Python, useful for specifying |
|
|
The usual suffix of Python extension modules, useful when listing files. Note that extension modules can alternatively have a simple |
|
|
See |
|
|
Various flags are passed to |
|
|
The |
|
|
Various environment variables are set to ensure the packaged version is tested. Use this macro instead of direct |
|
|
Various environment variables are set to ensure the packaged version is tested. Use this macro in |
|
(Lua script) |
Given a standardized name (i.e. dist name, name on PyPI) of Python software, it will convert it to a canonical format. See [Automatic Provides with a standardized name] for more information. |
|
(Lua script) |
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 |
|
(Lua script) |
Evaluates to the appropriate URL for the package. See above for more information. |
|
(Lua script) |
Given a Python file, lists the file and the files with its bytecode cache. See [Byte compiling] for more information. |
|
|
The default set of flags for Python shebangs. Redefine this to change the set. Used by |
|
(Python script) |
Given paths for Python files or directories with them, it changes Python shebangs to |
During %install or when listing %files you can use the %{python3_sitearch} and %{python3_sitelib} macros to specify where the installed modules are to be found. For instance:
%files
# A pure python3 module
%{python3_sitelib}/foomodule/
# A compiled python3 extension module
%{python3_sitearch}/barmodule/
Die Verwendung der Makros bietet mehrere Vorteile:
-
Es wird sichergestellt, dass die Pakete auf Multilib-Architekturen korrekt installiert werden.
-
Using these macros instead of hardcoding the directory in the specfile ensures your spec remains compatible with the installed Python version even if the directory structure changes radically (for instance, if
python3_sitelibmoves into%{_datadir}).
Pakete, die Cython verwenden
A great amount of extension modules for Python (Python modules written in a compiled language such as C or C++) are written using the Cython language and compiler.
Majority of such packages contains the generated C (or C++) sources in the source tarball.
Tightening the general Fedora policy, packages MUST NOT use pre-generated Cython sources. They MUST be deleted in %prep and regenerated during the build.
Any exception to this rule should be considered a bootstrapping.
Einzubeziehende Dateien
Beim Paketieren von Python-Modulen werden verschiedene Dateitypen einbezogen:
-
*.py-Quelldateien, da diese beim Generieren von Tracebacks verwendet werden.
-
byte-kompilierte *.pyc-Dateien.
-
Python versucht, diese zur Laufzeit zu erstellen, falls sie nicht existieren, was zu fälschlichen SELinux-AVC-Verweigerungen in den Protokollen führt.
-
If the system administrator invokes Python with -OO, they will be created with no docstrings. This can break some programs.
-
-
*.egg-info or *.dist-info files or directories. If these are generated by the module’s build scripts they must be included in the package because they might be needed by other applications and modules at runtime.
The source files MUST be included in the same package as the byte compiled versions.
Packagers SHOULD NOT simply glob everything under the sitelib or sitearch directories. The following SHOULD NOT be used:
-
%{python3_sitelib}/* -
%{python3_sitearch}/* -
%{python_sitelib}/* -
%{python_sitearch}/*
And packages MUST NOT include the top-level __pycache__ directory (see below).
Byte-Kompilierung
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). These files will be located inside a directory named __pycache__.
The .pyc 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 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 in %{python3_sitelib} or %{python3_sitearch} (this recompilation puts the proper filesystem paths into the modules otherwise tracebacks would include the %{buildroot} in them).
You must include the .pyc files in your package. 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 MUST 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}, use the %pycached macro to include the bytecode cache files:
%files
%pycached %{python3_sitelib}/foo.py
Das entspricht ungefähr
%files
%{python3_sitelib}/foo.py
%{python3_sitelib}/__pycache__/foo.cpython-%{python3_version_nodots}{,.opt-?}.pyc
The %pycached macro only supports Python 3.5+, so for older Python versions (such as 3.4 in EPEL 6 or 7), you need to list the files manually.
|
In case you need to use other macros with the %pycached macro, such as %exclude or %ghost, pass the other macro as part of the argument to %pycached. For example: %pycached %exclude /path/to/foo.py Using the macros in wrong order would only apply %exclude to the first entry that %pycached generates.
|
Manuelle Byte-Kompilierung
For more details on the internals of byte compilation, please see the appendix.
Beispiel-Spec-Datei für Python
Nachfolgend finden Sie eine sehr einfache Spec-Datei für ein Python-Modul.
%global srcname example
Name: python-%{srcname}
Version: 1.2.3
Release: 1%{?dist}
Summary: Example python module
License: MIT
URL: https://pypi.python.org/pypi/example
Source: %{pypi_source}
BuildArch: noarch
%global _description %{expand:
A python module which provides a convenient example. This is the
rest of the description that provides more details.}
%description %_description
%package -n python3-%{srcname}
Summary: %{summary}
BuildRequires: python3-devel
BuildRequires: python3-setuptools
%description -n python3-%{srcname} %_description
%prep
%autosetup -n %{srcname}-%{version}
%build
%py3_build
%install
%py3_install
%check
%{python3} setup.py test
# Note that there is no %%files section for the unversioned python module
%files -n python3-%{srcname}
%license COPYING
%doc README.rst
%{python3_sitelib}/%{srcname}-*.egg-info/
%{python3_sitelib}/%{srcname}/
%{_bindir}/sample-exec
Checkliste für Reviewer
Nachfolgend sind die Richtlinien für die Reviewer kurz zusammengefasst:
-
Must: Python modules must be built from source. They cannot simply drop an egg or whl from upstream into the proper directory. (See prebuilt binaries Guidelines for details).
-
Must: Python modules must not download any dependencies during the build process.
-
Must: When building a compat package, it must install using easy_install -m so it won’t conflict with the main package.
-
Must: When building multiple versions (for a compat package) one of the packages must contain a default version that is usable via "import MODULE" with no prior setup.
-
Should: Additional
python3-...provides should be accomplished via a%py_providescall. -
Should: A package which is used by another package via an egg interface should provide egg info.
Want to help? Learn how to contribute to Fedora Docs ›