PEP 438 – Umstellung auf Hosting von Release-Dateien auf PyPI
- Autor:
- Holger Krekel <holger at merlinux.eu>, Carl Meyer <carl at oddbird.net>
- BDFL-Delegate:
- Richard Jones <richard at python.org>
- Discussions-To:
- Distutils-SIG Liste
- Status:
- Abgelöst
- Typ:
- Prozess
- Thema:
- Packaging
- Erstellt:
- 15-März-2013
- Post-History:
- 19-Mai-2013
- Ersetzt-Durch:
- 470
- Resolution:
- Distutils-SIG Nachricht
Inhaltsverzeichnis
Zusammenfassung
Dieser PEP schlägt einen abwärtskompatiblen Zwei-Phasen-Übergangsprozess vor, um die Installation vom PyPI-Paketindex pypi.python.org (PyPI) zu beschleunigen, zu vereinfachen und zu robustifizieren. Um den Übergang zu erleichtern und die Reibungsverluste auf Client-Seite zu minimieren, sind **keine Änderungen an distutils oder bestehenden Installationstools erforderlich, um von der ersten Übergangsphase zu profitieren, die zu schnelleren, zuverlässigeren Installationen für die meisten bestehenden Pakete führt**.
Die erste Übergangsphase implementiert einfache und explizite Mittel für einen Paket-Maintainer, um zu steuern, welche Release-Datei-Links an gegenwärtige Installationstools ausgeliefert werden. Die erste Phase beinhaltet auch die Implementierung von Analysewerkzeugen für gegenwärtige Pakete, um die Kommunikation mit Paket-Maintainern und die automatisierte Einstellung von Standardmodi zur Steuerung von Release-Datei-Links zu unterstützen. Die erste Phase wird neu registrierte Projekte auf PyPI standardmäßig so einstellen, dass nur Links zu Release-Dateien ausgeliefert werden, die auf PyPI hochgeladen wurden.
Die zweite Übergangsphase betrifft Endbenutzer-Installationstools, die standardmäßig nur auf PyPI gehostete Release-Dateien installieren und den Benutzer informieren sollen, wenn externe Release-Dateien existieren, und eine Wahl anbieten, diese externen Dateien automatisch zu verwenden. Externe Release-Dateien sollen zukünftig zusammen mit einem Prüfsummen-Hash registriert werden, damit Installationstools die Integrität des letztendlichen Downloads überprüfen können (PyPI-gehostete Release-Dateien tragen immer eine solche Prüfsumme).
Alternative PyPI-Serverimplementierungen sollten das neue Verhalten des einfachen Index-Servers aus Phase 1 implementieren, um zu vermeiden, dass Installationstools ihre Release-Links in Phase 2 als extern behandeln.
Begründung
Verlauf und Motivation für externes Hosting
Als PyPI online ging, bot es die Registrierung von Releases an, hatte aber keine Möglichkeit, Release-Dateien selbst zu hosten. Als das Hosting hinzugefügt wurde, gab es noch kein automatisiertes Download-Tool. Als Phillip Eby automatisierte Downloads (über setuptools) implementierte, entschied er sich, Leuten die Verwendung von Download-Hosts ihrer Wahl zu erlauben. Das Finden von extern gehosteten Paketen wurde wie folgt implementiert:
- Der PyPI-Index
simple/für ein Paket enthält alle Links, die durch Scraping aus den long_description-Metadaten dieses Pakets für jede Version gefunden werden. Links in den Metadatenfeldern „Download-URL“ und „Home-page“ erhalten die Attributerel=downloadbzw.rel=homepage. - Jeder dieser Links, dessen Ziel eine Datei ist, deren Name wie eine installierbare Quell- oder Binärdistribution aussieht und dessen Name die Form „packagename-version.ARCHIVEEXT“ hat, wird von Installationstools als potenzielle Installationskandidat betrachtet.
- Ebenso werden alle Links, die mit einem Fragment „#egg=packagename-version“ enden, als Installationskandidat betrachtet.
- Zusätzlich werden die Links
rel=homepageundrel=downloadvon Installationstools gecrawlt und, falls es sich um HTML handelt, selbst nach Release-Datei-Links in den obigen Formaten durchsucht.
Siehe die easy_install-Dokumentation für eine vollständige Beschreibung dieses Verhaltens. [1]
Heute hosten die meisten auf PyPI indizierten Pakete ihre Release-Dateien auf PyPI. Von insgesamt 29.117 Projekten auf PyPI enthalten nur 2.581 (weniger als 10%) Links zu installierbaren Dateien, die nur außerhalb von PyPI verfügbar sind. [2]
Es gibt viele Gründe [3], warum Leute sich für externes Hosting entschieden haben. Um nur einige zu nennen:
- Release-Prozesse und Skripte wurden bereits entwickelt und laden auf externe Seiten hoch
- es dauert zu lange, große Dateien von einigen Orten der Welt hochzuladen
- Exportbeschränkungen, z. B. für kryptobezogene Software
- Unternehmensrichtlinien, die die Bereitstellung von Open-Source-Paketen über eigene Websites erfordern
- Probleme bei der Integration des Hochladens auf PyPI in den eigenen Release-Prozess (wegen Release-Richtlinien)
- Wunsch nach Download-Statistiken, die sich von denen von PyPI unterscheiden
- wahrgenommene schlechte Zuverlässigkeit von PyPI
- Nicht bewusst, dass PyPI das Dateihosting anbietet
Unabhängig von der aktuellen Gültigkeit dieser Gründe gibt es offensichtlich eine Historie, warum Leute Dateien extern hosten und es sogar zeitweise der einzige Weg war, Dinge zu tun. Dieser PEP vertritt die Position, dass es auch heute noch einige gültige Gründe für externes Hosting gibt.
Problem
**Heute müssen Python-Paket-Installer (pip, easy_install, buildout und andere) oft viele Nicht-PyPI-URLs abfragen, auch wenn keine extern gehosteten Dateien vorhanden sind**. Neben der Abfrage der einfachen Indexseiten von pypi.python.org werden auch alle Homepages und Download-Seiten, die jemals mit einer Version eines Pakets angegeben wurden, von einem Installer gecrawlt. Die Notwendigkeit für Installer, externe Seiten zu crawlen, verlangsamt die Installation und macht den Installationsprozess brüchig und unzuverlässig. Diese Seiten und Pakete nehmen auch nicht an der PEP 381-Mirroring-Infrastruktur teil, was die Zuverlässigkeit und Geschwindigkeit von automatisierten Installationsprozessen weltweit weiter verringert.
Die meisten Pakete werden direkt auf pypi.python.org gehostet [2]. Selbst für diese Pakete crawlen Installer immer noch ihre Homepage und Download-URL, falls angegeben. Viele Paket-Uploader sind sich nicht bewusst, dass die Angabe von „homepage“ oder „download-url“ in ihren Paketmetadaten den Installationsprozess für alle Benutzer unnötigerweise verlangsamt.
Die Abhängigkeit von Drittanbieter-Seiten eröffnet auch mehr Angriffsvektoren für die Einschleusung bösartiger Pakete in Seiten, die automatisierte Installationen verwenden. Ein einfacher Angriff könnte einfach darin bestehen, eine alte, nun ungenutzte Homepage-Domain zu erwerben und bösartige Pakete dort zu platzieren. Darüber hinaus kann ein Man-in-the-Middle (MITM)-Angriff zwischen einer Installationsseite und einer der Download-Seiten bösartige Pakete auf der Installationsseite einschleusen. Da viele Homepages und Download-Orte HTTP und nicht HTTPS verwenden, sind solche Angriffe nicht schwer durchzuführen. Solche MITM-Angriffe können leicht auch bei Paketen auftreten, die niemals beabsichtigt haben, Dateien extern zu hosten, da ihre Homepages ohnehin von Installern kontaktiert werden.
Derzeit gibt es keine Möglichkeit für Paket-Maintainer, das Crawling von externen Links zu vermeiden, außer alle Metadaten von Homepage/Download-URL für alle historischen Versionen zu entfernen. Obwohl ein Skript [4] geschrieben wurde, um diese Aktion durchzuführen, ist dies keine gute allgemeine Lösung, da es nützliche Metadaten aus PyPI-Releases entfernt.
Selbst wenn die von „Homepage“- und „Download-URL“-Links referenzierten Seiten nicht nach weiteren Links durchsucht würden, gibt es im aktuellen System keine offensichtliche Möglichkeit für einen Paketbesitzer, auf eine installierbare Datei aus einem Metadatenfeld von long_description (das als Paketdokumentation auf /pypi/PKG angezeigt wird) zu verlinken, ohne dass Installationstools diese Datei automatisch als Installationskandidat betrachten. Umgekehrt gibt es keine Möglichkeit, mehrere externe Release-Dateien explizit zu registrieren, ohne sie in Metadatenfelder zu setzen.
Ziele
Dies sind die Ziele, die durch die Implementierung dieses PEP erreicht werden sollen:
- Paketbesitzer sollten explizit steuern können, welche Dateien PyPI Installationswerkzeugen als Installationskandidaten präsentiert. Die Installation sollte nicht durch umfangreiches und unnötiges Crawling von Links, die Paketbesitzer nicht explizit als Installationsdateien nominiert haben, verlangsamt und weniger zuverlässig gemacht werden.
- Es sollte für Paketbesitzer weiterhin möglich sein, ihre Release-Dateien auf eigenem, extern zu PyPI gehostetem Speicherplatz zu belassen. Es sollte für Benutzer einfach sein, die Installation solcher Releases mit automatisierten Installationstools anzufordern, insbesondere wenn die externen Release-Dateien zusammen mit einem Prüfsummen-Hash registriert wurden.
- Automatisierte Installationstools sollten externe Pakete **nicht standardmäßig** installieren, sondern eine explizite Autorisierung durch den Benutzer erfordern. Wenn Tools die Installation solcher Pakete standardmäßig verweigern, sollten sie dem Benutzer genau mitteilen, welche externen Links der Installer verfolgen muss und welche Optionen der Benutzer bereitstellen kann, um das Tool zum Verfolgen dieser Links zu autorisieren. PyPI sollte alle notwendigen Metadaten für Installationstools bereitstellen, um dies einfach und innerhalb einer einzigen Anfrage/Antwort-Interaktion zu implementieren.
- Die Migration vom Status quo zu den oben genannten Punkten sollte schrittweise erfolgen und Brüche minimieren. Dies beinhaltet Tools, die es Paketbesitzern mit einem bestehenden Release-Prozess, der auf Nicht-PyPI-Hosting hochlädt, erleichtert, diese Release-Dateien auch auf PyPI hochzuladen.
Lösung / zwei Übergangsphasen
Die erste Übergangsphase führt ein „Hosting-Modus“-Feld für jedes Projekt auf PyPI ein, das Paketbesitzern die explizite Kontrolle darüber ermöglicht, welche Release-Datei-Links im maschinenlesbaren simple/-Index an gegenwärtige Installationstools ausgeliefert werden. Die erste Phase wird nach erfolgreichen Hosting-Modus-Änderungen durch einzelne Early-Adopter einen Standard-Hosting-Modus für bestehende Pakete festlegen, basierend auf automatisierter Analyse. **Maintainer werden einen Monat im Voraus über solche automatisierten Änderungen informiert**. Nach Abschluss der ersten Übergangsphase wird **erwartet, dass alle bestehenden Release- und Installationsprozesse und -Tools weiterhin funktionieren**. Verbleibende Fehler oder Probleme werden voraussichtlich nur die Installation einzelner Pakete betreffen und können von Paket-Maintainern oder PyPI-Administratoren leicht korrigiert werden, wenn Maintainer nicht erreichbar sind.
Ebenfalls in der ersten Phase wird jeder Link im simple/-Index explizit als rel="internal" gekennzeichnet, wenn er vom Index selbst gehostet wird (auch wenn er auf einer separaten Domain liegt, was der Fall sein kann, wenn der Index ein CDN zum Dateihosting verwendet). Jeder Link, der nicht so gekennzeichnet ist, wird als externer Link betrachtet.
In der zweiten Übergangsphase sollen die PyPI-Client-Installationstools aktualisiert werden, um standardmäßig nur rel="internal"-Pakete zu installieren, es sei denn, der Benutzer gibt Optionen an, die die Installation von externen Links erlauben. Siehe zweite Übergangsphase für Details, wie Installer sich verhalten sollen.
Maintainer von Paketen, die derzeit Release-Dateien auf Nicht-PyPI-Sites hosten, erhalten Anweisungen und Tools, um das „Re-Hosting“ ihrer historischen und zukünftigen Paket-Release-Dateien zu erleichtern. Dieses Re-Hosting-Tool MUSS verfügbar sein, bevor automatisierte Hosting-Modus-Änderungen für Paket-Maintainer angekündigt werden.
Implementierung
Hosting-Modi
Die Grundlage der ersten Übergangsphase ist die Einführung von drei „Modi“ des PyPI-Hostings für ein Paket, die beeinflussen, welche Links für den simple/-Index generiert werden. Diese Modi werden ohne Änderungen an den Installationstools durch Änderungen am Algorithmus zur Generierung des maschinenlesbaren simple/-Index implementiert.
Die Modi sind:
pypi-scrape-crawl: Keine Änderung gegenüber der aktuellen Situation der Generierung von maschinenlesbaren Links für Installationstools, wie im Verlauf beschrieben.pypi-scrape: Bei einem Paket in diesem Modus werden Links, die demsimple/-Index hinzugefügt werden sollen, immer noch aus Paketmetadaten gescrapt. Die Links „Home-page“ und „Download-url“ erhalten jedoch die Attributerel=ext-homepageundrel=ext-downloadanstelle vonrel=homepageundrel=download. Die Auswirkung davon (ohne notwendige Änderung der Installationstools) ist, dass diese Links von gegenwärtigen Installationstools nicht verfolgt und nach weiteren Kandidaten-Links durchsucht werden: Nur direkt von PyPI gehostete installierbare Dateien oder direkt aus PyPI-Metadaten verlinkte Dateien werden für die Installation berücksichtigt. Installationstools KÖNNEN sich weiterentwickeln, um eine Option anzubieten, die neue rel-Attribuierung zum Durchsuchen externer Seiten zu verwenden, MÜSSEN dies aber nicht standardmäßig tun.pypi-explicit: Bei einem Paket in diesem Modus werden demsimple/-Index nur Links zu auf PyPI hochgeladenen Release-Dateien und externe Links zu explizit vom Paketbesitzer nominierten Release-Dateien hinzugefügt. PyPI stellt eine neue Schnittstelle für Paketbesitzer bereit, um externe Release-Datei-URLs anzugeben. Diese URLs MÜSSEN einen URL-Fragment in der Form „#hashtype=hashvalue“ enthalten, der einen Hash der extern verlinkten Datei angibt, den Installationstools VERWENDEN MÜSSEN, um zu überprüfen, ob sie die beabsichtigte Datei heruntergeladen haben.
Somit besteht die Hoffnung, dass letztendlich alle Projekte auf PyPI in den Modus pypi-explicit migriert werden können, während die Möglichkeit erhalten bleibt, extern gehostete Release-Dateien über Installationstools zu installieren. Die Deprezierung von Hosting-Modi, um schließlich nur den Modus pypi-explicit zuzulassen, wird von diesem PEP NICHT REGELT, wird aber voraussichtlich irgendwann nach erfolgreicher Implementierung der in diesem PEP beschriebenen Übergangsphasen möglich sein. Es wird erwartet, dass die Deprezierung **einen neuen Prozess zur Behandlung von verlassenen Paketen** aufgrund unerreichbarer Maintainer für immer noch beliebte Pakete erfordert.
Erste Übergangsphase (PyPI)
Die vorgeschlagene Lösung besteht aus mehreren Implementierungs- und Kommunikationsschritten:
- Implementierung der oben beschriebenen drei Modi in PyPI, mit einer Schnittstelle für Paketbesitzer zur Auswahl des Modus für jedes Paket und zur Registrierung expliziter externer Datei-URLs.
- Kennzeichnung von Links zu Index-gehosteten Dateien im
simple/-Index mitrel="internal"für Pakete in allen Modi, um es Client-Tools zu erleichtern, diese Links in der zweiten Phase zu unterscheiden. - Hinzufügen eines HTML-Tags
<meta name="api-version" value="2">zu allensimple/-Indexseiten, damit Clients zwischen Indizes, die dierel="internal"-Metadaten bereitstellen, und älteren, die dies nicht tun, unterscheiden können. - Standardmäßige Einstellung aller neu registrierten Pakete auf den Modus
pypi-explicit(Paketbesitzer können bei Bedarf immer noch zu den anderen Modi wechseln). - Bestimmung (durch automatische Analyse [2]), welche Pakete alle installierbaren Dateien auf PyPI selbst verfügbar haben (Gruppe A), welche alle installierbaren Dateien auf PyPI oder direkt über PyPI-Metadaten verlinkt haben (Gruppe B) und welche installierbare Versionen verfügbar haben, die nur über externe HTML-Seiten von Homepage/Download verlinkt sind (Gruppe C).
- Senden von E-Mails an die Maintainer der Projekte in Gruppe A, dass ihr Projekt in einem Monat automatisch auf den Modus
pypi-explicitumgestellt wird, und ähnlich an die Maintainer der Projekte in Gruppe B, dass ihr Projekt automatisch auf den Moduspypi-scrapeumgestellt wird. Informieren, dass diese Änderung voraussichtlich keine Auswirkung auf die Installierbarkeit ihres Projekts hat, aber zu schnelleren und sichereren Installationen für ihre Benutzer führt. Ermutigen, diesen Modus früher selbst einzustellen, um ihren Benutzern Vorteile zu verschaffen. - Senden von E-Mails an die Maintainer der Pakete in Gruppe C, dass ihr Paket-Hosting-Modus
pypi-scrape-crawlist, Auflistung der aktuell gecrawlten URLs und Vorschlag, entweder ihre Pakete direkt auf PyPI neu zu hosten und aufpypi-explicitumzuschalten oder zumindest direkte Links zu Release-Dateien in PyPI-Metadaten bereitzustellen und aufpypi-scrapeumzuschalten. Bereitstellung von Anleitungen und Tools zur Unterstützung dieser Übergänge.
Zweite Übergangsphase (Installer-Tools)
Für die zweite Übergangsphase werden die Maintainer von Installationstools gebeten, zwei Updates zu veröffentlichen.
Das erste Update soll klare Warnungen ausgeben, wenn extern gehostete Release-Dateien (d.h. Dateien, deren Link nicht rel="internal" enthält) für den Download ausgewählt werden, für welche Projekte und URLs genau dies geschieht, und warnen, dass in zukünftigen Versionen extern gehostete Downloads standardmäßig deaktiviert werden.
Das zweite Update soll den Standardmodus ändern, um nur die Installation von rel="internal"-Paketdateien zu erlauben und die Installation von extern gehosteten Paketen nur zu gestatten, wenn der Benutzer eine Option angibt.
Der Installer soll zwischen verifizierbaren und nicht verifizierbaren externen Links unterscheiden. Ein verifizierbarer externer Link ist ein direkter Link zu einer installierbaren Datei aus dem PyPI simple/-Index, der einen Hash im URL-Fragment („#hashtype=hashvalue“) enthält, der zur Überprüfung der Integrität der heruntergeladenen Datei verwendet werden kann. Ein nicht verifizierbarer externer Link ist jeder Link (außer denen, die explizit vom Benutzer eines Installationstools angegeben wurden) ohne Hash, der aus externem HTML gescrapt wurde oder über eine andere Nicht-PyPI-Quelle in die Suche eingeschleust wurde (z. B. die dependency_links-Funktion von setuptools).
Installer sollten eine generelle Option bieten, die Installation aller verifizierbaren externen Links zu erlauben. Nicht verifizierbare externe Links sollten nur dann installiert werden, wenn die vom Benutzer angegebene Option genau festlegt, welche externen Domänen verwendet werden dürfen oder für welche spezifischen Paketnamen externe Links verwendet werden dürfen.
Wenn der Download eines extern gehosteten Pakets aufgrund der Standardkonfiguration nicht zulässig ist, sollte der Benutzer benachrichtigt werden, mit Anweisungen, wie die Installation erfolgreich gemacht werden kann, und Warnungen über die Auswirkungen (dass eine Datei von einer Seite heruntergeladen wird, die nicht Teil des Paketindex ist). Die Warnung für nicht verifizierbare Links sollte klarstellen, dass der Installer die Integrität der heruntergeladenen Datei nicht überprüfen kann. Die Warnung für verifizierbare externe Links sollte lediglich darauf hinweisen, dass die Datei von einer externen URL heruntergeladen wird, aber dass die Dateintegrität per Checksumme überprüft werden kann.
Alternative PyPI-kompatible Indeximplementierungen sollten so bald wie möglich ein Upgrade durchführen, um die Metadaten rel="internal" und den Tag <meta name="api-version" value="2"> bereitzustellen. Für alternative Indizes, die den Meta-Tag in ihren simple/-Seiten noch nicht bereitstellen, sollten Installationstools abwärtskompatibles Fallback-Verhalten bieten (Links wie vor PEP behandeln und eine Warnung ausgeben).
API zum Einreichen externer Distributions-URLs
Neue Distributions-URLs können durch Ausführung eines HTTP POST an die URL eingereicht werden:
Mit den folgenden Formular-kodierten Daten:
| Name | Wert |
| :action | Der String „urls“ |
| name | Der Paketname als String |
| version | Die Release-Version als String |
| new-url | Die neue zu speichernde URL |
| submit_new_url | Der String „yes“ |
Der POST muss von einem HTTP Basic Auth Header begleitet werden, der den Benutzernamen und das Passwort des Benutzers kodiert, der berechtigt ist, das Paket auf PyPI zu warten.
Die HTTP-Antwort auf diese Anfrage wird eine der folgenden sein:
| Code | Bedeutung | URL-Einreichungs-Implikationen |
| 200 | OK | Alles hat einwandfrei funktioniert |
| 400 | Ungültige Anfrage | Die für die Einreichung bereitgestellten Daten waren fehlerhaft |
| 401 | Nicht autorisiert | Der angegebene Benutzername oder das Passwort war falsch |
| 403 | Verboten | Benutzer hat keine Berechtigung, Paketinformationen zu aktualisieren (nicht Owner oder Maintainer) |
Referenzen
Danksagungen
Phillip Eby für präzise Informationen und die grundlegenden Ideen zur Implementierung der Umstellung nur über serverseitige Änderungen.
Donald Stufft für die Abkehr von externem Hosting und die Bereitschaft, sowohl einen Pull Request für die notwendigen PyPI-Änderungen als auch das Analysetool zur Steuerung der Phase 1 der Umstellung zu implementieren.
Marc-Andre Lemburg, Alyssa Coghlan und sig-catalog im Allgemeinen für die Durchdenkung von Problemen im Zusammenhang mit der Abschaffung des „externen Hostings“.
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0438.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT