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-info enthalten, üblicherweise als %ghost.

  • Der Paketname muss mit +EXTRA enden (wobei EXTRA der Name des Extras ist).

Beispielsweise kann das zusätzliche Teilpaket für requests[security] mithilfe des Hilfsmakros %python_extras_subpkg wie folgt angegeben werden. Das Makro benötigt den Namen des Hauptpakets, den/die Namen des/der Zusatzpakets/Zusatzpakete sowie den Pfad zum Verzeichnis .egg-info oder .dist-info:

%{?python_extras_subpkg:%python_extras_subpkg -n python3-requests -i %{python3_sitelib}/*.egg-info security}

In diesem Fall liest der Generator für die Abhängigkeiten der Extras die Upstream-Metadaten aus dem Verzeichnis .egg-info. Wenn er feststellt, dass das Extra security eine Abhängigkeit von cryptography hat, generiert er Requires: python3.Xdist(cryptography), Provides: python3dist(requests[security]) (und die entsprechende Variante python3.Xdist).

Falls Sie zusätzliche Funktionen benötigen, die das Makro %python_extras_subpkg nicht abdeckt, müssen Sie die Teilpaketabschnitte manuell schreiben. Solche Funktionen können beispielsweise sein:

  • „Obsoletes“ und „Provides“ für weitere Namen (z.B. für die Veraltet-Markierung von Extras-Paketen)

  • Manuelles Setzen harter oder weicher Abhängigkeiten zu anderen (evtl. Nicht-Python-)Paketen

  • Einbeziehung von Paketen, die aus dem Hautppaket ausgeschlossen wurden (wenn solche Dateien nur mit den zusätzlichen Dateien sinnvoll sind und das Basispaket auch ohne sie nicht fehlschlägt)

Als Beispiel dafür, was Sie in diesen Fällen schreiben müssen, wird der obige Makroaufruf %python_extras_subpkg wie folgt expandiert:

%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

Beachten Sie, dass der Abhängigkeitsgenerator keine Abhängigkeit vom Hauptpaket hinzufügt (die Zeile Requires: python3-setuptools_scm = ... oben). Wenn Sie das Makro %python_extras_subpkg nicht verwenden, müssen Sie es manuell hinzufügen.

Das Makro %python_extras_subpkg kann mehrere Namen für Extras annehmen, um mehrere Pakete zu generieren. Weitere Optionen finden Sie im Änderungsvorschlag zur Einführung dieser Funktion.

Provides

Für jedes Modul foo, das in Python 3 mit import foo verwendet werden soll, sollte das zugehörige Paket python3-foo bereitstellen. Dies ist natürlich immer der Fall, wenn das Teilpaket den Namen python3-foo trägt (wie in den folgenden Beispielen). Hat das Teilpaket einen anderen Namen, sollte Provides: python3-foo explizit hinzugefügt werden (über %py_provides python3-foo, siehe unten).

Das Makro %py_provides

Alle Pakete, die python3-... (für jedes ...) bereitstellen, SOLLTEN auch python-... und python3.X-... bereitstellen. Ab Fedora 33 werden die meisten Python-Pakete mit dem Namen python3-... diese Namen automatisch über den Abhängigkeitsgenerator in /usr/lib/rpm/fileattrs/pythonname.attr bereitstellen.

Alle manuell hinzugefügten virtuellen „Provides“ von python3-... SOLLTEN über das Makro %py_provides erfolgen.

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}

Paketierer SOLLTEN versuchen, explizite %py_provides-Aufrufe für Paketnamen zu entfernen, KÖNNEN sie aber beibehalten, wenn sie Kompatibilität zu älteren Versionen oder Paketen ohne Dateien anstreben.

Historisch gesehen gab es das Makro %python_provide mit ähnlicher, aber anderer Semantik. Es funktioniert aus Kompatibilitätsgründen weiterhin, ist aber veraltet und SOLLTE NICHT mehr verwendet werden. Paketierer SOLLTEN es durch einen entsprechenden Aufruf von %py_provides ersetzen.

Automatische Provides mit einem standardiserten Namen

Beim Erstellen eines Python-Pakets sucht RPM in den %files-Abschnitten aller Pakete nach .dist-info- und .egg-info-Dateien oder -Verzeichnissen. Werden solche Dateien oder Verzeichnisse gefunden, analysiert RPM sie, um den standardisierten Namen (d. h. den Dist-Namen, den Namen auf PyPI) der paketierten Software zu ermitteln, und erstellt anschließend automatisch zwei Provides:-Tags im folgenden Format:

Provides: python3.Ydist(KANONISCHER_STANDARDISIERTER_NAME)
Provides: python3dist(KANONISCHER_STANDARDISIERTER_NAME)

Die Angabe 3.Y steht für die verwendete Python-Version (üblicherweise 3.6 oder höher). In den Klammern findet sich der Name der Software im kanonischen Format, das von Python-Werkzeugen und -Diensten wie setuptools, pip und PyPI verwendet wird. Der kanonische Name wird erstellt, indem der standardisierte Name in Kleinbuchstaben umgewandelt und alle nicht-alphanumerischen Zeichen durch einzelne Bindestriche („-“) ersetzt werden. Beispiel: „The $$$ Tree“ wird zu „the-tree“.

Requires und BuildRequires mitt standardisierten Namen

Mit Hilfe dieser „Provides“-Tags lassen sich die „Requires“ und „BuildRequires“ eines Pakets anhand der standardisierten Namen (z.B. Dist-Name, Name auf PyPI) von Python-Modulen auflisten. Zur Vereinfachung kann das Makro %{py3_dist} verwendet werden, das einen oder mehrere Parameter akzeptiert: den/die standardisierten Namen der gewünschten Python-Software. Es konvertiert den/die Namen in das kanonische Format und erstellt die entsprechenden python3dist(...)-Tags.

Darüber hinaus können Sie das Makro %{py_dist_name} verwenden, das einfach jeden standardisierten Namen in das kanonische Format umwandelt.

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

Beim Verpacken von Software, die über PyPI verfügbar ist, können Sie das Makro %pypi_source verwenden. Dieses Makro akzeptiert bis zu drei Argumente und gibt eine entsprechende URL zur Quelldatei auf PyPI zurück. Die Argumente sind:

  1. Der Name des PyPI-Projekts. Standardmäßig wird %srcname verwendet, falls definiert, oder %pypi_name, falls definiert, oder %name (der Paketname).

  2. Die Version des PyPI-Projekts. Standardmäßig wird %version (die Paketversion) verwendet, wobei alle ~-Zeichen entfernt werden (wird für Alpha-/Beta-/Entwicklungsversionen in der RPM-Version, aber nicht in der Python-Paketversion verwendet).

  3. Die zu verwendende Dateiendung. Vorgabe ist tar.gz.

In den meisten Fällen ist es nicht notwendig, Argumente anzugeben.

Makros

Die folgenden Makros sind in allen unterstützten Fedora- und EPEL-Versionen für Sie definiert:

Makro Expandierter Pfad Erklärung

%{__python}

(Error)

Dieses Makro darf nicht ohne vorherige Definition verwendet werden. Die Definition ändert die Bedeutung anderer „nicht versionierter“ Python-Makros wie %{python} oder %{python_sitelib}.

%{__python3}

/usr/bin/python3

Python-3-Interpreter. Durch die Neudefinition dieses Makros werden alle %{python3...}-Makros geändert.

%{python3}

%{__python3}

Python-3-Interpreter. Verwenden Sie dieses Makro in Spec-Dateien.

%py_provides

(Lua-Skript)

Siehe [The %py_provides macro] für eine ausführliche Erklärung.

%{python3_sitelib}

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

Ort, an dem reine Python3-Module installiert werden.

%{python3_sitearch}

/usr/lib64/python3.X/site-packages auf 64bit-Architekturen (z.B. x86_64) und /usr/lib/python3.X/site-packages auf 32bit.

Ort, an dem Python3-Erweiterungsmodule installiert werden (z.B. C-kompiliert).

%{py_byte_compile}

(script)

Hinweise zur Byte-Kompilierung finden Sie im Abschnitt Byte-Kompilierung.

%{python3_version}

3.X

Python-3-Version. Nützlich beim Ausführen von Programmen, deren Dateiname die Python-Version enthält, wie z.B. nosetests-%{python3_version}.

%{python3_version_nodots}

3X

Python-3-Version ohne Punkte. Nützlich, wenn Dateien explizit im Abschnitt %files aufgelistet werden, z.B. %{python3_sitearch}/foo/_speedups.cpython-%{python3_version_nodots}*.so

%{python3_platform}

linux-x86_64 on x86_64

Der in Python verwendete Plattformname, nützlich zur Angabe von $PYTHONPATH, z.B. PYTHONPATH=build/lib.%{python3_platform}-%{python3_version}

%{python3_ext_suffix}

.cpython-3X-x86_64-linux-gnu.so on x86_64

Die übliche Dateiendung für Python-Erweiterungsmodule, was beim Auflisten von Dateien hilfreich ist. Beachten Sie, dass Erweiterungsmodule je nach der Art ihrer Erstellung auch die einfache Endung .so haben können.

%py3_build

%{__python3} setup.py build …

See %py3_install for passing arguments to setup.py build or directly to setup.py.

%py3_install

%{__python3} setup.py install --skip-build …

Verschiedene Flags werden an setup.py install übergeben. Details und ähnliche Makros finden Sie in /usr/lib/rpm/macros.d/macros.python3. Um zusätzliche Flags/Argumente an setup.py install zu übergeben, trennen Sie diese mit --, z. B.: %py3_install -- --install-scripts %{_libexecdir}. Um benutzerdefinierte Befehlszeilenargumente direkt an setup.py zu übergeben, definieren Sie %py_setup_args.

%__pytest

/usr/bin/pytest

Der pytest-Befehl, der in %pytest verwendet wird. Verwenden Sie dieses Makro nicht direkt, aber Sie können es bei Bedarf für die Verwendung in %pytest neu definieren.

%pytest

PATH=… PYTHONPATH=… … %{__pytest}

Um sicherzustellen, dass die paketierte Version getestet wird, werden verschiedene Umgebungsvariablen gesetzt. Verwenden Sie dieses Makro anstelle direkter pytest-Aufrufe in %check. Übergeben Sie zusätzliche Argumente wie bei pytest, z. B. %pytest -m "not network", um als network markierte Tests abzuwählen.

%py3_check_import …

PATH=… PYTHONPATH=… … %{__python3} -c 'import …'

Um sicherzustellen, dass die gepackte Version getestet wird, werden verschiedene Umgebungsvariablen gesetzt. Verwenden Sie dieses Makro in %check, um zu testen, ob öffentliche Python-Module importierbar sind, falls die Ausführung der Upstream-Testsuite nicht möglich ist. Übergeben Sie Modulnamen als Positionsargumente, getrennt durch Leerzeichen oder Kommas.

%{py_dist_name}

(Lua-Skript)

Bei Angabe eines standardisierten Namens (z. B. Distributionsname, Name auf PyPI) einer Python-Software wird dieser in ein kanonisches Format konvertiert. Weitere Informationen finden Sie unter [Automatic Provides with a standardized name].

%{py3_dist}

(Lua-Skript)

Bei Angabe eines standardisierten Namens (z. B. Distributionsname, Name auf PyPI) einer Python-Software wird dieser in das kanonische Format konvertiert und zu python3dist(CANONICAL_NAME) ausgewertet. Dies ist hilfreich beim Auflisten von Abhängigkeiten. Weitere Informationen finden Sie unter [Automatic Provides with a standardized name].

%{pypi_source}

(Lua-Skript)

Wird zur entsprechenden URL für das Paket ausgewertet. Weitere Informationen finden Sie oben.

%pycached ….py

(Lua-Skript)

Diese Funktion listet eine Python-Datei sowie die zugehörigen Dateien mit ihrem Bytecode-Cache auf. Weitere Informationen finden Sie unter [Byte compiling].

%{py3_shebang_flags}

s

Die Standardeinstellungen für Python-Shebangs. Definieren Sie diese neu, um die Einstellungen zu ändern. Wird von %py3_shebang_fix verwendet.

%py3_shebang_fix …

(Python-Skript)

Bei Angabe der Pfade zu Python-Dateien oder Verzeichnissen, die diese enthalten, ändert es die Python-Shebangs in #! %{__python3}, behält alle vorhandenen Flags bei (sofern vorhanden) und fügt Flags hinzu, die in %{py3_shebang_flags} definiert sind (sofern nicht bereits vorhanden).

Während %install oder beim Auflisten von %files können Sie die Makros %{python3_sitearch} und %{python3_sitelib} verwenden, um anzugeben, wo die installierten Module zu finden sind. Zum Beispiel:

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

  • Die Verwendung dieser Makros anstelle der festen Angabe des Verzeichnisses in der Spec-Datei gewährleistet, dass Ihre Spec-Datei zur installierten Python-Version kompatibel bleibt, selbst wenn sich die Verzeichnisstruktur radikal ändern würde (zum Beispiel, wenn python3_sitelib nach %{_datadir} verschoben wird).

Pakete, die Cython verwenden

Eine große Anzahl von Erweiterungsmodulen für Python (Python-Module, die in einer kompilierten Sprache wie C oder C++ geschrieben sind) werden unter Verwendung der Sprache und des Compilers Cython geschrieben.

Die meisten dieser Pakete enthalten die generierten C- (oder C++-)Quelltexte im Quellcode-Tarball.

Gemäß der allgemeinen Fedora-Richtlinie dürfen Pakete keine vorab generierten Cython-Quellen verwenden. Diese müssen in %prep gelöscht und während des Bauprozesses neu generiert werden.

Jede Ausnahme von dieser Regel sollte als Bootstrapping betrachtet werden.

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.

    • Wenn der Systemadministrator Python mit der Option -OO aufruft, werden die Dateien ohne Dokumentationszeichenketten erstellt. Dies kann zu Fehlfunktionen in einigen Programmen führen.

  • Dateien oder Verzeichnisse mit den Endungen *.egg-info oder *.dist-info. Falls diese von den Bauskripten des Moduls generiert werden, müssen sie in das Paket aufgenommen werden, da sie möglicherweise von anderen Anwendungen und Modulen zur Laufzeit benötigt werden.

Die Quelldateien MÜSSEN im selben Paket wie die byte-kompilierten Versionen enthalten sein.

Paketierer SOLLTEN NICHT einfach alles unter den Verzeichnissen sitelib oder sitearch in einen Glob-Ordner kopieren. Folgendes SOLLTE NICHT verwendet werden:

  • %{python3_sitelib}/*

  • %{python3_sitearch}/*

  • %{python_sitelib}/*

  • %{python_sitearch}/*

Und die Pakete DÜRFEN NICHT das oberste Verzeichnis __pycache__ enthalten (siehe unten).

Byte-Kompilierung

Python versucht beim Start automatisch, byte-kompilierte Dateien zu erzeugen, um den nächsten Start zu beschleunigen. Diese Dateien werden unter der Endung .pyc (kompiliertes Python) gespeichert und befinden sich im Verzeichnis __pycache__.

Die .pyc-Dateien enthalten Bytecode, der betriebssystemübergreifend funktioniert. Wenn Sie diese nicht in Ihre Pakete einbinden, versucht Python (was in der Regel fehlschlägt), sie beim Ausführen des Programms durch den Benutzer zu erstellen. Führt der Systemadministrator das Programm aus, werden die Dateien erfolgreich geschrieben, was zu verwaisten .pyc-Dateien führt, die beim Entfernen des Pakets nicht gelöscht werden. Um dies zu verhindern, müssen die Bytecode-kompilierten Dateien kompiliert und im Abschnitt %files eingebunden werden. Normalerweise übernimmt das Skript brp-python-bytecompile die Bytecode-Kompilierung. Dieses Skript wird ausgeführt, nachdem der Abschnitt %install der Spec-Datei verarbeitet wurde, und kompiliert alle .py-Dateien, die es in %{python3_sitelib} oder %{python3_sitearch} findet, als Bytecode (diese Neukompilierung fügt die korrekten Dateisystempfade in die Module ein, da sonst Tracebacks den Eintrag %{buildroot} enthalten würden).

Sie müssen die .pyc-Dateien in Ihr Paket einbinden. Falls der Bauprozess ein Verzeichnis __pycache__ in einem Unterverzeichnis von %{python3_sitearch} oder %{python3_sitelib} erstellt, müssen Sie auch alle Elemente in diesem Verzeichnis einbinden. Die Verzeichnisse %{python3_sitearch}/__pycache__ oder %{python3_sitelib}/__pycache__ DÜRFEN NICHT eingebunden werden, da sie bereits zum Paket python3-libs gehören.

Sie müssen lediglich die Dateien im Abschnitt %files einfügen (und dabei %{python3_sitelib} durch das entsprechende Makro für Ihr Paket ersetzen):

%files
%{python3_sitelib}/foo/

Oder, falls der Python-Code direkt in %{python3_sitelib} installiert wird, verwenden Sie das Makro %pycached, um die Bytecode-Cache-Dateien einzubinden:

%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
Das Makro %pycached wird nur von Python 3.5+ unterstützt. Für ältere Python-Versionen (wie z.B. 3.4 in EPEL 6 oder 7) müssen die Dateien manuell aufgelistet werden.
Falls Sie andere Makros zusammen mit dem Makro %pycached verwenden müssen, wie beispielsweise %exclude oder %ghost, übergeben Sie das jeweilige Makro als Teil des Arguments an %pycached. Beispiel: %pycached %exclude /Pfad/zu/foo.py. Die Verwendung der Makros in der falschen Reihenfolge würde %exclude nur auf den ersten Eintrag anwenden, den %pycached erzeugt.

Manuelle Byte-Kompilierung

Weitere Details zu den Interna der Byte-Kompilation finden Sie im Anhang.

Beispiel-Spec-Datei für Python

Nachfolgend finden Sie eine sehr einfache Spec-Datei für ein Python-Modul.

python-example.spec
%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:

  • MUSS: Python-Module müssen aus dem Quellcode erstellt werden. Es reicht nicht aus, einfach ein Egg- oder WHL-Archiv aus dem Upstream-Repository in das entsprechende Verzeichnis zu kopieren. (Siehe Keine vorkompilierten Binärdateien oder Bibliotheken für Details).

  • MUSS: Python-Module dürfen während des Bauprozesses keine Abhängigkeiten herunterladen.

  • MUSS: Beim Erstellen eines Kompatibilitätspakets muss dieses mit easy_install -m installiert werden, damit es nicht mit dem Hauptpaket in Konflikt gerät.

  • MUSS: Beim Erstellen mehrerer Versionen (für ein Kompatibilitätspaket) muss eines der Pakete eine Standardversion enthalten, die über „import MODULE“ ohne vorherige Einrichtung verwendet werden kann.

  • SOLLTE: Zusätzliche python3-...-Provides sollten über einen %py_provides-Aufruf bereitgestellt werden.

  • SOLLTE: Ein Paket, das von einem anderen Paket über eine Egg-Schnittstelle verwendet wird, sollte ein „Provides“ für egg-info haben.