Files
pdf-ocr-hotfolder/CHANGELOG.md
T
techadmin 578472872e fix: Fehlerzaehlung, Upload-Fehler und ocr.timeout scharf (v0.4.0)
- [ocr].timeout wird als tesseract_timeout (pro Seite) an ocrmypdf
  durchgereicht; Default 1800 -> 300, 0 = ocrmypdf-Default
- Exceptions nach dem OCR zaehlen als Fehler, Datei wird nach error/ gerettet
- Fehlgeschlagene Uploads zaehlen als Fehler und loesen Fehler-Mail aus
- name_mode wird im Preflight geprueft, nicht erst pro Datei
- Fehlende [paths]-Sektion -> ConfigError mit klarer Meldung statt KeyError
- Stabilitaets-Timeout zaehlt als Fehler (--once liefert Exit 1)
- upload_folder nutzt shutil.copyfile statt read_bytes/write_bytes
- OcrConfig.pdfa_level Default "2" -> "" (Ghostscript-Bug, Issue #3)
- 35 neue Tests (92 gesamt), pytest.ini
- AI_AGENT_BRIEFING.md auf Stand 0.4.0 gebracht

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:01:38 +02:00

7.9 KiB
Raw Blame History

Changelog

[0.4.0] - 2026-09-22

Added

  • [ocr].timeout ist jetzt wirksam: der Wert wird als tesseract_timeout (Sekunden pro Seite) an ocrmypdf durchgereicht. Bisher war der Key zwar dokumentiert, wurde aber nirgends gelesen.
  • check_output_config() validiert zusätzlich [output].name_mode. Ein Tippfehler führt jetzt beim Start zum Abbruch mit Exit-Code 2, statt erst pro Datei zuzuschlagen — und zwar bisher nach dem Verschieben nach working/, wo die Datei dann liegen blieb.
  • Neue Exception ConfigError in pdf_ocr_hotfolder.config — fehlende [paths]-Sektion oder ein fehlender Pfad-Eintrag liefern eine deutsche Fehlermeldung mit Datei- und Key-Nennung statt eines nackten KeyError-Tracebacks. Die CLI bricht damit sauber mit Exit-Code 2 ab.
  • pytest.ini mit testpaths = tests, damit pytest aus dem Repo-Root läuft.
  • 35 neue Tests: Fehlerzählung (Exception, Upload, Stabilitäts-Timeout), Config-Fehlermeldungen, tesseract_timeout-Durchreichung (ocrmypdf gemockt) und upload_folder().

Changed

  • [ocr].timeout hat eine neue Bedeutung — für bestehende Installationen relevant! Der Wert ist kein (nie implementiertes) Gesamt-Timeout pro PDF mehr, sondern das Limit pro Seite für Tesseract. Der Default sinkt entsprechend von 1800 auf 300. Wer den alten Wert 1800 in seiner config.toml stehen hat, gibt Tesseract damit 30 Minuten je Seite — bitte auf einen Seiten-Wert anpassen (Richtwert 300). 0 bedeutet "kein eigenes Limit": der Wert wird dann gar nicht erst durchgereicht, weil ocrmypdf tesseract_timeout=0 als "OCR komplett überspringen" interpretiert.
  • _dispatch_uploads() liefert jetzt die Namen der fehlgeschlagenen Upload-Ziele zurück; die doppelte enabled-Prüfung (Service + Uploader) ist entfallen — die Uploader prüfen das selbst.
  • upload_folder() kopiert mit shutil.copyfile() statt read_bytes()/write_bytes() — große PDFs landen nicht mehr komplett im Speicher. Die Selbst-Ziel-Erkennung bleibt unverändert.

Fixed

  • OcrConfig.pdfa_level hatte im Code noch den Default "2", obwohl config.example.toml seit 0.2.2 bewusst "" setzt (Ghostscript-Bug, Issue #3). Eine Config ohne [ocr]-Sektion bzw. ohne den Key lief damit ungewollt in PDF/A. Default im Code jetzt ebenfalls "".
  • Eine Exception nach dem OCR (z.B. ein fehlgeschlagener shutil.move() nach outgoing/) wurde nur im Worker-Callback geloggt. error_count blieb 0 und --once lieferte trotz Fehlschlag Exit-Code 0. Jede Exception aus process_pdf() zählt jetzt als Fehler, wird geloggt, löst eine Fehler-Mail aus und die Datei wandert — soweit noch auffindbar (incoming/ oder working/) — nach error/.
  • Fehlgeschlagene Uploads waren folgenlos: die Rückgabewerte der Uploader wurden verworfen, es ging sogar eine Erfolgs-Mail raus. Jetzt zählt mindestens ein fehlgeschlagenes Ziel als Fehler und die E-Mail geht als FEHLER raus, mit Nennung der betroffenen Ziele. Das OCR-PDF bleibt bewusst in outgoing/ liegen (das OCR selbst war ja erfolgreich) — das steht so auch im Log.
  • Lief der Stabilitäts-Check einer Datei in den 60-Sekunden-Timeout, gab es nur ein log.warning; --once meldete Exit-Code 0. Jetzt log.error + error_count. Die Datei bleibt bewusst in incoming/ liegen und wird beim nächsten Lauf erneut versucht. Eine zwischenzeitlich verschwundene Datei wird davon unterschieden und zählt weiterhin nicht als Fehler.

[0.3.1] - 2026-04-10

Fixed

  • Issue #4: LXC/Container-Kompatibilität — systemd-Hardening (PrivateTmp, ProtectSystem, etc.) verursacht Error 226/NAMESPACE in LXC-Containern. Installer erkennt Container-Umgebung automatisch und bietet ein Drop-in an. Zusätzlich liegt systemd/lxc-compat.conf als Vorlage im Repo.
  • Issue #5: WorkingDirectory=/opt/pdf-ocr-hotfolder in der systemd Template-Unit ergänzt — ohne diesen Eintrag konnte das Python-Modul nicht gefunden werden.
  • Issue #6: Auf Debian 12 bietet der Installer bei betroffenen Ghostscript-Versionen (10.0.0–10.02.0) jetzt automatisch an, bookworm-backports zu aktivieren und GS zu upgraden (statt nur zu warnen).

[0.3.0] - 2026-04-09

Added

  • Neue Config-Sektion [output] mit:
    • name_mode — Platzierung des Tags im Dateinamen: "prefix", "suffix" (vor Extension), "none"
    • name_tag — verbatim einzufügender String, z.B. "OCR_" oder "_OCR"
    • original_on_success — "delete" (alter Default) oder "archive"
    • archive_dir — Zielverzeichnis für "archive", mit Kollisions-Schutz (Timestamp-Suffix)
  • Runtime-Validierung der Output-Config in check_output_config()
  • 20 neue Tests für build_output_name(), check_output_config() und process_pdf() mit allen Kombinationen aus Modus + Original-Behandlung

Changed

  • process_pdf() nimmt jetzt output_cfg: OutputConfig als Pflicht-Argument

[0.2.2] - 2026-04-09

Fixed

  • Issue #3: Ghostscript 10.0.0–10.02.0 (Debian 12 default) zerschießen OCR mit PDF/A + skip_text=true.
    • config.example.toml: pdfa_level = "" als sicherer Default
    • Runtime-Preflight: Prüft gs --version wenn pdfa_level gesetzt ist, bricht mit klarer Fehlermeldung ab
    • install.sh: warnt bei betroffenen GS-Versionen mit Upgrade-Hinweis auf bookworm-backports

Added

  • is_ghostscript_broken() / detect_ghostscript_version() in pdf_ocr_hotfolder.service
  • 19 weitere pytest-Tests für GS-Versions-Detection (parametrisiert) und Preflight-Kombinationen

[0.2.1] - 2026-04-09

Fixed

  • Issue #1: Preflight-Check beim Start prüft jetzt tesseract und gs (Ghostscript). Fehlt eine Abhängigkeit, beendet sich der Service sofort mit Exit-Code 2 und klarer Fehlermeldung statt erst bei der ersten Datei.
  • Issue #2: --once-Modus liefert jetzt Exit-Code 1, sobald mindestens ein PDF fehlgeschlagen ist. Exit-Code 0 nur bei vollständigem Erfolg (inkl. "keine Dateien vorhanden"). Exit-Code 2 bei Preflight-Fehler.

Added

  • Public API: HotfolderService.run_once(), .success_count, .error_count, .ensure_dirs()
  • check_preflight() / PreflightError in pdf_ocr_hotfolder.service
  • pytest-Test-Suite (tests/) mit 11 Tests — deckt alle Szenarien aus Issue #1 und #2 ab
  • ocrmypdf-Import in processor.py ist jetzt lazy (Tests ohne ocrmypdf-Installation möglich)

[0.2.0] - 2026-04-08

Added

  • Multi-Instanz-Support via systemd Template-Unit pdf-ocr-hotfolder@<name>.service
  • Pro Instanz: eigene Config (/etc/pdf-ocr-hotfolder/<name>.toml), eigene Datenverzeichnisse (/var/lib/pdf-ocr-hotfolder/<name>/…), optional eigener Service-User via Drop-in
  • Instanz-Manager in install.sh: erkennt bestehende Instanzen bei Re-Run, fragt nach weiteren, listet Namen + Status
  • update.sh stoppt/startet automatisch alle laufenden Instanzen

Changed

  • Single-Unit pdf-ocr-hotfolder.service durch Template-Unit pdf-ocr-hotfolder@.service ersetzt
  • Installer fragt nicht mehr einmalig nach Service-User, sondern pro Instanz

Removed

  • Alte Single-Config unter /etc/pdf-ocr-hotfolder/config.toml — wird nicht mehr erzeugt

[0.1.0] - 2026-04-08

Added

  • Initiale Version (Komplettes Rewrite des alten Bash-Tools pdf-tool)
  • Python-Implementation auf Basis von ocrmypdf (Library, kein Subprozess)
  • Hotfolder-Watcher mit watchdog (created/moved/closed Events)
  • File-Stability-Check (wartet bis Scanner fertig geschrieben hat)
  • ThreadPool für parallele PDF-Verarbeitung (max_workers)
  • Upload-Targets: lokaler Ordner, Nextcloud (WebDAV via requests), SFTP (paramiko)
  • E-Mail-Notify (smtplib, immer / nur Fehler / nie)
  • Optional veraPDF-Validierung
  • TOML-Konfiguration (tomllib aus stdlib, Python ≥3.11)
  • systemd-Unit mit Hardening-Optionen
  • install.sh mit interaktivem Service-User-Prompt (lokal anlegen oder bestehenden lokalen/AD-User übernehmen)
  • update.sh mit Backup, Code-Sync und Service-Reload
  • README.md, AI_AGENT_BRIEFING.md