PEP 691 – JSON-basierte Simple API für Python Package Indexes
- Autor:
- Donald Stufft <donald at stufft.io>, Pradyun Gedam <pradyunsg at gmail.com>, Cooper Lees <me at cooperlees.com>, Dustin Ingram <di at python.org>
- PEP-Delegate:
- Brett Cannon <brett at python.org>
- Discussions-To:
- Discourse thread
- Status:
- Akzeptiert
- Typ:
- Standards Track
- Thema:
- Packaging
- Erstellt:
- 04-Mai-2022
- Post-History:
- 05-Mai-2022
- Resolution:
- Discourse-Nachricht
Inhaltsverzeichnis
- Zusammenfassung
- Ziele
- Spezifikation
- Empfehlungen
- FAQ
- Bedeutet das, dass PyPI die Unterstützung für HTML/PEP 503 einstellen wird?
- Warum JSON statt X-Format?
- Warum nicht X-Funktion hinzufügen?
- Warum die Dateinamen angeben, wenn die URL sie bereits enthält?
- Warum nicht andere Informationen aus dem Dateinamen extrahieren?
- Warum Inhaltsaushandlung statt mehrerer URLs?
- Bedeutet dies, dass statische Server nicht mehr unterstützt werden?
- Warum nicht einen Alias für
application/jsonwie fürtext/htmlhinzufügen? - Warum einen
application/vnd.pypi.simple.v1+htmlhinzufügen? - Warum v1.0 und nicht v1.1 oder v2.0?
- Anhang 1: Umfrage zu abzudeckenden Anwendungsfällen
- Anhang 2: Grobe zugrunde liegende Datenmodelle
- Urheberrecht
Zusammenfassung
Die „Simple Repository API“, die in PEP 503 definiert wurde (und schon viel länger in Gebrauch ist), hat uns sehr gut gedient. Die Abhängigkeit von HTML als Datenaustauschmechanismus hat jedoch mehrere Nachteile.
Es gibt zwei Hauptprobleme mit einer HTML-basierten API:
- Obwohl HTML5 ein Standard ist, ist es ein unglaublich komplexer Standard und die Gewährleistung einer vollständig korrekten Analyse erfordert komplexe Logik, die derzeit weder in der Python-Standardbibliothek (noch in der Standardbibliothek vieler anderer Sprachen) existiert.
Das bedeutet, dass Tools, um alles technisch Gültige zu akzeptieren, große Abhängigkeiten einbinden müssen oder sich auf die
html.parser-Bibliothek der Standardbibliothek verlassen müssen, die schlanker ist, aber möglicherweise HTML5 nicht vollständig unterstützt. - HTML5 ist in erster Linie als Auszeichnungssprache zur Präsentation von Dokumenten für menschlichen Konsum konzipiert. Unsere Verwendung beruht weitgehend auf historischen und zufälligen Gründen, und es ist unwahrscheinlich, dass jemand eine API entwerfen würde, die sich darauf verlässt, wenn er bei Null anfinge.
Das Hauptproblem bei der Verwendung eines Auszeichnungsformats, das für den menschlichen Konsum konzipiert ist, besteht darin, dass es keine gute Möglichkeit gibt, Daten tatsächlich in HTML zu kodieren. Wir haben dies umgangen, indem wir die Daten, die wir in diese API aufnehmen, eingeschränkt haben und kreativ damit umgehen, wie wir Daten in die API quetschen können (z. B. werden Hashes als URL-Fragmente eingebettet, das
data-yanked-Attribut in PEP 592).
PEP 503 war weitgehend ein Versuch, das bereits Verwendete zu standardisieren, und schlug daher keine großen Änderungen an der API vor.
In den dazwischen liegenden Jahren haben wir regelmäßig über eine „API V2“ gesprochen, die die gesamte API von PyPI neu konzipieren würde. Aufgrund begrenzter Zeitbeschränkungen hat diese Anstrengung jedoch keine nennenswerte Traktion gewonnen, abgesehen von den Gedanken, dass es schön wäre, dies zu tun.
Dieses PEP versucht einen anderen Weg einzuschlagen. Es ändert die Gesamtstruktur der API nicht grundlegend, sondern spezifiziert stattdessen eine neue Serialisierung der vorhandenen Daten, die in den bestehenden PEP 503-Antworten enthalten sind, in einem Format, das für Software leichter zu parsen ist, anstatt ein menschenzentriertes Dokumentenformat zu verwenden.
Ziele
- Ermöglicht Zero-Configuration-Discovery. Clients der Simple API **MÜSSEN** in der Lage sein, ein Zielrepository, das dieses PEP unterstützt, ohne jegliche Out-of-Band-Kommunikation (Konfiguration, Vorwissen usw.) zu ermitteln. Einzelne Clients **DÜRFEN** jedoch wählen, eine Konfiguration zur Aktivierung der Verwendung dieser API zu verlangen.
- Ermöglicht Clients die Einstellung der Unterstützung für „Legacy“-HTML-Parsing. Während erwartet wird, dass die meisten Clients HTML-only-Repositories für eine Weile, wenn nicht für immer, unterstützen werden, sollte es einem Client möglich sein, nur die neuen API-Formate zu unterstützen und keinen HTML-Parser mehr aufzurufen.
- Ermöglicht Repositories die Einstellung der Unterstützung für „Legacy“-HTML-Formate. Ähnlich wie bei Clients wird erwartet, dass die meisten Repositories HTML-Antworten lange Zeit oder für immer unterstützen werden. Es sollte einem Repository möglich sein, nur die neuen Formate zu unterstützen.
- Vollständige Unterstützung für bestehende HTML-only-Clients beibehalten. Wir **DÜRFEN** bestehende Clients, die auf die API als rein PEP 503-API zugreifen, nicht brechen. Die einzige Ausnahme hierbei ist, wenn das Repository selbst die Unterstützung des HTML-Formats nicht mehr gewählt hat.
- Minimale zusätzliche HTTP-Anfragen. Die Verwendung dieser API **DARF** die Anzahl der HTTP-Anfragen, die ein Installer zur Funktion benötigt, nicht drastisch erhöhen. Idealerweise erfordert sie 0 zusätzliche Anfragen, kann aber bei Bedarf ein oder zwei zusätzliche Anfragen erfordern (insgesamt, nicht pro Abhängigkeit).
- Minimale zusätzliche eindeutige Antworten. Aufgrund der Art und Weise, wie große Repositories wie PyPI Antworten cachen, sollte dieses PEP keine signifikant oder kombinatorisch große Anzahl zusätzlicher eindeutiger Antworten einführen, die das Repository produzieren kann.
- Unterstützt TUF. Dieses PEP **MUSS** in der Lage sein, innerhalb der Grenzen dessen zu funktionieren, was TUF unterstützen kann (PEP 458), und muss in der Lage sein, damit gesichert zu werden.
- Nur die Standardbibliothek oder kleine externe Abhängigkeiten für Clients erforderlich. Das Parsen einer API-Antwort sollte idealerweise nichts anderes als die Standardbibliothek erfordern, aber die Anforderung einer kleinen, reinen Python-Abhängigkeit wäre akzeptabel.
Spezifikation
Um die Antwortanalyse mit nur der Standardbibliothek zu ermöglichen, spezifiziert dieses PEP, dass alle Antworten (neben den Dateien selbst und den HTML-Antworten von PEP 503) mithilfe von JSON serialisiert werden sollten.
Um die Zero-Configuration-Discovery zu ermöglichen und die Anzahl der zusätzlichen HTTP-Anfragen zu minimieren, erweitert dieses PEP PEP 503 so, dass alle API-Endpunkte (außer den Dateien selbst) HTTP-Content-Negotiation nutzen, um Client und Server die Auswahl des richtigen Serialisierungsformats zu ermöglichen, d. h. entweder HTML oder JSON.
Versionierung
Die Versionierung folgt dem PEP 629-Format (Major.Minor), das die bestehenden HTML-Antworten als 1.0 definiert hat. Da dieses PEP keine neuen Features zur API hinzufügt, sondern ein anderes Serialisierungsformat für die vorhandenen Features beschreibt, ändert dieses PEP die bestehende Version 1.0 nicht, sondern beschreibt nur, wie diese in JSON serialisiert wird.
Ähnlich wie bei PEP 629 **MUSS** die Hauptversionsnummer inkrementiert werden, wenn Änderungen am neuen Format dazu führen würden, dass bestehende Clients das Format nicht mehr sinnvoll verstehen können.
Ebenso **MUSS** die Nebenversionsnummer inkrementiert werden, wenn Features zum Format hinzugefügt oder daraus entfernt werden, aber bestehende Clients das Format weiterhin sinnvoll verstehen können.
Änderungen, die nicht dazu führen, dass bestehende Clients das Format nicht mehr sinnvoll verstehen können, und die keine Hinzufügung oder Entfernung von Features darstellen, können ohne Änderung der Versionsnummer erfolgen.
Dies ist bewusst vage gehalten, da dieses PEP der Ansicht ist, dass zukünftige PEPs, die Änderungen an der API vornehmen, dies untersuchen und entscheiden sollten, ob diese Änderung die Haupt- oder Nebenversion inkrementieren sollte.
Zukünftige Versionen der API können Dinge hinzufügen, die nur in einer Teilmenge der verfügbaren Serialisierungen dieser Version dargestellt werden können. Alle Serialisierungsversionsnummern innerhalb einer Hauptversion **SOLLTEN** synchron gehalten werden, aber die spezifischen Details, wie ein Feature in jedes Format serialisiert wird, können variieren, einschließlich der Frage, ob dieses Feature überhaupt vorhanden ist.
Die Absicht dieses PEPs ist, dass die API als URL-Endpunkte betrachtet werden sollte, die Daten zurückgeben, deren Interpretation durch die Version dieser Daten definiert ist und dann in das Ziel-Serialisierungsformat serialisiert wird.
JSON-Serialisierung
Die URL-Struktur von PEP 503 gilt weiterhin, da dieses PEP nur ein zusätzliches Serialisierungsformat für die bereits vorhandene API hinzufügt.
Die folgenden Einschränkungen gelten für alle JSON-serialisierten Antworten, die in diesem PEP beschrieben sind:
- Alle JSON-Antworten werden **immer** ein JSON-Objekt sein und keine Array oder ein anderer Typ.
- Obwohl JSON keinen URL-Typ nativ unterstützt, kann jeder Wert, der eine URL in dieser API darstellt, absolut oder relativ sein, solange er auf den korrekten Speicherort zeigt. Bei relativen URLs sind diese relativ zur aktuellen URL, als wäre sie HTML.
- Zusätzliche Schlüssel können zu allen Wörterbuchobjekten in den API-Antworten hinzugefügt werden, und Clients **MÜSSEN** Schlüssel ignorieren, die sie nicht verstehen.
- Alle JSON-Antworten haben einen
meta-Schlüssel, der Informationen bezüglich der Antwort selbst und nicht den Inhalt der Antwort enthält. - Alle JSON-Antworten haben einen
meta.api-version-Schlüssel, der eine Zeichenkette ist und die PEP 629Major.Minor-Versionsnummer enthält, mit denselben Fehlermeldungs-/Warnsemantiken wie in PEP 629 definiert. - Alle Anforderungen von PEP 503, die nicht HTML-spezifisch sind, gelten weiterhin.
Projektliste
Die Root-URL / für dieses PEP (die die Basis-URL repräsentiert) wird ein JSON-kodiertes Wörterbuch sein, das zwei Schlüssel hat:
projects: Ein Array, wobei jeder Eintrag ein Wörterbuch mit einem einzigen Schlüssel,name, ist, das die Zeichenkette des Projektnamens darstellt.meta: Die allgemeinen Antwortmetadaten, wie weiter oben beschrieben.
Als Beispiel:
{
"meta": {
"api-version": "1.0"
},
"projects": [
{"name": "Frob"},
{"name": "spamspamspam"}
]
}
Hinweis
Das Feld name ist dasselbe wie in PEP 503, das nicht spezifiziert, ob es sich um den nicht normalisierten Anzeigenamen oder den normalisierten Namen handelt. In der Praxis entscheiden verschiedene Implementierungen dieser PEPs hier unterschiedlich, sodass die Abhängigkeit davon, ob er nicht normalisiert oder normalisiert ist, von einem Implementierungsdetail des betreffenden Repositories abhängt.
Hinweis
Obwohl der Schlüssel projects ein Array ist und daher in irgendeiner Reihenfolge sein muss, weder PEP 503 noch dieses PEP eine bestimmte Reihenfolge oder eine konsistente Reihenfolge von Anfrage zu Anfrage verlangen. Mental ist dies am besten als Set zu verstehen, aber sowohl JSON als auch HTML fehlen die Funktionalität, Sets zu haben.
Projektdetail
Das Format dieser URL ist /<projekt>/, wobei <projekt> durch den PEP 503-normalisierten Namen für dieses Projekt ersetzt wird. Ein Projekt namens „Silly_Walk“ hätte also eine URL wie /silly-walk/.
Diese URL muss mit einem JSON-kodierten Wörterbuch antworten, das drei Schlüssel hat:
name: Der normalisierte Name des Projekts.files: Eine Liste von Wörterbüchern, wobei jedes ein einzelnes Datei darstellt.meta: Die allgemeinen Antwortmetadaten, wie weiter oben beschrieben.
Jedes einzelne Wörterbuch für eine Datei hat die folgenden Schlüssel:
filename: Der Dateiname, der dargestellt wird.url: Die URL, von der die Datei abgerufen werden kann.hashes: Ein Wörterbuch, das einen Hashnamen auf einen hexadezimal kodierten Digest der Datei abbildet. Mehrere Hashes können enthalten sein, und es liegt am Client, zu entscheiden, was er mit mehreren Hashes tut (er kann alle oder eine Teilmenge davon validieren oder gar nichts). Diese Hashnamen **SOLLTEN** immer zu Kleinbuchstaben normalisiert werden.Das Wörterbuch
hashes**MUSS** vorhanden sein, auch wenn keine Hashes für die Datei verfügbar sind. Es wird jedoch **DRINGEND** empfohlen, immer mindestens einen sicheren, garantiert verfügbaren Hash einzufügen.Standardmäßig kann jeder Hash-Algorithmus, der über hashlib verfügbar ist (speziell jeder, der an
hashlib.new()übergeben werden kann und keine zusätzlichen Parameter erfordert), als Schlüssel für dashashes-Wörterbuch verwendet werden. Mindestens ein sicherer Algorithmus aushashlib.algorithms_guaranteed**SOLLTE** immer enthalten sein. Zum Zeitpunkt dieses PEPs wirdsha256speziell empfohlen.requires-python: Ein **optionaler** Schlüssel, der das Metadatenfeld *Requires-Python* offenlegt, spezifiziert in PEP 345. Wenn dies vorhanden ist, **SOLLTEN** Installer-Tools den Download ignorieren, wenn sie auf eine Python-Version installieren, die die Anforderung nicht erfüllt.Im Gegensatz zu
data-requires-pythonin PEP 503 erfordert der Schlüsselrequires-pythonkeine spezielle Maskierung über das hinaus, was JSON naturgemäß leistet.dist-info-metadata: Ein **optionaler** Schlüssel, der angibt, dass Metadaten für diese Datei verfügbar sind, über denselben Speicherort wie in PEP 658 angegeben ({file_url}.metadata). Wenn dies vorhanden ist, **MUSS** es entweder ein boolescher Wert sein, der angibt, ob die Datei eine zugehörige Metadatendatei hat, oder ein Wörterbuch, das Hash-Namen auf einen hexadezimal kodierten Digest des Metadaten-Hashes abbildet.Wenn dies ein Wörterbuch von Hashes anstelle eines booleschen Werts ist, dann gelten für diesen Schlüssel alle gleichen Anforderungen und Empfehlungen wie für den Schlüssel
hashes.Wenn dieser Schlüssel fehlt, kann die Metadatendatei vorhanden sein oder auch nicht. Wenn der Schlüsselwert wahr ist, ist die Metadatendatei vorhanden, und wenn er falsch ist, ist sie es nicht.
Es wird empfohlen, dass Server die Hashes der Metadatendatei nach Möglichkeit bereitstellen.
gpg-sig: Ein **optionaler** Schlüssel, der als boolescher Wert fungiert und angibt, ob die Datei eine zugehörige GPG-Signatur hat oder nicht. Die URL für die Signaturdatei folgt dem, was in PEP 503 angegeben ist ({file_url}.asc). Wenn dieser Schlüssel nicht existiert, kann die Signatur vorhanden sein oder auch nicht.yanked: Ein **optionaler** Schlüssel, der entweder ein boolescher Wert sein kann, der angibt, ob die Datei „yanked“ ist, oder eine nicht leere, aber ansonsten beliebige Zeichenkette, die angibt, dass eine Datei mit einem bestimmten Grund „yanked“ wurde. Wenn der Schlüsselyankedvorhanden und ein wahrer Wert ist, **SOLLTE** er als Indikator dafür interpretiert werden, dass die Datei, auf die das Feldurlverweist, gemäß PEP 592 „Yanked“ wurde.
Als Beispiel:
{
"meta": {
"api-version": "1.0"
},
"name": "holygrail",
"files": [
{
"filename": "holygrail-1.0.tar.gz",
"url": "https://example.com/files/holygrail-1.0.tar.gz",
"hashes": {"sha256": "...", "blake2b": "..."},
"requires-python": ">=3.7",
"yanked": "Had a vulnerability"
},
{
"filename": "holygrail-1.0-py3-none-any.whl",
"url": "https://example.com/files/holygrail-1.0-py3-none-any.whl",
"hashes": {"sha256": "...", "blake2b": "..."},
"requires-python": ">=3.7",
"dist-info-metadata": true
}
]
}
Hinweis
Obwohl der Schlüssel files ein Array ist und daher in irgendeiner Reihenfolge sein muss, weder PEP 503 noch dieses PEP eine bestimmte Reihenfolge oder eine konsistente Reihenfolge von Anfrage zu Anfrage verlangen. Mental ist dies am besten als Set zu verstehen, aber sowohl JSON als auch HTML fehlen die Funktionalität, Sets zu haben.
Inhaltstypen
Dieses PEP schlägt vor, dass alle Antworten der Simple API einen Standard-Content-Type haben werden, der beschreibt, was die Antwort ist (eine Simple API-Antwort), welche Version der API sie repräsentiert und welches Serialisierungsformat verwendet wurde.
Die Struktur dieses Content-Type wird sein:
application/vnd.pypi.simple.$version+format
Da nur Hauptversionen für Clients, die versuchen, eine dieser API-Antworten zu verstehen, störend sind, wird nur die Hauptversion in den Content-Type aufgenommen und mit einem v als Präfix versehen, um klarzustellen, dass es sich um eine Versionsnummer handelt.
Das bedeutet, dass für die bestehende 1.0 API die Content-Types wären:
- JSON:
application/vnd.pypi.simple.v1+json - HTML:
application/vnd.pypi.simple.v1+html
Zusätzlich zu den oben genannten wird eine spezielle „Meta“-Version namens latest unterstützt, deren Zweck es ist, Clients die Anforderung der absolut neuesten Version zu ermöglichen, ohne im Voraus wissen zu müssen, welche Version dies ist. Es wird jedoch empfohlen, dass Clients explizit angeben, welche Versionen sie unterstützen.
Um bestehende Clients zu unterstützen, die erwarten, dass die bestehenden PEP 503 API-Antworten den Content-Type text/html verwenden, definiert dieses PEP ferner text/html als Alias für den Content-Type application/vnd.pypi.simple.v1+html.
Versions- und Formatwahl
Da es nun mehrere mögliche Serialisierungen gibt, benötigen wir einen Mechanismus, der es Clients ermöglicht, anzugeben, welche Serialisierungsformate sie verstehen. Zusätzlich wäre es vorteilhaft, wenn jede mögliche neue Hauptversion der API hinzugefügt werden kann, ohne bestehende Clients, die die vorherige API-Version erwarten, zu stören.
Um dies zu ermöglichen, standardisiert dieses PEP die Verwendung der Server-Driven Content Negotiation von HTTP.
Obwohl dieses PEP nicht die Gesamtheit der Server-Driven Content Negotiation vollständig beschreiben wird, ist der Ablauf ungefähr so:
- Der Client macht eine HTTP-Anfrage, die einen
Accept-Header enthält, der alle Version+Format-Content-Types auflistet, die er verstehen kann. - Der Server inspiziert diesen Header, wählt einen der aufgelisteten Content-Types aus und gibt dann eine Antwort mit diesem Content-Type zurück (wobei die Abwesenheit eines
Accept-Headers alsAccept: */*behandelt wird). - Wenn der Server keinen der Content-Types im
Accept-Header unterstützt, kann er zwischen 3 verschiedenen Optionen wählen, wie er antwortet:- Wählen Sie einen Standard-Content-Type, der sich von dem vom Client angeforderten unterscheidet, und geben Sie eine Antwort mit diesem zurück.
- Geben Sie eine HTTP-Antwort
406 Not Acceptablezurück, um anzuzeigen, dass keiner der angeforderten Content-Types verfügbar war und der Server nicht in der Lage oder nicht willens war, einen Standard-Content-Type für die Antwort auszuwählen. - Geben Sie eine HTTP-Antwort
300 Multiple Choiceszurück, die eine Liste aller möglichen Antworten enthält, die hätten gewählt werden können.
- Der Client interpretiert die Antwort und behandelt die verschiedenen Arten von Antworten, mit denen der Server geantwortet haben könnte.
Dieses PEP spezifiziert nicht, welche Wahl der Server bei der Handhabung eines Content-Types trifft, den er nicht zurückgeben kann, und Clients **SOLLTEN** darauf vorbereitet sein, alle möglichen Antworten auf eine Weise zu behandeln, die für den Client am sinnvollsten ist.
Da es jedoch kein Standardformat für die Interpretation einer 300 Multiple Choices-Antwort gibt, rät dieses PEP Servern dringend davon ab, diese Option zu nutzen, da Clients keine Möglichkeit hätten, eine andere Content-Type zu verstehen und anzufordern. Außerdem ist es unwahrscheinlich, dass der Client ohnehin einen anderen Content-Type verstehen *könnte*, sodass diese Antwort im besten Fall wahrscheinlich genauso behandelt würde wie ein 406 Not Acceptable-Fehler.
Dieses PEP **verlangt**, dass, wenn die Meta-Version latest verwendet wird, der Server mit dem Content-Type für die tatsächliche Version antworten **MUSS**, die in der Antwort enthalten ist (d. h. eine Anfrage Accept: application/vnd.pypi.simple.latest+json, die eine v1.x-Antwort zurückgibt, sollte einen Content-Type von application/vnd.pypi.simple.v1+json haben).
Der Accept-Header ist eine kommagetrennte Liste von Content-Types, die der Client versteht und verarbeiten kann. Er unterstützt drei verschiedene Formate für jeden angeforderten Content-Type:
$type/$subtype$type/**/*
Für die Auswahl einer Version+Format ist das Nützlichste davon $type/$subtype, da dies der einzige Weg ist, die gewünschte Version und das gewünschte Format tatsächlich anzugeben.
Die Reihenfolge der im Accept-Header aufgeführten Content-Types hat keine spezifische Bedeutung, und der Server **SOLLTE** sie alle als gleichwertig betrachten. Wenn ein Client angeben möchte, dass er einen bestimmten Content-Type gegenüber einem anderen bevorzugt, kann er die Quality-Value-Syntax des Accept-Headers verwenden.
Dies ermöglicht es einem Client, eine Priorität für einen bestimmten Eintrag in seinem Accept-Header anzugeben, indem er ein ;q= gefolgt von einem Wert zwischen 0 und 1 (einschließlich) mit bis zu 3 Dezimalstellen anhängt. Bei der Interpretation dieses Werts hat ein Eintrag mit einer höheren Qualität Vorrang vor einem Eintrag mit einer niedrigeren Qualität, und jeder Eintrag ohne Qualität hat standardmäßig eine Qualität von 1.
Clients sollten jedoch bedenken, dass ein Server frei ist, **jeden** der angeforderten Content-Types auszuwählen, unabhängig von seiner angeforderten Priorität, und er kann sogar einen Content-Type zurückgeben, den sie **nicht** angefordert haben.
Um Clients bei der Bestimmung des Content-Types der Antwort, die sie von einer API-Anfrage erhalten haben, zu unterstützen, verlangt dieses PEP, dass Server immer einen Content-Type-Header enthalten, der den Content-Type der Antwort angibt. Dies ist technisch eine abwärtsinkompatible Änderung, aber in der Praxis erzwingt pip diese Anforderung, sodass die Risiken für tatsächliche Fehler gering sind.
Ein Beispiel dafür, wie ein Client operieren könnte, würde so aussehen:
import email.message
import requests
def parse_content_type(header: str) -> str:
m = email.message.Message()
m["content-type"] = header
return m.get_content_type()
# Construct our list of acceptable content types, we want to prefer
# that we get a v1 response serialized using JSON, however we also
# can support a v1 response serialized using HTML. For compatibility
# we also request text/html, but we prefer it least of all since we
# don't know if it's actually a Simple API response, or just some
# random HTML page that we've gotten due to a misconfiguration.
CONTENT_TYPES = [
"application/vnd.pypi.simple.v1+json",
"application/vnd.pypi.simple.v1+html;q=0.2",
"text/html;q=0.01", # For legacy compatibility
]
ACCEPT = ", ".join(CONTENT_TYPES)
# Actually make our request to the API, requesting all of the content
# types that we find acceptable, and letting the server select one of
# them out of the list.
resp = requests.get("https://pypi.org/simple/", headers={"Accept": ACCEPT})
# If the server does not support any of the content types you requested,
# AND it has chosen to return a HTTP 406 error instead of a default
# response then this will raise an exception for the 406 error.
resp.raise_for_status()
# Determine what kind of response we've gotten to ensure that it is one
# that we can support, and if it is, dispatch to a function that will
# understand how to interpret that particular version+serialization. If
# we don't understand the content type we've gotten, then we'll raise
# an exception.
content_type = parse_content_type(resp.headers.get("content-type", ""))
match content_type:
case "application/vnd.pypi.simple.v1+json":
handle_v1_json(resp)
case "application/vnd.pypi.simple.v1+html" | "text/html":
handle_v1_html(resp)
case _:
raise Exception(f"Unknown content type: {content_type}")
Wenn ein Client nur HTML oder nur JSON unterstützen möchte, würde er einfach die Content-Types, die er nicht möchte, aus dem Accept-Header entfernen und deren Empfang als Fehler behandeln.
Alternative Aushandlungsmechanismen
Während die Verwendung der HTTP Content Negotiation als der Standardweg für einen Client und Server gilt, um zu koordinieren, dass der Client eine HTTP-Antwort erhält, die er verstehen kann, gibt es Situationen, in denen dieser Mechanismus möglicherweise nicht ausreicht. Für diese Fälle enthält dieses PEP alternative Verhandlungsmechanismen, die **optional** stattdessen verwendet werden können.
URL-Parameter
Server, die die Simple API implementieren, können optional einen URL-Parameter namens format unterstützen, um Clients die Anforderung einer bestimmten Version der URL zu ermöglichen.
Der Wert des Parameters format sollte **einer** der gültigen Content-Types sein. Das Übergeben mehrerer Content-Types, Wildcards, Quality Values usw. wird **nicht** unterstützt.
Die Unterstützung dieses Parameters ist optional, und Clients **SOLLTEN NICHT** sich darauf verlassen, um mit der API zu interagieren. Dieser Verhandlungsmechanismus ist dazu gedacht, die menschliche Erkundung der API im Browser zu erleichtern oder Dokumentationen oder Notizen zu ermöglichen, die auf eine bestimmte Version+Format verlinken.
Server, die diesen Parameter nicht unterstützen, können wählen, einen Fehler zurückzugeben, wenn er vorhanden ist, oder ihn einfach ignorieren.
Wenn ein Server diesen Parameter implementiert, **SOLLTE** er Vorrang vor allen Werten im Accept-Header des Clients haben. Wenn der Server das angeforderte Format nicht unterstützt, kann er wählen, auf den Accept-Header zurückzugreifen oder eine der Fehlerbedingungen zu wählen, die die Standard-Server-Driven Content Negotiation typischerweise hat (z. B. 406 Not Available, 303 Multiple Choices oder die Auswahl eines Standardtyps zur Rückgabe).
Endpunktkonfiguration
Diese Option ist technisch gesehen keine spezielle Option, sondern einfach eine natürliche Konsequenz der Verwendung von Content Negotiation und der Erlaubnis, dass Server wählen, welcher der verfügbaren Content-Types ihr Standard ist.
Wenn ein Server die Server-Driven Content Negotiation nicht umsetzen kann oder will und stattdessen erwartet, dass Benutzer ihren Client explizit konfigurieren, um die gewünschte Version auszuwählen, dann ist dies eine unterstützte Konfiguration.
Um dies zu ermöglichen, sollte ein Server mehrere Endpunkte (z. B. /simple/v1+html/ und/oder /simple/v1+json/) für jede Version+Format erstellen, die er unterstützen möchte. Unter diesem Endpunkt kann er eine Kopie seines Repositories hosten, die nur einen (oder eine Teilmenge) der Content-Types unterstützt. Wenn ein Client eine Anfrage mit dem Accept-Header stellt, kann der Server ihn ignorieren und den Content-Type zurückgeben, der diesem Endpunkt entspricht.
Für Clients, die eine spezifische Konfiguration erfordern möchten, können sie verfolgen, für welche Version+Format ein bestimmter Repository-URL konfiguriert wurde, und bei einer Anfrage an diesen Server einen Accept-Header ausgeben, der *nur* den korrekten Content-Type enthält.
TUF-Unterstützung – PEP 458
PEP 458 verlangt, dass alle API-Antworten hashbar sind und eindeutig durch einen Pfad relativ zum Repository-Stamm identifiziert werden können. Für ein Simple-API-Repository ist der Zielpfad die Wurzel unserer API (z. B. /simple/ auf PyPI). Dies schafft Herausforderungen beim Zugriff auf die API mit einem TUF-Client anstelle eines direkten Zugriffs mit einem Standard-HTTP-Client, da der TUF-Client nicht damit umgehen kann, dass ein Ziel mehrere verschiedene Darstellungen haben könnte, die alle unterschiedlich hashen.
PEP 458 gibt nicht an, wie der Zielpfad für die Simple API sein soll, aber TUF verlangt, dass die Zielpfade „dateiähnlich“ sind. Mit anderen Worten, ein Pfad wie simple/PROJECT/ ist nicht akzeptabel, da er technisch auf ein Verzeichnis verweist.
Die Rettung ist, dass der Zielpfad nicht tatsächlich mit der URL übereinstimmen muss, die von der Simple API abgerufen wird, und er kann einfach ein Sigil sein, den der abrufende Code in die tatsächlich abzurufende URL umwandeln kann. Dasselbe kann für andere Aspekte der eigentlichen HTTP-Anfrage gelten, wie z. B. den Accept-Header.
Letztendlich liegt die Ermittlung, wie ein Verzeichnis einer Datei zugeordnet wird, außerhalb des Umfangs dieser PEP (aber sie wäre im Geltungsbereich von PEP 458), und diese PEP verschiebt die Entscheidung darüber, wie dies genau innerhalb der PEP 458-Metadaten dargestellt werden soll.
Es scheint jedoch, dass der aktuelle WIP-Branch gegen pip, der versucht, PEP 458 zu implementieren, einen Zielpfad wie simple/PROJECT/index.html verwendet. Dies könnte modifiziert werden, um die API-Version und das Serialisierungsformat mit etwas wie simple/PROJECT/vnd.pypi.simple.vN.FORMAT aufzunehmen. Die v1 HTML-Format wäre also simple/PROJECT/vnd.pypi.simple.v1.html und das v1 JSON-Format wäre simple/PROJECT/vnd.pypi.simple.v1.json.
In diesem Fall, da text/html ein Alias für application/vnd.pypi.simple.v1+html ist, wenn über TUF interagiert wird, wird es wahrscheinlich am sinnvollsten sein, zu dem expliziteren Namen zu normalisieren.
Ebenso sollte die Metaversion latest nicht in den Zielen enthalten sein; nur explizit deklarierte Versionen sollten unterstützt werden.
Empfehlungen
Dieser Abschnitt ist nicht-normativ und stellt dar, was die Autoren der PEP als beste Standardimplementierungsentscheidungen für etwas betrachten, das diese PEP implementiert, aber er stellt keine Anforderung dar, diese Entscheidungen zu übernehmen.
Diese Entscheidungen wurden getroffen, um die Anzahl der Anfragen zu maximieren, die auf die neueste Version einer API verschoben werden können, während die größtmögliche Kompatibilität erhalten bleibt. Darüber hinaus wurde versucht, die Verwendung der API mit Schutzplanken zu versehen, die versuchen, Clients zu den bestmöglichen Entscheidungen zu drängen.
Es wird empfohlen, dass Server
- Alle in dieser PEP beschriebenen 3 Inhaltstypen unterstützen, indem sie serverseitige Inhaltsaushandlung verwenden, solange es ihnen vernünftigerweise möglich ist, oder zumindest solange sie nicht triviale Datenverkehr erhalten, der HTML-Antworten verwendet.
- Wenn ein
Accept-Header angetroffen wird, der keine Inhaltstypen enthält, mit denen er umgehen kann, sollte der Server niemals eine Antwort300 Multiple Choicezurückgeben, sondern stattdessen eine Antwort406 Not Acceptablezurückgeben.- Wenn Sie sich jedoch für die Verwendung der Endpunktkonfiguration entscheiden, sollten Sie vorzugsweise eine Antwort
200 OKim erwarteten Inhaltstyp für diesen Endpunkt zurückgeben.
- Wenn Sie sich jedoch für die Verwendung der Endpunktkonfiguration entscheiden, sollten Sie vorzugsweise eine Antwort
- Bei der Auswahl einer akzeptablen Version sollte der Server die höchste Version wählen, die der Client unterstützt, mit dem ausdrucksstärksten/funktionsreichsten Serialisierungsformat, unter Berücksichtigung der Spezifität der Clientanfragen sowie etwaiger Qualitätswertprioritäten, die sie ausgedrückt haben. Er sollte den Inhaltstyp
text/htmlnur als letzte Option verwenden.
Es wird empfohlen, dass Clients
- Alle in dieser PEP beschriebenen 3 Inhaltstypen unterstützen, indem sie serverseitige Inhaltsaushandlung verwenden, solange es ihnen vernünftigerweise möglich ist.
- Beim Erstellen eines
Accept-Headers alle unterstützten Inhaltstypen einschließen.Sie sollten im Allgemeinen keinen Qualitätsprioritätswert für Ihre Inhaltstypen angeben, es sei denn, Sie haben implementierungsspezifische Gründe, die der Server berücksichtigen soll (z. B. wenn Sie den HTML-Parser der Standardbibliothek verwenden und befürchten, dass es bestimmte HTML-Antworten gibt, die Sie in einigen Randfällen nicht analysieren können).
Die einzige Ausnahme von dieser Empfehlung ist, dass es empfohlen wird, einen Wert von
;q=0.01für den Legacy-Inhaltstyptext/htmlanzugeben, es sei denn, es ist der einzige angeforderte Inhaltstyp. - Explizit auswählen, welche Versionen sie suchen, anstatt die Metaversion
latestim normalen Betrieb zu verwenden. - Den
Content-Typeder Antwort überprüfen und sicherstellen, dass er mit etwas übereinstimmt, das Sie erwartet haben.
FAQ
Bedeutet das, dass PyPI die Unterstützung für HTML/PEP 503 einstellen wird?
Nein, PyPI hat derzeit keine Pläne, die Unterstützung für PEP 503 oder HTML-Antworten einzustellen.
Obwohl diese PEP Repositories die Flexibilität dazu gibt, existiert dies weitgehend, um sicherzustellen, dass Dinge wie die Verwendung des Endpunktkonfigurationsmechanismus funktionieren und um sicherzustellen, dass Clients keine Annahmen treffen, die es verhindern würden, zu einem späteren Zeitpunkt die Unterstützung für HTML graceful einzustellen.
Die bestehenden HTML-Antworten verursachen für PyPI fast keine Wartungslast und es gibt keinen dringenden Bedarf, sie zu entfernen. Der einzige wirkliche Vorteil des Entfernens wäre die Reduzierung der Anzahl der Elemente, die in unserem CDN zwischengespeichert werden.
Wenn PyPI in Zukunft tatsächlich die Unterstützung dafür einstellen möchte, wäre dies fast sicher das Thema einer PEP oder zumindest einer öffentlichen, offenen Diskussion und würde von Metriken informiert, die Auswirkungen auf Endbenutzer zeigen.
Warum JSON statt X-Format?
JSON-Parser sind in den meisten, wenn nicht allen Sprachen weit verbreitet. Ein JSON-Parser ist auch in der Python-Standardbibliothek verfügbar. Es ist nicht das perfekte Format, aber es ist gut genug.
Warum nicht X-Funktion hinzufügen?
Das allgemeine Ziel dieser PEP ist es, sehr wenig zu ändern oder hinzuzufügen. Wir werden uns stattdessen weitgehend darauf konzentrieren, die vorhandenen Informationen aus unseren HTML-Antworten in eine sinnvolle JSON-Darstellung zu übersetzen. Dies wird PEP 658 Metadaten, die für Packaging-Tools benötigt werden, einschließen.
Die einzige wirkliche neue Fähigkeit, die in dieser PEP hinzugefügt wird, ist die Möglichkeit, mehrere Hashes für eine einzelne Datei zu haben. Dies wurde getan, weil der aktuelle Mechanismus, der auf einen einzigen Hash beschränkt ist, es in der Vergangenheit schmerzhaft gemacht hat, Hashes zu migrieren (md5 zu sha256), und die Kosten für die Umwandlung der Hashes in ein Wörterbuch und die Zulassung mehrerer sind ziemlich gering.
Die API wurde im Allgemeinen so konzipiert, dass sie durch Hinzufügen neuer Schlüssel weiter erweitert werden kann. Wenn es also neue Daten gibt, die ein Installer möglicherweise benötigt, können zukünftige PEPs diese leicht verfügbar machen.
Warum die Dateinamen angeben, wenn die URL sie bereits enthält?
Wir könnten die Größe unserer Antworten reduzieren, indem wir den Schlüssel filename entfernen und erwarten, dass Clients diese Informationen aus der URL beziehen.
Derzeit verzichtet diese PEP darauf, hauptsächlich weil PEP 503 explizit verlangte, dass der Dateiname über das Anker-Tag der Links verfügbar ist, obwohl dies weitgehend darauf zurückzuführen war, dass etwas dort sein musste. Es ist unklar, ob Repositories in freier Wildbahn immer einen Dateinamen als letzten Teil der URL haben oder ob sie sich auf den Dateinamen im Anker-Tag verlassen.
Es macht die Antworten auch etwas angenehmer zu lesen für einen Menschen, da man eine schöne kurze eindeutige Kennung erhält.
Wenn wir die Zuversicht gewinnen, dass die Mandatierung des Dateinamens in der URL erfolgt, könnten wir diese Daten entfernen und die Größe der JSON-Antwort reduzieren.
Warum nicht andere Informationen aus dem Dateinamen extrahieren?
Derzeit wird von Clients erwartet, dass sie eine Reihe von Informationen aus dem Dateinamen parsen, wie z. B. Projektname, Version, ABI-Tags usw. Wir könnten diese aufbrechen und sie als Schlüssel zum Datei-Objekt hinzufügen.
Diese PEP hat sich entschieden, dies nicht zu tun, da dies die Größe der API-Antworten erhöhen würde, und die meisten Clients ohnehin die Fähigkeit benötigen werden, diese Informationen aus Dateinamen zu extrahieren, unabhängig davon, was die API tut. Daher ist es sinnvoll, diese Funktionalität in den Clients zu belassen.
Warum Inhaltsaushandlung statt mehrerer URLs?
Ein weiterer vernünftiger Weg, dies zu implementieren, wäre, die API-Routen zu duplizieren und einen Marker in die URL selbst für JSON einzufügen. Zum Beispiel, indem die URLs so aussehen: /simple/foo.json, /simple/_index.json usw.
Dies vereinfacht einige Dinge wie die TUF-Integration und das vollständig statische Servieren eines Repositorys (da .json-Dateien einfach herausgeschrieben werden können).
Dies sind jedoch zwei ziemlich schwerwiegende Probleme
- Unsere aktuelle URL-Struktur beruht auf der Tatsache, dass es eine URL gibt, die die „Wurzel“
/zum Servieren der Projektliste darstellt. Wenn wir separate URLs für JSON und HTML haben möchten, müssten wir uns einen Weg ausdenken, zwei Root-URLs zu haben.Etwas wie
/als HTML und/_index.jsonals JSON, da_indexkein gültiger Projektname ist, könnte funktionieren. Aber/als HTML funktioniert nicht gut, wenn ein Repository die Unterstützung für HTML entfernen möchte.Eine andere Option könnte sein, alle aktuellen HTML-URLs unter einem Namespace zu verschieben, während ein neuer Namespace für JSON geschaffen wird. Da
/<projekt>/definiert wurde, müssten wir diese Namespaces zu ungültigen Projektnamen machen, daher könnten etwas wie/_html/und/_json/funktionieren, dann einfach die nicht-Namespaced-URLs auf den „Standard“ für dieses Repository umleiten (wahrscheinlich HTML, es sei denn, sie haben HTML deaktiviert, dann JSON). - Mit separaten URLs gibt es keine gute Möglichkeit, eine Nullkonfigurationserkennung zu unterstützen, dass ein Repository die JSON-URLs unterstützt, ohne zusätzliche HTTP-Anfragen zu stellen, um festzustellen, ob die JSON-URL existiert oder nicht.
Die naivste Implementierung wäre, die JSON-URL anzufordern und bei jeder einzelnen Anfrage auf die HTML-URL zurückzufallen, aber das wäre furchtbar leistungsschwach und würde das Ziel minimaler zusätzlicher HTTP-Anfragen verletzen.
Die wahrscheinlichste Implementierung wäre, eine Art Repository-Konfigurationsdatei zu erstellen, die irgendwie anzeigt, was unterstützt wird. Wir hätten dasselbe Namespace-Problem wie oben, mit derselben Lösung: etwas wie
/_config.jsonoder so könnte diese Daten enthalten, und ein Client könnte zuerst eine HTTP-Anfrage an diese senden, und wenn sie existiert, herunterladen und parsen, um die Fähigkeiten dieses spezifischen Repositorys zu erfahren. - Die Verwendung von
Accepterlaubt uns auch, die Versionierung in dieses Feld einzubauen
Alles in allem ist es die Meinung dieser PEP, dass diese drei Probleme zusammen die Verwendung separater API-Routen zu einer weniger wünschenswerten Lösung machen als die Abhängigkeit von der Inhaltsaushandlung, um die idealste Darstellung der Daten auszuwählen.
Bedeutet dies, dass statische Server nicht mehr unterstützt werden?
Kurz gesagt, nein, statische Server werden von dieser PEP immer noch (fast) vollständig unterstützt.
Die Einzelheiten der Unterstützung hängen vom betreffenden statischen Server ab. Zum Beispiel
- S3: S3 unterstützt vollständig benutzerdefinierte Inhaltstypen, unterstützt jedoch keine Form der Inhaltsaushandlung. Um einen Server auf S3 zu hosten, müssten Sie die „Endpunktkonfiguration“-Art der Aushandlung verwenden, und Benutzer müssten ihre Clients explizit konfigurieren.
- GitHub Pages: GitHub Pages unterstützt keine benutzerdefinierten Inhaltstypen, daher ist die S3-Lösung derzeit nicht machbar. Das bedeutet, dass nur Repositories vom Typ
text/htmlfunktionieren würden. - Apache: Apache unterstützt vollständig serverseitige Inhaltsaushandlung und müsste nur konfiguriert werden, um die benutzerdefinierten Inhaltstypen bestimmten Erweiterungen zuzuordnen.
Warum nicht einen Alias für application/json wie für text/html hinzufügen?
Diese PEP ist der Meinung, dass es sowohl für Clients als auch für Server am besten ist, explizit über die Typen der verwendeten API-Antworten zu sein, und ein Inhaltstyp wie application/json ist das genaue Gegenteil von explizit.
Die Existenz des Alias text/html existiert als Kompromiss, hauptsächlich um sicherzustellen, dass bestehende Verbraucher der API weiterhin wie gewohnt funktionieren. Es gibt keine solche Erwartung, dass bestehende Clients die Simple API mit einem Inhaltstyp von application/json verwenden.
Darüber hinaus enthält application/json keine Versionierung. Das bedeutet, wenn es jemals eine 2.x-Version der Simple API geben wird, sind wir gezwungen, eine Entscheidung zu treffen. Soll application/json die Abwärtskompatibilität wahren und weiterhin ein Alias für application/vnd.pypi.simple.v1+json sein, oder soll es aktualisiert werden, um ein Alias für application/vnd.pypi.simple.v2+json zu sein?
Dieses Problem existiert nicht für text/html, da die Annahme ist, dass HTML ein Legacy-Format bleiben wird und wahrscheinlich keine neuen Funktionen erhalten wird, geschweige denn Funktionen, die eine inkonsistente Kompatibilität erfordern. So wird es ein Alias für application/vnd.pypi.simple.v1+html sein, was effektiv dasselbe ist, wie wenn es ein Alias für application/vnd.pypi.simple.latest+html wäre, da 1.x wahrscheinlich die einzige HTML-Version sein wird, die existiert.
Der größte Vorteil der Hinzufügung des Inhaltstyps application/json ist, dass es Dinge gibt, die keine benutzerdefinierten Inhaltstypen zulassen und Sie zwingen, einen ihrer voreingestellten Inhaltstypen auszuwählen. Das Hauptbeispiel hierfür ist GitHub Pages. Da diese PEP application/json nicht unterstützt, können statische Repositories nicht mehr auf GitHub Pages gehostet werden, es sei denn, GitHub fügt den Inhaltstyp application/vnd.pypi.simple.v1+json hinzu.
Diese PEP ist der Meinung, dass die Vorteile nicht groß genug sind, um diesen Alias für Inhaltstypen zu diesem Zeitpunkt hinzuzufügen, und dass seine Aufnahme wahrscheinlich ein Fallstrick wäre, der auf ahnungslose Personen wartet, die ihn versehentlich aufgreifen. Insbesondere da wir ihn jederzeit in der Zukunft hinzufügen können, aber das Entfernen von Dingen ist viel schwieriger.
Warum einen application/vnd.pypi.simple.v1+html hinzufügen?
Die PEP erwartet, dass die HTML-Version der API zum Legacy-Format wird. Daher könnte eine Option darin bestehen, den Inhaltstyp application/vnd.pypi.simple.v1+html nicht hinzuzufügen und stattdessen text/html dafür zu verwenden.
Diese PEP hat entschieden, dass die Hinzufügung des neuen Inhaltstyps insgesamt besser ist, da sie selbst das Legacy-Format selbsterklärender macht und beide konsistenter miteinander macht. Insgesamt halte ich es für verwirrender, wenn die +html-Version nicht existiert.
Warum v1.0 und nicht v1.1 oder v2.0?
Diese PEP ist immer noch vollständig abwärtskompatibel mit Clients, die die bestehende v1.0 API lesen konnten; sie können die API auch nach diesen Änderungen weiterhin lesen. In PEP 629 ist die Qualifikation für eine Major-Versionserhöhung
Die Erhöhung der Hauptversion signalisiert eine abwärtsinkompatible Änderung, so dass von bestehenden Clients nicht mehr erwartet wird, dass sie die API sinnvoll nutzen können.
Die Änderungen in dieser PEP erreichen diese Schwelle nicht. Nichts hat sich so geändert, dass von bestehenden Clients nicht mehr erwartet wird, dass sie die API sinnvoll nutzen können.
Das bedeutet, wir sollten uns immer noch innerhalb der v1.x-Versionen befinden.
Die Frage, ob wir v1.1 oder v1.0 sein sollten, ist interessanter und es gibt ein paar Betrachtungsweisen
- Wir haben neue Funktionen für die API freigegeben (der Projektname auf der Projektseite, mehrere Hashes), was ein Zeichen dafür ist, dass wir die Nebenversion erhöhen sollten.
- Die neuen Funktionen existieren ausschließlich innerhalb der JSON-Serialisierung, was bedeutet, dass kein Client, der derzeit die HTML 1.0-Seite anfordert, jemals die neuen Funktionen sehen würde. Für sie ist es also effektiv immer noch v1.0.
- Kein wichtiger Client hat bisher die Unterstützung für PEP 629 implementiert, was bedeutet, dass die Nummerierung der Nebenversionen zu diesem Zeitpunkt weitgehend akademisch ist, da sie dazu dient, Clients Feedback an Endbenutzer zu geben.
Die zweiten und dritten Punkte oben machen den ersten Punkt praktisch bedeutungslos, und damit ist es sinnvoller, alles v1.0 zu nennen und in Zukunft strenger bei der Aktualisierung von Versionen zu sein.
Anhang 1: Umfrage zu abzudeckenden Anwendungsfällen
Dies geschah durch eine Diskussion zwischen den Maintainern von pip, PyPI und bandersnarch, den beiden ersten potenziellen Nutzern der neuen API. So nutzen sie heute die Simple + JSON APIs oder wie sie sie derzeit nutzen wollen
pip:- Liste aller Dateien für eine bestimmte Veröffentlichung
- Metadaten jedes einzelnen Artefakts
- Wurde es zurückgezogen? (
data-yanked) - Was ist
python-requires? (data-python-requires) - Was ist der Hash dieser Datei? (derzeit Hash in der URL)
- Vollständige Metadaten (
data-dist-info-metadata) - [Bonus] Was sind die deklarierten Abhängigkeiten, falls verfügbar (Liste von Strings, null falls nicht verfügbar)?
- Wurde es zurückgezogen? (
bandersnatch- Nutzt heute nur die Legacy JSON API + XMLRPC- Generiert Simple HTML anstatt von PyPI zu kopieren
- Vielleicht ändert sich das mit der neuen API und wir ziehen diese API-Assets verbatim von PyPI.
- Liste aller Dateien für eine bestimmte Veröffentlichung.
- Workout URL für Release-Dateien zum Download
- Metadaten jedes einzelnen Artefakts.
- Schreibt das JSON heute in den Mirror-Speicher (Disk/S3).
- Verwendete erforderliche Metadaten (über die Package-Klasse)
metadata["info"]metadata["last_serial"]metadata["releases"]- digests
- URL
- Verwendete erforderliche Metadaten (über die Package-Klasse)
- Schreibt das JSON heute in den Mirror-Speicher (Disk/S3).
- XML-RPC-Aufrufe (wir würden gerne deprecaten - aber wir denken nicht, dass es in die Simple API gehört)
- [Bonus] Pakete seit Seriennummer X abrufen (oder alle)
- XML-RPC-Aufruf:
changelog_since_serial
- XML-RPC-Aufruf:
- [Bonus] Alle Pakete mit Seriennummer abrufen
- XML-RPC-Aufruf:
list_packages_with_serial
- XML-RPC-Aufruf:
- [Bonus] Pakete seit Seriennummer X abrufen (oder alle)
- Generiert Simple HTML anstatt von PyPI zu kopieren
Anhang 2: Grobe zugrunde liegende Datenmodelle
Diese sind nicht dazu bestimmt, perfekt mit den Server-, Client- oder Wire-Formaten übereinzustimmen. Vielmehr sind dies konzeptionelle Modelle, die in Code umgesetzt wurden, um sie expliziter hinsichtlich der abstrakten Modelle zu machen, die der Repository-API zugrunde liegen, wie sie sich durch PEP 503, PEP 592, PEP 629, PEP 658 und jetzt dieser PEP, PEP 691, entwickelt hat.
Die bestehenden HTML- und die neuen JSON-Serialisierungen dieser Modelle stellen dann dar, wie diese zugrundeliegenden konzeptionellen Modelle auf die tatsächlichen Wire-Formate abgebildet werden.
Wie Server oder Clients diese Daten modellieren, liegt außerhalb des Umfangs dieser PEP.
@dataclass
class Meta:
api_version: Literal["1.0"]
@dataclass
class Project:
# Normalized or Non-Normalized Name
name: str
# Computed in JSON, Included in HTML
url: str | None
@dataclass
class File:
filename: str
url: str
# Limited to a len() of 1 in HTML
hashes: dict[str, str]
gpg_sig: bool | None
requires_python: str | None
@dataclass
class PEP592File(File):
yanked: bool | str
@dataclass
class PEP658File(PEP592File):
# Limited to a len() of 1 in HTML
dist_info_metadata: bool | dict[str, str]
# Simple Index page (/simple/)
@dataclass
class PEP503_Index:
projects: set[Project]
@dataclass
class PEP629_Index(PEP503_Index):
meta: Meta
@dataclass
class Index(PEP629_Index):
pass
# Simple Detail page (/simple/$PROJECT/)
@dataclass
class PEP503_Detail:
files: set[File]
@dataclass
class PEP592_Detail(PEP503_Detail):
files: set[PEP592File]
@dataclass
class PEP629_Detail(PEP592_Detail):
meta: Meta
@dataclass
class PEP658_Detail(PEP629_Detail):
files: set[PEP658File]
@dataclass
class PEP691_Detail(PEP658_Detail):
name: str # Normalized Name
@dataclass
class Detail(PEP691_Detail):
pass
Urheberrecht
Dieses Dokument wird in die Public Domain oder unter die CC0-1.0-Universal-Lizenz gestellt, je nachdem, welche Lizenz permissiver ist.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0691.rst
Zuletzt geändert: 2025-08-20 21:30:45 GMT