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

Python Enhancement Proposals

PEP 561 – Verteilen und Verpacken von Typinformationen

Autor:
Emma Harper Smith <emma at python.org>
Status:
Final
Typ:
Standards Track
Thema:
Verpackung, Typisierung
Erstellt:
09-Sep-2017
Python-Version:
3.7
Post-History:
10. Sep. 2017, 12. Sep. 2017, 06. Okt. 2017, 26. Okt. 2017, 12. Apr. 2018

Inhaltsverzeichnis

Wichtig

Diese PEP ist ein historisches Dokument: siehe Typinformationen in Bibliotheken für aktuelle Spezifikationen und Dokumentation. Kanonische Typisierungsspezifikationen werden auf der Website für Typisierungsspezifikationen gepflegt; das Laufzeitverhalten der Typisierung wird in der CPython-Dokumentation beschrieben.

×

Siehe den Prozess zur Aktualisierung der Typ-Spezifikation, um Änderungen an der Typ-Spezifikation vorzuschlagen.

Zusammenfassung

PEP 484 führte Typ-Hinweise in Python ein, mit dem Ziel, die Typisierung schrittweise und einfach umsetzbar zu machen. Derzeit müssen Typinformationen manuell verteilt werden. Diese PEP bietet ein standardisiertes Mittel, vorhandene Werkzeuge zu nutzen, um Typinformationen mit minimalem Aufwand zu verpacken und zu verteilen, sowie eine Reihenfolge für Typüberprüfer, um Module aufzulösen und diese Informationen für die Typüberprüfung zu sammeln.

Begründung

Derzeit möchten Paketautoren Code verteilen, der Inline-Typinformationen enthält. Zusätzlich möchten Wartende Stub-Dateien verteilen, um die Kompatibilität mit Python 2 zu erhalten und gleichzeitig neuere Annotationssyntax zu verwenden. Es gibt jedoch keine Standardmethode, um Pakete mit Typinformationen zu verteilen. Wenn man Stub-Dateien privat versenden wollte, wäre die einzige verfügbare Methode das Setzen von MYPYPATH oder einem Äquivalent, um manuell auf Stubs zu verweisen. Wenn das Paket öffentlich veröffentlicht werden kann, kann es zu typeshed hinzugefügt werden [1]. Dies skaliert jedoch nicht und wird zur Belastung für die Wartenden von typeshed. Zusätzlich bindet es Fehlerkorrekturen in Stubs an die Veröffentlichungen des Tools, das typeshed verwendet.

PEP 484 enthält einen kurzen Abschnitt über die Verteilung von Typinformationen. In diesem Abschnitt empfiehlt die PEP die Verwendung von shared/typehints/pythonX.Y/ zum Versenden von Stub-Dateien. Das manuelle Hinzufügen eines Pfades zu Stub-Dateien für jede Drittanbieterbibliothek skaliert jedoch nicht. Der einfachste Ansatz, den Leute verfolgt haben, ist das Hinzufügen von site-packages zu ihrem MYPYPATH, aber dies führt dazu, dass Typüberprüfer bei stark dynamischen Paketen (z. B. SQLAlchemy und Django) fehlschlagen.

Begriffsbestimmungen

Die Definition von „MUSS“, „SOLLTE“ und „SOLLTE NICHT“ ist so zu interpretieren, wie sie in RFC 2119 beschrieben sind.

„inline“ – die Typen sind Teil des Laufzeitcodes unter Verwendung der Syntax von PEP 526 und PEP 3107 (der Dateiname endet auf .py).

„stubs“ – Dateien, die nur Typinformationen enthalten und keinen Laufzeitcode (der Dateiname endet auf .pyi).

„Distributionen“ sind die verpackten Dateien, die zur Veröffentlichung und Verbreitung einer Veröffentlichung verwendet werden. (PEP 426)

„Modul“ eine Datei, die Python-Laufzeitcode oder Stub-Typinformationen enthält.

„Paket“ ein Verzeichnis oder Verzeichnisse, die Python-Module benennen. (Beachten Sie die Unterscheidung zwischen Paketen und Distributionen. Während die meisten Distributionen nach dem einen Paket benannt sind, das sie installieren, installieren einige Distributionen mehrere Pakete.)

Spezifikation

