Zum Hauptinhalt springen

pypaperless v6 - Und wieder ein Reboot

·627 Wörter·3 min
Tobias Schulz
Autor
Tobias Schulz
고생 끝에 낙이 온다 · immer, weiter
Inhaltsverzeichnis

Kurz nach dem Release von Paperless-ngx v3 folgt pypaperless v6 - und diesmal hat es wirklich Konsequenzen. Aufgrund vielerlei Veränderungen in der Paperless-ngx REST API und meinem Unwillen, bis in alle Ewigkeit rückwärts-kompatibel zu sein, traf ich eine Entscheidung. Es gibt Breaking Changes. Und damit meine ich nicht „eine Methode wurde umbenannt", sondern einen tiefgreifenden Umbau der gesamten Bibliothek.

Warum ein Reboot?
#

Wenn ich ehrlich bin, hatte pypaperless in v5 drei Baustellen, über die ich schon länger immer wieder gestolpert bin. Alle drei haben mich genug gestört, um diesmal wirklich von Grund auf neu zu bauen. Und in diesem Anlauf habe ich mein aktuelles Verständnis des SDK Gedanken noch mehr einfließen lassen.

1. Models waren zu eng ans HTTP-Layer gekoppelt
#

In v5 hielt jede Model-Instanz eine Referenz auf den Client und rief ihn intern direkt auf. Das klingt praktisch, führt aber dazu, dass man Models nicht isoliert testen kann und sie auch nicht ohne Kontext weitergeben kann. Das war beim Testen regelmäßig ein Ärgernis.

In v6 sind Models reine Daten - kein Client, keine HTTP-Aufrufe. Der gesamte I/O läuft ausschließlich über Services. Das macht den Code deutlich sauberer und testbarer. Und als kleines Schmankerl habe ich einen kleinen Dispatcher in die PaperlessClient Klasse eingebaut, über den wichtige CRUD-Methoden direkt nutzbar sind.

doc = await paperless.documents(4711)
doc.title = "Ein neuer Titel"
await doc.save()
doc = await paperless.documents(4711)
doc.title = "Ein neuer Titel"
await paperless.save(doc)

2. Keine Typprüfung zur Laufzeit
#

v5 nutzte Dataclasses mit manueller Dict-Konvertierung. Wenn die API unerwartet etwas zurückgab, konnte das jedoch still und heimlich zu falschen Werten führen. Es gab zwar eine Warning in der Konsole, aber das wars 😁.

v6 setzt auf Pydantic v2: Jede API-Antwort wird beim Parsen validiert. Ich muss keinem Python-Entwickler die Vorteile davon erklären.

3. aiohttp raus, httpx rein
#

aiohttp hat seinen Job getan, aber httpx ist moderner, hat eine sauberere API für synchrone und asynchrone Nutzung, und bringt ein eingebautes Mock-Transport-System mit, das das Schreiben von Tests erheblich vereinfacht. Ein Wechsel, der sich auch beim Entwickeln sofort bemerkbar macht.

Als User von pypaperless solltest du diesen Change in den meisten Fällen gar nicht bemerken.

Was ändert sich konkret?
#

Die vollständige Checkliste der Breaking Changes gibt es im Migrationsleitfaden , hier die wichtigsten Punkte:

Python 3.13 ist jetzt Pflicht
#

Wer noch auf <=3.12 läuft, muss vor dem Update die Python-Runtime upgraden.

Neues PaperlessConfig-Objekt und Umgebungsvariablen
#

Der Konstruktor hat sich verändert. Neu ist außerdem die PaperlessConfig-Klasse:

from pypaperless import Paperless, PaperlessConfig

# Via Config-Objekt
cfg = PaperlessConfig(url="http://localhost:8000", token="mytoken")
paperless = Paperless(config=cfg)

# Via Umgebungsvariablen (PYPAPERLESS_URL, PYPAPERLESS_TOKEN)
paperless = Paperless()

filter() statt reduce()
#

reduce() ist weg. Das neue filter() funktioniert ähnlich, aber die Context-Manager-Variable ist jetzt das eigentliche Iterationsobjekt:

filters = {
  "title__icontains": "invoice"
}
async with paperless.documents.reduce(**filters):
    async for doc in paperless.documents:
        print(doc.title)
filters = {
  "title__icontains": "invoice"
}
async with paperless.documents.filter(**filters) as ctx:
    async for doc in ctx:
        print(doc.title)

Erstellen neuer Models
#

draft() heißt jetzt create().

Was ist neu?
#

Neben dem Umbau kommen sechs neue Services dazu:

  • paperless.profile - Zugriff auf das eigene Benutzerprofil
  • paperless.trash - Gelöschte Dokumente durchsuchen, wiederherstellen oder den Papierkorb leeren
  • paperless.share_links - Share-Links für Dokumente erstellen und verwalten
  • paperless.documents.history - Audit-Log eines Dokuments abrufen
  • paperless.documents.bulk_edit - Massenoperationen auf vielen Dokumenten in einem einzigen API-Aufruf
  • paperless.bulk_edit_objects - Berechtigungen oder Löschvorgänge auf Tags, Korrespondenten, Dokumenttypen und Speicherpfaden in Masse

Fazit
#

v6 ist kein kleines Pflaster. Ich bin mit den Neuerungen und Änderungen sehr glücklich. Der Preis dafür ist eine Migration, die für bestehende User etwas Arbeit bedeutet.

Der Migrationsleitfaden führt Schritt für Schritt durch alle Änderungen.

Viel Spaß mit pypaperless v6!


Das Titel-/Hintergrundbild stammt von Chris Ried auf Unsplash.

Verwandte Artikel