PEP 423 – Namenskonventionen und Rezepte im Zusammenhang mit Packaging
- Autor:
- Benoit Bryon <benoit at marmelune.net>
- Discussions-To:
- Distutils-SIG Liste
- Status:
- Verschoben
- Typ:
- Informational
- Thema:
- Packaging
- Erstellt:
- 24. Mai 2012
- Post-History:
Inhaltsverzeichnis
- Zusammenfassung
- PEP Verschiebung
- Terminologie
- Beziehung zu anderen PEPs
- Übersicht
- Im Zweifelsfall fragen
- Top-Level-Namespace bezieht sich auf Code-Besitz
- Einen einzelnen Namen verwenden
- PEP 8 für die Syntax von Paket- und Modulnamen folgen
- Merkwürdige Namen wählen
- Bedeutungsvolle Namen wählen
- Packaging-Metadaten verwenden
- Tiefe Verschachtelung vermeiden
- Konventionen für Communities oder verwandte Projekte
- Namen bei PyPI registrieren
- Rezepte
- Referenzen
- Urheberrecht
Zusammenfassung
Dieses Dokument befasst sich mit
- Namen von Python-Projekten,
- Namen von verteilten Python-Paketen oder Modulen,
- Namespace-Paketen.
Es bietet Richtlinien und Rezepte für Distributionsautoren
- neue Projekte sollten den Richtlinien unten folgen.
- bestehende Projekte sollten sich dieser Richtlinien bewusst sein und können spezifischen Rezepten für bestehende Projekte folgen.
PEP Verschiebung
Weitere Überlegungen zu diesem PEP wurden mindestens bis nach der Klärung von PEP 426 (Paketmetadaten 2.0) und verwandten Aktualisierungen zurückgestellt.
Terminologie
Referenz ist Packaging-Terminologie in der Python-Dokumentation.
Beziehung zu anderen PEPs
- PEP 8 befasst sich mit dem Styleguide für Code, einschließlich der Namen von Python-Paketen und -Modulen. Er behandelt die Syntax von Paket-/Modulnamen.
- PEP 345 befasst sich mit Packaging-Metadaten und definiert das Argument `name` der Funktion
packaging.core.setup(). - PEP 420 befasst sich mit Namespace-Paketen. Er bringt Unterstützung für Namespace-Pakete in den Python-Kern. Zuvor wurden Namespace-Pakete von externen Bibliotheken implementiert.
- PEP 3108 befasst sich mit dem Übergang von Python 2.x zu Python 3.x in der Standardbibliothek: einige Module sollten gelöscht, einige umbenannt werden. Er weist darauf hin, dass Namenskonventionen wichtig sind und ist ein Beispiel für einen Übergangsplan.
Übersicht
Hier ist eine zusammenfassende Liste von Richtlinien, die Sie bei der Wahl von Namen befolgen sollten
- den Zweck von Namespaces verstehen und respektieren.
- wenn Ihr Projekt mit einem anderen Projekt oder einer Community zusammenhängt
- nach Konventionen in der Hauptprojektdokumentation suchen, da Projekte Community-Beiträge organisieren sollten.
- spezifischen Projekt- oder verwandten Community-Konventionen folgen, falls vorhanden.
- wenn keine Konvention existiert, einem Standardbenennungsmuster folgen.
- sicherstellen, dass Ihr Projektname eindeutig ist, d.h. Duplikate vermeiden
- sicherstellen, dass verteilte Paket- und Modulnamen eindeutig sind, es sei denn, Sie möchten explizit Alternativen zu bestehenden Paketen oder Modulen verteilen. Die Verwendung desselben Wertes für Paket-/Modulnamen und Projektname ist der empfohlene Weg, dies zu erreichen.
- nur ein Paket oder Modul pro Verteilung liefern, es sei denn, Sie wissen, was Sie tun. Dies ermöglicht die Anwendung der Regel „einen Namen verwenden“ und somit konsistente Namen.
- Ihr Projekt leicht auffindbar und erinnerbar machen
- tiefe Verschachtelung vermeiden. Flache Dinge sind einfacher zu verwenden und zu merken als verschachtelte.
- eine oder zwei Namespace-Ebenen werden empfohlen, da sie fast immer ausreichen.
- auch wenn nicht empfohlen, sind drei Ebenen de facto ein häufiger Fall.
- in den meisten Fällen sollten Sie nicht mehr als drei Ebenen benötigen.
- PEP 8 folgen für die Syntax von Paket- und Modulnamen.
- Wenn Sie spezifischen Konventionen gefolgt sind oder wenn Ihr Projekt dazu bestimmt ist, Beiträge aus der Community zu erhalten, organisieren Sie Community-Beiträge.
- wenn Sie immer noch unsicher sind, fragen Sie.
Im Zweifelsfall fragen
Wenn Sie sich nach dem Lesen dieses Dokuments unsicher fühlen, fragen Sie die Python-Community im IRC oder auf einer Mailingliste.
Top-Level-Namespace bezieht sich auf Code-Besitz
Dies hilft, Kollisionen zwischen Projektnamen zu vermeiden.
Besitz kann sein
- eine Einzelperson. Beispiel: gp.fileupload gehört und wird von Gael Pasgrimaud gepflegt.
- eine Organisation. Beispiele
- zest.releaser gehört und wird von Zest Software gepflegt.
- Django gehört und wird von der Django Software Foundation gepflegt.
- eine Gruppe oder Community. Beispiel: sphinx wird von den Entwicklern des Sphinx-Projekts gepflegt, nicht nur von seinem Autor Georg Brandl.
- eine Gruppe oder Community, die mit einem anderen Paket verbunden ist. Beispiel: collective.recaptcha gehört seinem Autor: David Glick, Groundwire. Aber der „collective“-Namespace gehört der Plone-Community.
Besitz respektieren
Verstehen Sie den Zweck eines Namespaces, bevor Sie ihn verwenden.
Schließen Sie sich keinem Namespace an, der Ihnen nicht gehört, es sei denn, dies ist ausdrücklich genehmigt.
Verbinden Sie sich beispielsweise nicht mit dem „django.contrib“-Namespace, da dieser von den Kernbeitragenden von Django verwaltet wird.
Ausnahmen können von Projektverfassern definiert werden. Siehe Community-Beiträge organisieren unten.
Diese Regel gilt auch für Nicht-Python-Projekte.
Verwenden Sie beispielsweise nicht „apache“ als Top-Level-Namespace: „Apache“ ist der Name eines bestehenden Projekts (im Fall von „Apache“ ist es auch eine Marke).
Private (einschließlich Closed-Source) Projekte verwenden einen Namespace
… weil private Projekte jemandem gehören. Wenden Sie also die Besitzregel an.
Für interne/Kundenprojekte verwenden Sie den Namen Ihres Unternehmens als Namespace.
Diese Regel gilt für Closed-Source-Projekte.
Wenn Sie beispielsweise ein Projekt „climbing“ für das Unternehmen „Python Sport“ erstellen: Verwenden Sie den Namen „pythonsport.climbing“, auch wenn es Closed Source ist.
Individuelle Projekte verwenden einen Namespace
… weil sie Einzelpersonen gehören. Wenden Sie also die Besitzregel an.
Es gibt keine Schande, ein Projekt als Open Source zu veröffentlichen, auch wenn es einen „internen“ oder „individuellen“ Namen hat.
Wenn das Projekt an einem Punkt angelangt ist, an dem der Autor den Besitz ändern möchte (d. h. das Projekt gehört nicht mehr einer Einzelperson), denken Sie daran, dass es einfach ist, das Projekt umzubenennen.
Community-eigene Projekte können Namespace-Pakete vermeiden
Wenn Ihr Projekt generisch genug ist (d. h. es ist kein Beitrag zu einem anderen Produkt oder Framework), können Sie Namespace-Pakete vermeiden. Die Grundbedingung ist im Allgemeinen, dass Ihr Projekt einer Gruppe (d. h. dem Entwicklungsteam) gehört, die sich diesem Projekt widmet.
Verwenden Sie nur einen „gemeinsamen“ Namespace, wenn Sie wirklich beabsichtigen, dass der Code gemeinschaftseigen ist.
Zum Beispiel gehört das Projekt sphinx dem Sphinx-Entwicklungsteam. Es besteht keine Notwendigkeit, ein „sphinx“-Namespace-Paket mit nur einem Projekt „sphinx.sphinx“ darin zu haben.
Im Zweifelsfall einen individuellen/organisatorischen Namespace verwenden
Wenn Ihr Projekt wirklich experimentell ist, ist die beste Wahl die Verwendung eines individuellen oder organisatorischen Namespace
- es ermöglicht frühe Veröffentlichungen von Projekten.
- es wird einen Namen nicht blockieren, wenn das Projekt aufgegeben wird.
- es blockiert keine zukünftigen Änderungen. Wenn ein Projekt reif wird und es keinen Grund mehr gibt, den individuellen Besitz beizubehalten, bleibt es möglich, das Projekt umzubenennen.
Einen einzelnen Namen verwenden
Liefern Sie nur ein Paket (oder nur ein Modul) pro Projekt und verwenden Sie den Paket- (oder Modul-) Namen als Projektnamen.
- Es vermeidet mögliche Verwechslungen zwischen Projektname und verteiltem Paket- oder Modulnamen.
- Es macht den Namen konsistent.
- Es ist explizit: Wenn man den Projektnamen sieht, errät man den Paket-/Modulnamen und umgekehrt.
- Es begrenzt auch implizite Kollisionen zwischen Paket-/Modulnamen. Durch die Verwendung eines einzelnen Namens, wenn Sie einen Projektnamen bei PyPI registrieren, führen Sie auch eine grundlegende Überprüfung der Paket-/Modulnamenverfügbarkeit durch.
Beispielsweise verteilen pipeline, python-pipeline und django-pipeline alle ein Paket oder Modul namens „pipeline“. Das Installieren von zweien davon führt zu Fehlern. Dieses Problem wäre nicht aufgetreten, wenn diese Distributionen einen einzelnen Namen verwendet hätten.
Ja
- Paketname: „kheops.pyramid“, d.h.
import kheops.pyramid - Projektname: „kheops.pyramid“, d.h.
pip install kheops.pyramid
Nein
- Paketname: „kheops“
- Projektname: „KheopsPyramid“
Hinweis
Aus historischen Gründen enthält PyPI viele Distributionen, bei denen Projekt- und verteilte Paket-/Modulnamen unterschiedlich sind.
Mehrere Pakete/Module sollten selten sein
Technisch gesehen können Python-Distributionen mehrere Pakete und/oder Module bereitstellen. Siehe Setup-Skript-Referenz für Details.
Einige Distributionen tun dies tatsächlich. Zum Beispiel deklarieren setuptools und distribute neben den jeweiligen Paketen „setuptools“ und „distribute“ auch die Module „pkg_resources“, „easy_install“ und „site“.
Betrachten Sie diesen Anwendungsfall als Ausnahme. In den meisten Fällen benötigen Sie diese Funktion nicht. Daher sollte eine Distribution nur ein Paket oder Modul gleichzeitig bereitstellen.
Unterschiedliche Namen sollten selten sein
Eine bemerkenswerte Ausnahme von der Regel Einen einzelnen Namen verwenden ist, wenn Sie explizit unterschiedliche Namen benötigen.
Zum Beispiel bietet das Projekt Pillow eine Alternative zur ursprünglichen PIL-Distribution. Beide Projekte verteilen ein „PIL“-Paket.
Betrachten Sie diesen Anwendungsfall als Ausnahme. In den meisten Fällen benötigen Sie diese Funktion nicht. Daher sollte der Name eines verteilten Pakets mit dem Projektnamen übereinstimmen.
PEP 8 für die Syntax von Paket- und Modulnamen folgen
PEP 8 gilt für die Namen von Python-Paketen und -Modulen.
Wenn Sie einen einzelnen Namen verwenden, gilt PEP 8 auch für Projektnamen. Ausnahmen sind Namespace-Pakete, bei denen Punkte im Projektnamen erforderlich sind.
Merkwürdige Namen wählen
Eine wichtige Sache bei einem Projektnamen ist, dass er merkwürdig ist.
Zum Beispiel ist celery kein aussagekräftiger Name. Zuerst ist es nicht offensichtlich, dass es sich um Nachrichtenwarteschlangen handelt. Aber es ist merkwürdig, teilweise weil es verwendet werden kann, um einen RabbitMQ-Server zu speisen.
Bedeutungsvolle Namen wählen
Fragen Sie sich „Wie würde ich in einem Satz beschreiben, wofür dieser Name ist?“, und dann „Könnte jemand das erraten, indem er den Namen ansieht?“.
Zum Beispiel ist DateUtils ein aussagekräftiger Name. Es ist offensichtlich, dass es sich um Dienstprogramme für Daten handelt.
Wenn Sie Namespaces verwenden, versuchen Sie, jeden Teil aussagekräftig zu gestalten.
Packaging-Metadaten verwenden
Betrachten Sie Projektnamen als eindeutige Identifikatoren auf PyPI
- es ist wichtig, dass diese Identifikatoren lesbar bleiben.
- es ist noch besser, wenn diese Identifikatoren aussagekräftig sind.
- aber der Hauptzweck von Identifikatoren ist nicht, Projekte zu klassifizieren oder zu beschreiben.
Klassifikatoren und Schlüsselwort-Metadaten sind für die Kategorisierung von Distributionen gedacht. Zusammenfassungs- und Beschreibungsmetadaten sollen das Projekt beschreiben.
Zum Beispiel gibt es den Klassifikator „Framework :: Twisted“. Auch wenn die Namen recht heterogen sind (sie folgen keinem bestimmten Muster), erhalten wir die Liste.
Um Community-Beiträge zu organisieren, sind Konventionen über Namen und Namespaces wichtig, aber Konventionen über Metadaten sollten noch wichtiger sein.
Als Beispiel finden wir Portlets in Plone an vielen Stellen
- plone.portlet.*
- collective.portlet.*
- collective.portlets.*
- collective.*.portlets
- einige vendor-spezifische Projekte wie „quintagroup.portlet.cumulus“
- und sogar Projekte, bei denen das Muster „portlet“ nicht im Namen vorkommt.
Auch wenn die Plone-Community Konventionen hat, ist die Verwendung des Namens zur Kategorisierung von Distributionen unangemessen. Es ist unmöglich, die vollständige Liste der Distributionen, die Portlets für Plone bereitstellen, durch Filterung nach Namen zu erhalten. Aber es wäre möglich, wenn all diese Distributionen den Klassifikator „Framework :: Plone“ und das Schlüsselwort „portlet“ verwenden würden.
Tiefe Verschachtelung vermeiden
The Zen of Python besagt „Flach ist besser als verschachtelt“.
Zwei Ebenen sind fast immer genug
Definieren Sie nicht alles in tief verschachtelten Hierarchien: Sie werden am Ende bei Projekten und Paketen wie „pythonsport.common.maps.forest“ landen. Diese Art von Namen ist sowohl sperrig als auch umständlich (z. B. wenn Sie viele Importe aus dem Paket haben).
Darüber hinaus neigen große Hierarchien dazu, im Laufe der Zeit zusammenzubrechen, da die Grenzen zwischen verschiedenen Paketen verschwimmen.
Der Konsens ist, dass zwei Verschachtelungsebenen bevorzugt werden.
Zum Beispiel haben wir plone.principalsource anstelle von plone.source.principal oder etwas Ähnlichem. Der Name ist kürzer, die Paketstruktur ist einfacher, und es gäbe wenig zu gewinnen, drei Verschachtelungsebenen hier zu haben. Es wäre unpraktisch zu versuchen, alle „Kern-Plone“-Quellen (eine Quelle ist eine Art Vokabular) in den Namespace plone.source.* aufzunehmen, zum Teil, weil einige Quellen Teil anderer Pakete sind, und zum Teil, weil Quellen bereits an anderer Stelle existieren. Hätten wir einen neuen Namespace geschaffen, wäre er von Anfang an inkonsistent verwendet worden.
Ja: „pyranha“
Ja: „pythonsport.climbing“
Ja: „pythonsport.forestmap“
Nein: „pythonsport.maps.forest“
Nur eine Ebene für den Besitz verwenden
Verwenden Sie keine 3 Ebenen, um individuelle/organisatorische Zugehörigkeit in einem Community-Namespace festzulegen.
Als Beispiel betrachten wir
- Sie schließen sich einem Community-Namespace an, wie z. B. „collective“.
- und Sie möchten eine restriktivere „Besitz“-Ebene hinzufügen, um Kollisionen innerhalb der Community zu vermeiden.
In diesem Fall **verwenden Sie besser die restriktivste Besitzebene als erste Ebene.**
Zum Beispiel, wo „collective“ ein großer Community-Namespace ist, zu dem „gergovie“ gehört, und „vercingetorix“ der Name des Autors von „gergovie“ ist
Nein: „collective.vercingetorix.gergovie“
Ja: „vercingetorix.gergovie“
Keine Namespace-Ebenen zur Kategorisierung verwenden
Verwenden Sie Packaging-Metadaten stattdessen.
Nicht mehr als 3 Ebenen verwenden
Technisch gesehen können Sie tief verschachtelte Hierarchien erstellen. In den meisten Fällen benötigen Sie dies jedoch nicht.
Hinweis
Selbst Communities, in denen Namespaces Standard sind, verwenden nicht mehr als 3 Ebenen.
Namen bei PyPI registrieren
PyPI ist der zentrale Ort für Distributionen in der Python-Community. Daher ist es auch der Ort, an dem Projekt- und Paketnamen registriert werden.
Siehe Registrierung beim Paketindex für Details.
Rezepte
Die folgenden Rezepte helfen Ihnen, die oben genannten Richtlinien und Konventionen zu befolgen.
Wie prüft man die Verfügbarkeit von Namen?
Bevor Sie einen Projektnamen wählen, stellen Sie sicher, dass er nicht bereits an den folgenden Orten registriert ist
- PyPI
- das ist alles. PyPI ist der einzige offizielle Ort.
Sie könnten zum Beispiel auch an verschiedenen Orten wie beliebten Code-Hosting-Diensten nachschauen, aber denken Sie daran, dass PyPI der einzige Ort ist, an dem Sie sich für Namen in der Python-Community **registrieren** können.
Deshalb ist es wichtig, dass Sie Namen bei PyPI registrieren.
Stellen Sie auch sicher, dass die Namen der verteilten Pakete oder Module nicht bereits registriert wurden
- in der Python Standard Library.
- in Projekten bei
PyPI. Es gibt derzeit keine Hilfestellung dafür. Beachten Sie, dass es umso einfacher ist, die Überprüfung, je mehr Projekte der Regel einen einzelnen Namen verwenden folgen. - Sie können die Community fragen.
Die Regel einen einzelnen Namen verwenden hilft Ihnen auch, Kollisionen mit Paketnamen zu vermeiden: Wenn ein Projektname verfügbar ist, hat der Paketname gute Chancen, ebenfalls verfügbar zu sein.
Wie benennt man ein Projekt um?
Das Umbenennen eines Projekts ist möglich, aber denken Sie daran, dass dies einige Verwirrung stiften wird. Achten Sie daher besonders auf README und Dokumentation, damit die Benutzer verstehen, was passiert ist.
- Zunächst einmal: **Entfernen Sie keine Legacy-Distributionen aus PyPI**. Denn einige Benutzer verwenden sie möglicherweise.
- Kopieren Sie das Legacy-Projekt, ändern Sie dann die Namen (Projekt und Paket/Modul). Achten Sie mindestens auf
- Packaging-Dateien,
- Ordnernamen, die Quelldateien enthalten,
- Dokumentation, einschließlich README,
- Importanweisungen im Code.
- Weisen Sie der neuen Distribution die Metadaten
Obsoletes-Distin der Datei setup.cfg zu. Siehe PEP 345 zu Obsolete-Dist und setup.cfg-Spezifikation. - Veröffentlichen Sie eine neue Version des umbenannten Projekts und veröffentlichen Sie sie dann.
- Bearbeiten Sie das Legacy-Projekt
- fügen Sie eine Abhängigkeit zum neuen Projekt hinzu,
- entfernen Sie alles außer den Packaging-Elementen,
- fügen Sie den Klassifikator
Development Status :: 7 - Inactiveim Setup-Skript hinzu, - veröffentlichen Sie eine neue Version.
Daher können Benutzer des Legacy-Pakets
- Legacy-Distributionen weiterhin in einer veralteten Version verwenden,
- können auf die letzte Version der Legacy-Distribution upgraden, die leer ist…
- … und laden automatisch die neue Distribution als Abhängigkeit des Legacy-Projekts herunter.
Benutzer, die das Legacy-Projekt entdecken, sehen, dass es inaktiv ist.
Verbesserte Handhabung umbenannter Projekte auf PyPI
Wenn viele Projekte dem Rezept Umbenennungs-Howto folgen, dann werden viele Legacy-Distributionen folgende Eigenschaften haben
- Klassifikator
Development Status :: 7 - Inactive. - letzte Version ist leer, bis auf die Packaging-Elemente.
- letzte Version „leitet weiter“ auf eine andere Distribution. Z.B. hat sie eine einzige Abhängigkeit vom umbenannten Projekt.
- referenziert als
Obsoletes-Distin einer neueren Distribution.
So wird es möglich sein, umbenannte Projekte zu erkennen und die Lesbarkeit auf PyPI zu verbessern. So dass Benutzer sich auf aktive Distributionen konzentrieren können. Aber diese Funktion ist derzeit nicht erforderlich. Es gibt keine Eile. Sie wird in diesem Dokument nicht behandelt.
Wie wendet man Namensrichtlinien auf bestehende Projekte an?
Es gibt keine Verpflichtung für bestehende Projekte, umbenannt zu werden. Die Wahl liegt bei den Projektverfassern und Maintainern aus offensichtlichen Gründen.
Projektverfasser werden jedoch eingeladen
- zumindest Stand zur aktuellen Benennung.
- dann Planung und Förderung der Migration.
- optional tatsächlich bestehende Projekte oder verteilte Pakete/Module umbenennen.
Stand zur aktuellen Benennung
Das Wichtigste ist zunächst, dass Sie sich zu den aktuellen Entscheidungen äußern
- Fragen Sie sich: „Warum habe ich den aktuellen Namen gewählt?“, dann dokumentieren Sie es.
- Wenn es Unterschiede zu den in diesem Dokument enthaltenen Richtlinien gibt, sollten Sie Ihre Benutzer informieren.
- Erstellen Sie, wenn möglich, Issues im Bugtracker des Projekts, zumindest zur Dokumentation. Dann können Sie sie später lösen oder als „wontfix“ markieren.
Projekte, die Beiträge aus der Community erhalten sollen, sollten auch Community-Beiträge organisieren.
Migrationen fördern
Jeder Python-Entwickler sollte, wann immer möglich, migrieren oder Migrationen in seinen jeweiligen Communities fördern.
Wenden Sie diese Richtlinien auf Ihre Projekte an, dann wird die Community sehen, dass es sicher ist.
Insbesondere „Führer“ wie Autoren beliebter Projekte sind einflussreich, sie haben Macht und damit Verantwortung über Communities.
Wenden Sie diese Richtlinien auf beliebte Projekte an, dann werden Communities die Konventionen ebenfalls übernehmen.
Projekte sollten Migrationen fördern, wenn sie eine neue (Haupt-)Version veröffentlichen, insbesondere wenn diese Version Unterstützung für Python 3.x, neues Packaging der Standardbibliothek oder Namespace-Pakete einführt.
Gelegenheit
Da Python 3.3 entwickelt wird
- sind viele Projekte nicht Python 3.x-kompatibel. Dazu gehören „große“ Produkte oder Frameworks. Das bedeutet, dass viele Projekte eine Migration durchführen müssen, um Python 3.x zu unterstützen.
- Packaging (aka distutils2) steht in den Startlöchern. Wenn es veröffentlicht wird, werden Projekte aufgefordert, zu migrieren und neues Packaging zu verwenden.
- PEP 420 bringt offizielle Unterstützung für Namespace-Pakete nach Python.
Das bedeutet, dass die meisten aktiven Projekte in den nächsten Jahren migrieren sollten, um Python 3.x, neues Packaging oder neue Namespace-Pakete zu unterstützen.
Eine solche Gelegenheit ist einzigartig und wird nicht so bald wiederkommen! Lassen Sie uns also Namenskonventionen so schnell wie möglich (d.h. **jetzt**) einführen und fördern.
Referenzen
Zusätzlicher Hintergrund
- Martin Aspelis Artikel über Namen. Einige Teile dieses Dokuments sind Zitate aus diesem Artikel.
- in Entwicklung offizielle Dokumentation zum Packaging.
- The Hitchhiker’s Guide to Packaging, das einen leeren Platzhalter für „Namensspezifikation“ enthält.
Referenzen und Fußnoten
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0423.rst
Zuletzt geändert: 2025-05-03 18:09:21 GMT