Es gibt mehrere Motivationen und Methoden zur Unterstützung der Typisierung in einem Paket. Diese PEP erkennt drei Arten von Paketen an, die Benutzer der Typisierung erstellen möchten:

  1. Der Paketwart möchte Typinformationen inline hinzufügen.
  2. Der Paketwart möchte Typinformationen über Stubs hinzufügen.
  3. Ein Drittanbieter oder Paketwart möchte Stub-Dateien für ein Paket teilen, der Wartende möchte sie jedoch nicht in den Quellcode des Pakets aufnehmen.

Diese PEP zielt darauf ab, alle drei Szenarien zu unterstützen und sie einfach in Verpackung und Bereitstellung zu integrieren.

Die beiden Hauptteile dieser Spezifikation sind die Verpackungsspezifikationen und die Auflösungsreihenfolge für die Auflösung von Modultypinformationen. Die Typüberprüfungsspezifikation soll die shared/typehints/pythonX.Y/ Spezifikation von PEP 484 ersetzen.

Neue Drittanbieter-Stub-Bibliotheken SOLLTEN Stubs über die in dieser PEP vorgeschlagenen Drittanbieter-Verpackungsmethoden verteilen, anstatt sie an typeshed anzuhängen. Typeshed wird weiterhin verwendet, aber wenn Wartende gefunden werden, SOLLTEN Drittanbieter-Stubs in typeshed in eigene Pakete aufgeteilt werden.

Verpackung von Typinformationen

Um das Verpacken und Verteilen von Typinformationen so einfach und unkompliziert wie möglich zu gestalten, erfolgt die Verpackung und Verteilung über bestehende Frameworks.

Paketwarte, die die Typüberprüfung ihres Codes unterstützen möchten, MÜSSEN eine Markierungsdatei namens py.typed zu ihrem Typisierung unterstützenden Paket hinzufügen. Diese Markierung gilt rekursiv: Wenn ein Top-Level-Paket sie enthält, MÜSSEN alle seine Unterpakete ebenfalls Typüberprüfung unterstützen. Um diese Datei mit dem Paket zu installieren, können Wartende bestehende Verpackungsoptionen wie package_data in distutils verwenden, wie unten gezeigt.

Distutils-Optionsbeispiel

setup(
    ...,
    package_data = {
        'foopkg': ['py.typed'],
    },
    ...,
    )

Für Namespace-Pakete (siehe PEP 420) sollte die py.typed-Datei in den Untermodulen des Namespace liegen, um Konflikte zu vermeiden und für Klarheit zu sorgen.

Diese PEP unterstützt nicht das Verteilen von Typinformationen als Teil von Nur-Modul-Distributionen oder Einzeldatei-Modulen innerhalb von Namespace-Paketen.

Das Einzeldatei-Modul sollte in ein Paket refaktorisiert und angegeben werden, dass das Paket Typisierung unterstützt, wie oben beschrieben.

Nur-Stub-Pakete

Für Paketwarte, die Stub-Dateien mit all ihren Typinformationen versenden möchten, ist es bevorzugt, dass die *.pyi-Stubs neben den entsprechenden *.py-Dateien liegen. Die Stubs können jedoch auch in einem separaten Paket abgelegt und separat verteilt werden. Drittanbieter können diese Methode ebenfalls nützlich finden, wenn sie Stub-Dateien verteilen möchten. Der Name des Stub-Pakets MUSS dem Schema foopkg-stubs für Typ-Stubs für das Paket namens foopkg folgen. Beachten Sie, dass für reine Stub-Pakete das Hinzufügen einer py.typed-Markierung nicht erforderlich ist, da der Name *-stubs ausreicht, um anzugeben, dass es sich um eine Quelle für Typinformationen handelt.

Drittanbieter, die Stub-Dateien verteilen möchten, werden ermutigt, sich mit dem Wartenden des Pakets über die Verteilung neben dem Paket in Verbindung zu setzen. Wenn der Wartende keine Stub-Dateien oder Inline-Typinformationen pflegen oder verpacken möchte, kann ein reines Drittanbieter-Stub-Paket erstellt werden.

Darüber hinaus SOLLTEN reine Stub-Distributionen angeben, welche Versionen des Laufzeitpakets unterstützt werden, indem sie die Version(en) der Laufzeitdistribution über normale Abhängigkeitsdaten angeben. Zum Beispiel kann das Stub-Paket flyingcircus-stubs die Versionen der Laufzeitdistribution flyingcircus angeben, die es über install_requires in distutils-basierten Tools oder das Äquivalent in anderen Verpackungstools unterstützt. Beachten Sie, dass in pip 9.0, wenn Sie flyingcircus-stubs aktualisieren, es flyingcircus aktualisieren wird. In pip 9.0 können Sie das Flag --upgrade-strategy=only-if-needed verwenden. In pip 10.0 ist dies das Standardverhalten.

