Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 660 – Editierbare Installationen für pyproject.toml-basierte Builds (Wheel-basiert)

Autor:
Daniel Holth <dholth at gmail.com>, Stéphane Bidoul <stephane.bidoul at gmail.com>
Sponsor:
Paul Moore <p.f.moore at gmail.com>
Discussions-To:
Discourse thread
Status:
Final
Typ:
Standards Track
Thema:
Packaging
Erstellt:
30-Mrz-2021
Post-History:

Resolution:
Discourse thread

Inhaltsverzeichnis

Zusammenfassung

Dieses Dokument beschreibt eine Methode im Stil von PEP 517 für die Installation von Paketen im editierbaren Modus.

Motivation

Python-Programmierer möchten Pakete entwickeln können, ohne sie in site-packages installieren (d.h. kopieren) zu müssen, zum Beispiel, indem sie in einem Checkout des Quellcode-Repositorys arbeiten.

Während dies durch Hinzufügen der relevanten Quellcode-Verzeichnisse zu PYTHONPATH geschehen kann, bietet setuptools den Mechanismus setup.py develop, der den Prozess erleichtert und auch Abhängigkeiten und Einstiegspunkte wie Konsolenskripte installiert. pip macht diesen Mechanismus über seine Option pip install --editable zugänglich.

Die Installation von Projekten in einer Weise, dass der zu importierende Python-Code im Quellcode-Verzeichnis verbleibt, ist als editierbarer Installationsmodus bekannt.

Da PEP 517 nun einen Mechanismus zur Erstellung von Alternativen zu setuptools und zur Entkopplung von Installations-Frontends von Build-Backends bietet, benötigen wir einen neuen Mechanismus zur Installation von Paketen im editierbaren Modus.

Begründung

PEP 517 hat "Editierbare Installationen" aufgeschoben, was bedeutet, dass Nicht-setup.py-Distributionen diese Funktion nicht hatten. Die einzige Möglichkeit, editable-Installationen für diese Distributionen beizubehalten, war die Bereitstellung einer kompatiblen setup.py develop-Implementierung. Durch die Definition eines editierbaren Hooks erhalten andere Build-Frontends Gleichstand mit setup.py.

Terminologie und Ziele

Der editierbare Installationsmodus impliziert, dass der Quellcode des zu installierenden Projekts in einem lokalen Verzeichnis verfügbar ist.

Sobald das Projekt im editierbaren Modus installiert ist, erwarten Benutzer, dass Änderungen am Python-Quellcode des Projekts im lokalen Quellcode-Baum wirksam werden, ohne dass ein neuer Installationsschritt erforderlich ist.

Einige Arten von Änderungen, wie das Hinzufügen oder Ändern von Einstiegspunkten oder das Hinzufügen neuer Abhängigkeiten, erfordern einen neuen Installationsschritt, um wirksam zu werden. Diese Änderungen werden typischerweise in Build-Backend-Konfigurationsdateien (wie pyproject.toml) vorgenommen, daher ist es im Einklang mit der allgemeinen Erwartung der Benutzer, dass Python-Quellcode aus dem Quellcode-Baum importiert wird.

Die Änderung von Nicht-Python-Quellcode wie C-Erweiterungsmodulen erfordert offensichtlich einen Kompilierungs- und/oder Installationsschritt, um wirksam zu werden. Die genauen Schritte bleiben spezifisch für das verwendete Build-Backend.

Wenn ein Projekt im editierbaren Modus installiert wird, erwarten Benutzer, dass die Installation identisch wie eine reguläre Installation funktioniert. Insbesondere muss der Code von anderem Code importierbar sein, und Metadaten müssen für Standardmechanismen wie importlib.metadata verfügbar sein.

Je nachdem, wie Build-Backends diese Spezifikation implementieren, können einige geringfügige Unterschiede sichtbar sein, wie z.B. das Vorhandensein zusätzlicher Dateien, die sich im Quellcode-Baum befinden und nicht Teil einer regulären Installation wären. Build-Backends werden ermutigt, solche potenziellen Unterschiede zu dokumentieren.

Der Mechanismus

