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

143 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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