Für Namespace-Pakete (siehe PEP 420) sollten reine Stub-Pakete den Suffix -stubs nur für das Stamm-Namespace-Paket verwenden. Alle reinen Stub-Namespace-Pakete sollten __init__.pyi-Dateien weglassen. py.typed-Markierungsdateien sind für reine Stub-Pakete nicht erforderlich, aber ähnlich wie bei Paketen mit Inline-Typen sollten sie, wenn sie verwendet werden, in Untermodulen des Namespace liegen, um Konflikte zu vermeiden und für Klarheit zu sorgen.

Wenn zum Beispiel die Verteilungen pentagon und hexagon separate Distributionen sind, die innerhalb des Namespace-Pakets shapes.polygons installiert werden, sollten die entsprechenden reinen Typen-Distributionen Pakete mit folgender Struktur erzeugen:

shapes-stubs
└── polygons
    └── pentagon
        └── __init__.pyi

shapes-stubs
└── polygons
    └── hexagon
        └── __init__.pyi

Auflösungsreihenfolge von Typüberprüfungsmodulen

Dies ist die Reihenfolge, in der Typüberprüfer, die diese PEP unterstützen, Module mit Typinformationen AUFGEFORDERT werden sollten:

  1. Manuell platzierte Stubs oder Python-Quellcode am Anfang des Pfades. Typüberprüfer SOLLTEN dies ermöglichen, um dem Benutzer die vollständige Kontrolle darüber zu geben, welche Stubs verwendet werden, und um fehlerhafte Stubs/Inline-Typen von Paketen zu patchen. In mypy kann die Umgebungsvariable $MYPYPATH dafür verwendet werden.
  2. Benutzercode – die Dateien, auf denen der Typüberprüfer läuft.
  3. Stub-Pakete – diese Pakete SOLLTEN jedes installierte Inline-Paket ersetzen. Sie sind unter foopkg-stubs für das Paket foopkg zu finden.
  4. Pakete mit einer py.typed-Markierungsdatei – wenn nichts das installierte Paket überschreibt UND es sich für die Typüberprüfung entscheidet, SOLLTEN die mit dem Paket gebündelten Typen verwendet werden (sei es in .pyi-Typ-Stub-Dateien oder inline in .py-Dateien).
  5. Typeshed (falls verwendet) – Bietet die Typen der Standardbibliothek und mehrere Drittanbieterbibliotheken.

Wenn Typüberprüfer ein reines Stub-Namespace-Paket ohne das gewünschte Modul in Schritt 3 identifizieren, sollten sie zu Schritt 4/5 übergehen. Typüberprüfer sollten Namespace-Pakete durch das Fehlen von __init__.pyi identifizieren. Dies ermöglicht es verschiedenen Unterpaketen, unabhängig zwischen Inline und reinem Stub zu wählen.

Typüberprüfer, die eine andere Python-Version als die Laufzeitversion überprüfen, MÜSSEN die Typinformationen in den site-packages/dist-packages dieser Python-Version finden. Dies kann z. B. mit pythonX.Y -c 'import site; print(site.getsitepackages())' abgefragt werden. Es wird auch empfohlen, dass der Typüberprüfer es dem Benutzer erlaubt, auf eine bestimmte Python-Binärdatei zu verweisen, falls diese nicht im Pfad ist.

Teilweise Stub-Pakete

Viele Stub-Pakete werden nur einen Teil der Typenschnittstelle für Bibliotheken abgeschlossen haben, insbesondere anfänglich. Zum Nutzen der Typüberprüfung und von Code-Editoren können Pakete „partiell“ sein. Das bedeutet, dass Module, die nicht im Stub-Paket gefunden werden, SOLLTEN in den Teilen vier und fünf der obigen Modulauflösungsreihenfolge gesucht werden, nämlich in Inline-Paketen und Typeshed.

Typüberprüfer sollten das Stub-Paket und das Laufzeitpaket oder die Typeshed-Verzeichnisse zusammenführen. Dies kann als funktionales Äquivalent zum Kopieren des Stub-Pakets in dasselbe Verzeichnis wie das entsprechende Laufzeitpaket oder Typeshed-Ordner und zur Typüberprüfung der kombinierten Verzeichnisstruktur betrachtet werden. Daher MÜSSEN Typüberprüfer die normale Auflösungsreihenfolge beibehalten, um *.pyi vor *.py-Dateien zu überprüfen.