Dieser PEP fügt der PEP 517 Backend-Schnittstelle drei optionale Hooks hinzu. Diese Hooks werden verwendet, um ein Wheel zu erstellen, das bei der Installation die Möglichkeit bietet, diese Distribution aus ihrem Quellordner zu importieren.

build_editable

def build_editable(wheel_directory, config_settings=None, metadata_directory=None):
    ...

Muss eine .whl-Datei erstellen und sie im angegebenen wheel_directory ablegen. Es muss den Basisnamen (nicht den vollständigen Pfad) der erstellten .whl-Datei als Unicode-String zurückgeben.

Kann als Nebeneffekt eine In-Place-Erstellung der Distribution durchführen, sodass Erweiterungsmodule oder andere erstellte Artefakte sofort einsatzbereit sind.

Die .whl-Datei muss mit der Spezifikation des Wheel-Binärdatei-Formats (PEP 427) konform sein. Insbesondere muss sie ein konformes .dist-info-Verzeichnis enthalten. Die Metadaten müssen identisch sein mit denen, die von build_wheel oder prepare_metadata_for_build_wheel erzeugt worden wären, mit Ausnahme von Requires-Dist, das leicht abweichen kann, wie unten erläutert.

Build-Backends müssen Wheels erstellen, die die gleichen Abhängigkeiten (Requires-Dist Metadaten) haben wie Wheels, die vom build_wheel Hook erzeugt wurden, mit der Ausnahme, dass sie Abhängigkeiten hinzufügen können, die für die Laufzeitfunktion ihres editierbaren Mechanismus notwendig sind (wie z.B. editables).

Der Dateiname für das "editable" Wheel muss ebenfalls PEP 427-konform sein. Er muss nicht die gleichen Tags wie build_wheel verwenden, aber er muss als mit dem System kompatibel gekennzeichnet sein.

Wenn das Build-Frontend zuvor prepare_metadata_for_build_editable aufgerufen hat und darauf angewiesen ist, dass das aus diesem Aufruf resultierende Wheel Metadaten hat, die mit diesem früheren Aufruf übereinstimmen, dann sollte es den Pfad zum erstellten .dist-info-Verzeichnis als Argument metadata_directory angeben. Wenn dieses Argument angegeben ist, muss build_editable ein Wheel mit identischen Metadaten erstellen. Das vom Build-Frontend übergebene Verzeichnis MUSS identisch mit dem von prepare_metadata_for_build_editable erstellten Verzeichnis sein, einschließlich aller nicht erkannten Dateien, die es erstellt hat.

Ein "editable" Wheel verwendet das Wheel-Format nicht zur Verteilung, sondern als flüchtige Kommunikation zwischen dem Build-System und dem Frontend. Dies vermeidet, dass das Build-Backend etwas direkt installiert. Dieses Wheel darf Endbenutzern nicht zugänglich gemacht, nicht zwischengespeichert und nicht verteilt werden.

get_requires_for_build_editable

def get_requires_for_build_editable(config_settings=None):
    ...

Dieser Hook MUSS eine zusätzliche Liste von Strings zurückgeben, die PEP 508-Abhängigkeitsspezifikationen enthält, zusätzlich zu denen, die in der pyproject.toml-Datei angegeben sind, die bei Aufruf der build_editable-Hooks installiert werden sollen.

Wenn nicht definiert, ist die Standardimplementierung äquivalent zu return [].

prepare_metadata_for_build_editable

def prepare_metadata_for_build_editable(metadata_directory, config_settings=None):
    ...

Muss ein .dist-info-Verzeichnis mit Wheel-Metadaten innerhalb des angegebenen metadata_directory erstellen (d.h. es wird ein Verzeichnis wie {metadata_directory}/{package}-{version}.dist-info/ erstellt). Dieses Verzeichnis MUSS ein gültiges .dist-info-Verzeichnis gemäß der Wheel-Spezifikation sein, mit der Ausnahme, dass es keine RECORD oder Signaturen enthalten muss. Der Hook KANN auch andere Dateien in dieses Verzeichnis aufnehmen, und ein Build-Frontend muss solche Dateien aufbewahren, aber ansonsten ignorieren; die Absicht ist hier, dass in Fällen, in denen die Metadaten von Build-Zeit-Entscheidungen abhängen, das Build-Backend diese Entscheidungen in einem geeigneten Format für die Wiederverwendung durch den eigentlichen Wheel-Erstellungsschritt aufzeichnen muss.

Dies muss den Basisnamen (nicht den vollständigen Pfad) des von ihm erstellten .dist-info-Verzeichnisses als Unicode-String zurückgeben.

Wenn ein Build-Frontend diese Informationen benötigt und die Methode nicht definiert ist, sollte es build_editable aufrufen und die resultierenden Metadaten direkt betrachten.

Was in das Wheel aufgenommen werden soll

Build-Backends müssen das generierte Wheel mit Dateien bestücken, die bei der Installation zu einer editierbaren Installation führen. Build-Backends können verschiedene Techniken verwenden, um die Ziele einer editierbaren Installation zu erreichen. Dieser Abschnitt liefert Beispiele und ist nicht normativ.

  • Build-Backends können wählen, eine .pth-Datei im Stammverzeichnis der .whl-Datei abzulegen, die das Stammverzeichnis des Quellcode-Baums enthält. Dieser Ansatz ist einfach, aber nicht sehr präzise, obwohl er als gut genug (insbesondere bei Verwendung des src-Layouts) angesehen werden kann und dem ähnelt, was setup.py develop derzeit tut.
  • Die editables-Bibliothek zeigt, wie Proxy-Module erstellt werden, die eine hochwertige editierbare Installation ermöglichen. Sie akzeptiert eine Liste von Modulen, die einbezogen und verborgen werden sollen. Beim Importieren ersetzen sich diese Proxy-Module durch den Code aus dem Quellcode-Baum. Pfadbasierte Methoden machen alle Skripte unter einem Pfad importierbar, oft einschließlich des eigenen setup.py des Projekts und anderer Skripte, die nicht Teil einer normalen Installation wären. Die Proxy-Strategie kann eine höhere Wiedergabetreue als pfadbasierte Methoden erzielen.
  • Symbolische Links sind ein weiterer nützlicher Mechanismus zur Realisierung von editierbaren Installationen. Da zum Zeitpunkt der Erstellung dieser Zeilen die wheel-Spezifikation keine symbolischen Links unterstützt, sind sie nicht direkt nutzbar, um symbolische Links in der Zielumgebung einzurichten. Es ist jedoch möglich, dass das Backend eine Symlink-Struktur in einem build-Verzeichnis des Quellcode-Baums erstellt und dieses Verzeichnis über eine .pth-Datei im "editable" Wheel zum Python-Pfad hinzufügt. Wenn einige auf diese Weise verlinkte Dateien von der Python-Implementierung oder -Version, der ABI oder der Plattform abhängen, muss darauf geachtet werden, die Link-Struktur in verschiedenen Verzeichnissen basierend auf Kompatibilitäts-Tags zu generieren, damit derselbe Projektbaum im editierbaren Modus in mehreren Umgebungen installiert werden kann.

Frontend-Anforderungen

Frontends müssen "editable" Wheels auf die gleiche Weise wie reguläre Wheels installieren. Dies bedeutet auch, dass die Deinstallation von editierbaren Installationen keine spezielle Behandlung erfordert.

Frontends müssen eine direct_url.json-Datei im .dist-info-Verzeichnis der installierten Distribution erstellen, konform mit PEP 610. Der url-Wert muss eine file://-URL sein, die auf das Projektverzeichnis zeigt (d.h. das Verzeichnis, das pyproject.toml enthält), und der dir_info-Wert muss {'editable': true} sein.

Frontends müssen die get_requires_for_build_editable-Hooks in einer Umgebung ausführen, die die im pyproject.toml-Datei angegebenen Bootstrap-Anforderungen enthält.

Frontends müssen die prepare_metadata_for_build_editable- und build_editable-Hooks in einer Umgebung ausführen, die die Bootstrap-Anforderungen aus pyproject.toml und die vom get_requires_for_build_editable-Hook angegebenen Anforderungen enthält.

Frontends dürfen das von build_editable erhaltene Wheel nicht für Endbenutzer sichtbar machen. Das Wheel muss nach der Installation verworfen und darf nicht zwischengespeichert oder verteilt werden.

Einschränkungen