Wenn eine reine Stub-Paketdistribution partiell ist, MUSS sie partial\n in einer py.typed-Datei enthalten. Für reine Stub-Pakete, die innerhalb eines Namespace-Pakets verteilt werden (siehe PEP 420), sollte die py.typed-Datei in den Untermodulen des Namespace liegen.

Typüberprüfer sollten Namespace-Pakete innerhalb von Stub-Paketen als unvollständig behandeln, da mehrere Distributionen sie füllen können. Reguläre Pakete innerhalb von Namespace-Paketen in reinen Stub-Paket-Distributionen werden als vollständig betrachtet, es sei denn, eine py.typed mit partial\n ist enthalten.

Implementierung

Das vorgeschlagene Schema zur Kennzeichnung der Unterstützung für Typisierung ist vollständig abwärtskompatibel und erfordert keine Änderungen an den Paketwerkzeugen. Ein Beispielpaket mit Inline-Typen ist verfügbar [typed_package], ebenso wie ein [stub_package]. Ein Beispiel für einen Paketprüfer [pkg_checker], der die Metadaten installierter Pakete liest und ihren Status als untypisiert, inline typisiert oder als Stub-Paket meldet.

Der mypy-Typüberprüfer verfügt über eine Implementierung der PEP 561-Suche, über die in der mypy-Dokumentation gelesen werden kann [4].

[numpy-stubs] ist ein Beispiel für ein reales reines Stub-Paket für die numpy-Distribution.

Danksagungen

Diese PEP wäre ohne die Ideen, das Feedback und die Unterstützung von Ivan Levkivskyi, Jelle Zijlstra, Alyssa Coghlan, Daniel F Moisset, Andrey Vlasovskikh, Nathaniel Smith und Guido van Rossum nicht möglich gewesen.

Versionshistorie

  • 2023-01-13
    • Klarstellung, dass der 4. Schritt der Modulauflösungsreihenfolge für jedes Paket mit einer py.typed-Markierungsdatei gilt (und nicht nur für Inline-Pakete).
  • 2021-09-20
    • Klarstellung der Erwartungen und des Typüberprüferverhaltens für reine Stub-Namespace-Pakete
    • Klarstellung der Behandlung von Einzeldatei-Modulen innerhalb von Namespace-Paketen.
  • 2018-07-09
    • Links zu Beispiel-Stub-Paketen hinzufügen
  • 2018-06-19
    • Partielle Stub-Pakete können typeshed sowie Laufzeitpakete betrachten
  • 2018-05-15
    • Spezifikation für partielle Stub-Pakete hinzufügen.
  • 2018-04-09
    • Referenz zur mypy-Implementierung hinzufügen
    • Stub-Paket-Priorität klären.
  • 2018-02-02
    • Suffix für reine Stub-Pakete von _stubs in -stubs ändern.
    • Anmerkung, dass py.typed für reine Stub-Pakete nicht benötigt wird.
    • Hinweis zu pip und der Aktualisierung von Stub-Paketen hinzufügen.
  • 2017-11-12
    • Umgeschrieben, um ausschließlich vorhandene Werkzeuge zu verwenden
    • Keine Notwendigkeit, die Art der Typinformationen in Metadaten anzugeben
    • Name der Markierungsdatei von .typeinfo in py.typed geändert
  • 2017-11-10
    • Spezifikation umgeschrieben, um Paketmetadaten anstelle von Distributionsmetadaten zu verwenden.
    • Reine Stub-Pakete entfernt und in die Spezifikation für Drittanbieter-Pakete integriert.
    • Vorschlag für Typüberprüfer, Laufzeitversionen zu berücksichtigen, entfernt
    • Implementierungen aktualisiert, um PEP-Änderungen widerzuspiegeln.
  • 2017-10-26
    • Implementierungsreferenzen hinzugefügt.
    • Danksagungen und Versionshistorie hinzugefügt.
  • 2017-10-06
    • Umgeschrieben, um .distinfo/METADATA anstelle eines distutils-spezifischen Befehls zu verwenden.
    • Versionierung von Drittanbieter-Stub-Paketen klären.
  • 2017-09-11
    • Informationen über aktuelle Lösungen und typeshed hinzugefügt.
    • Begründung klären.

Referenzen


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

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