In Bezug auf das .data-Verzeichnis des Wheels konzentriert sich dieser PEP darauf, die Kategorien purelib und platlib (installiert in site-packages) "editierbar" zu machen. Er trifft keine besonderen Vorkehrungen für die anderen Kategorien wie headers, data und scripts. Paketautoren werden ermutigt, console_scripts zu verwenden, ihre scripts zu winzigen Wrapper um Bibliotheksfunktionalität zu machen oder diese während der Entwicklung aus dem Quellcode-Checkout zu verwalten.

Prototypen

Zum Zeitpunkt der Erstellung dieses PEP sind mehrere Prototyp-Implementierungen in verschiedenen Frontends und Backends verfügbar. Wir stellen unten Links zur Veranschaulichung möglicher Ansätze zur Verfügung.

Frontends

Build-Backends

Abgelehnte Ideen

editable lokale Versionskennung

Die Idee, dass Build-Backends die lokale Versionskennung anhängen oder ändern, um den String editable einzuschließen, wurde abgelehnt, da dies die == Versionsspezifikation, die die lokale Versionskennung enthält, nicht erfüllen würde. Mit anderen Worten, pkg==1.0+local wird von der Version 1.0+local.editable nicht erfüllt.

Virtuelles Wheel

Ein anderer Ansatz wurde in PEP 662 vorgeschlagen, bei dem das Build-Backend eine Zuordnung von Quelldateien und -verzeichnissen zum installierten Layout zurückgibt. Es liegt dann am Installer-Frontend, die editierbare Installation auf die Weise zu realisieren, die es für seine Benutzer für angemessen hält.

In Bezug auf die Fähigkeiten bieten beide Vorschläge die Kernfunktionalität "editierbar".

Der Hauptunterschied besteht darin, dass PEP 662 es dem Frontend überlässt, zu entscheiden, wie die editierbare Installation realisiert wird, während bei diesem PEP die Wahl vom Backend getroffen werden muss. Beide Ansätze können prinzipiell mehrere editierbare Installationsmethoden für ein gegebenes Projekt bereitstellen und den Entwickler zum Zeitpunkt der Installation eine auswählen lassen.

Zum Zeitpunkt der Erstellung dieses PEP ist klar, dass die Community eine breite Palette theoretischer und praktischer Erwartungen an editierbare Installationen hat. Die Realität ist, dass die einzige Erfahrung, mit der breite Erfahrung besteht, die Pfad-Einfügung über .pth ist (d.h. was setup.py develop tut).

Wir glauben, dass PEP 660 diese "unbekannten Unbekannten" heute auf die zuverlässigste Weise adressiert, indem es Projektverfassern erlaubt, das Backend auszuwählen oder die Methode zu implementieren, die den editierbaren Mechanismus bereitstellt, der ihren Anforderungen am besten entspricht, und zu testen, ob er korrekt funktioniert. Da das Frontend keine Spielräume bei der Frage hat, *wie* das "editable" Wheel installiert wird, gibt es im Fehlerfall nur einen Ort zur Untersuchung: das Build-Backend.

Mit PEP 662 müssen Probleme im Frontend, im Backend und möglicherweise in der Spezifikation untersucht werden. Es besteht auch eine hohe Wahrscheinlichkeit, dass verschiedene Frontends, die die Spezifikation unterschiedlich implementieren, Installationen erzeugen, die sich anders verhalten, als Projektverfasser es beabsichtigt haben, was zu Verwirrung führt oder schlimmer noch, zu Projekten, die nur mit bestimmten Frontends oder IDEs funktionieren.

Entpacktes Wheel

Ein Prototyp wurde erstellt, der ein entpacktes Wheel in einem temporären Verzeichnis erzeugte, das vom Frontend in die Zielumgebung kopiert werden sollte. Dieser Ansatz wurde nicht weiterverfolgt, da ein Wheel-Archiv für das Backend einfach zu erstellen ist und die Verwendung eines Wheels als Kommunikationsmechanismus besser zur PEP 517-Philosophie passt und somit die Dinge für das Frontend einfacher hält.


Quelle: https://github.com/python/peps/blob/main/peps/pep-0660.rst

Zuletzt geändert: 2025-02-01 08:55:40 GMT