fix: ocrmypdf-Pin auf 17.4.1, Preflight erkennt den GS-Fall, Rauchtest (v0.6.1)
v0.6.0 hat ocrmypdf auf 16.13.0 gepinnt, um einen ungewollten Major-Sprung
zu verhindern. Auf Bestandsinstallationen war das ein DOWNGRADE (dort lief
via ">=16.0" bereits 17.x) — und 16.13.0 bricht auf Debian 12 mit dem
Bord-Ghostscript 10.0.0 bei JEDER PDF ab, sobald skip_text gesetzt ist.
Im Test auf CT 200 lief das Update mit Exit 0 durch, der Dienst blieb
"active", --check-config meldete "Preflight ok" — und jede Datei landete
in error/. Stiller Totalausfall.
- requirements.txt: ocrmypdf==17.4.1 (real auf Debian 12 + gs 10.0.0
verifiziert). Ab 17.0.0 steht die GS-Pruefung in ocrmypdf unter einem
`if options.output_type.startswith('pdfa')`; bis 16.x lief sie ohne
diesen Guard und schlug auch bei output_type="pdf" zu.
- check_preflight() prueft Ghostscript nicht mehr nur bei gesetztem
pdfa_level, sondern bildet die reale Bedingung ab:
betroffene GS-Version UND skip_text UND (PDF/A ODER ocrmypdf < 17).
Der Dienst bricht damit beim Start ab statt bei der ersten Datei.
- update.sh zeigt Versionsspruenge der gepinnten Pakete; Downgrades als
WARN, auch in der Abschluss-Zusammenfassung.
- update.sh faehrt nach dem Start einen Rauchtest (eingebettete Mini-PDF
durch die echte Pipeline) und raeumt restlos auf. Uebersprungen, wenn
Upload-Ziele oder E-Mail-Notify aktiv sind, damit kein Testmuell zum
Kunden geht. Abschaltbar mit --no-smoke-test.
- Doku korrigiert: pdfa_level = "" allein ist keine Entwarnung, die haengt
an der ocrmypdf-Version.
152 Tests gruen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+11
-7
@@ -1,8 +1,8 @@
|
||||
# AI Agent Briefing — PDF OCR Hotfolder
|
||||
|
||||
**Zuletzt aktualisiert:** 2026-09-22
|
||||
**Version:** 0.6.0
|
||||
**Status:** Multi-Instanz-Betrieb, Preflight-Checks, Fehlerzählung, Wiederaufnahme aus `working/` und ein abgesicherter Updater (venv-Rebuild, Backup, Verifikation). Test-Suite grün (135 pytest-Tests). Ein Produktiv-Einsatz ist im Repo (README/CHANGELOG) nicht dokumentiert — die bisherigen Fixes stammen aus Issues #1–#6 und aus Vorbereitungen auf Debian 13, nicht aus einem belegten Dauerbetrieb.
|
||||
**Version:** 0.6.1
|
||||
**Status:** Multi-Instanz-Betrieb, Preflight-Checks, Fehlerzählung, Wiederaufnahme aus `working/` und ein abgesicherter Updater (venv-Rebuild, Backup, Verifikation, Versionssprung-Meldung, Rauchtest). Test-Suite grün (152 pytest-Tests). Ein Produktiv-Einsatz ist im Repo (README/CHANGELOG) nicht dokumentiert — die bisherigen Fixes stammen aus Issues #1–#6 und aus Vorbereitungen auf Debian 13, nicht aus einem belegten Dauerbetrieb.
|
||||
|
||||
> **Betriebsabläufe stehen nicht hier**, sondern in:
|
||||
> [README.md](README.md) (Einstieg, Layout, Config-Überblick) ·
|
||||
@@ -26,7 +26,7 @@ pdf-ocr-hotfolder/
|
||||
│ ├── service.py # HotfolderService (watchdog + ThreadPool), Preflight, Resume, Zähler
|
||||
│ ├── processor.py # ocrmypdf-Call, veraPDF, Ausgabename, Original-Entsorgung
|
||||
│ └── uploaders.py # folder, nextcloud (WebDAV), sftp, E-Mail-Notify
|
||||
├── tests/ # pytest-Suite (135 Tests, ocrmypdf wird gemockt)
|
||||
├── tests/ # pytest-Suite (152 Tests, ocrmypdf wird gemockt)
|
||||
│ ├── conftest.py # Fixtures tmp_config / dummy_pdf
|
||||
│ ├── test_check_config.py # --check-config, Exit 0/1/2
|
||||
│ ├── test_config_errors.py
|
||||
@@ -230,7 +230,7 @@ wenn der installierte Code das Flag noch nicht kennt.
|
||||
## 🔄 Verarbeitungs-Flow
|
||||
|
||||
**Beim Start (`run()` wie `run_once()`), vor allem anderen:**
|
||||
1. `check_preflight()` — `tesseract` und `gs` müssen im PATH sein; ist `pdfa_level` gesetzt, wird zusätzlich die Ghostscript-Version gegen den 10.0.0–10.02.0-Bug geprüft
|
||||
1. `check_preflight(pdfa_level, skip_text)` — `tesseract` und `gs` müssen im PATH sein; zusätzlich wird die Ghostscript-Version gegen den 10.0.0–10.02.0-Bug geprüft, und zwar unter genau der Bedingung, unter der ocrmypdf selbst abbricht (`_gs_block_reason()`: betroffene GS-Version **und** `skip_text` **und** (`pdfa_level` gesetzt **oder** ocrmypdf < 17))
|
||||
2. `check_output_config()` — validiert `original_on_success`, `archive_dir` (Pflicht bei `archive`) und `name_mode`
|
||||
3. Scheitert eines davon → `PreflightError`, CLI beendet sich mit **Exit-Code 2** (ebenso bei kaputter/fehlender Config)
|
||||
4. `ensure_dirs()`, dann `_scan_existing()`: **zuerst `working/`**, danach `incoming/`
|
||||
@@ -289,7 +289,11 @@ Der Service läuft in allen Fällen weiter (kein `exit 1` wie im alten Bash-Tool
|
||||
|
||||
## ⚠️ Fallstricke
|
||||
|
||||
- **Ghostscript 10.0.0–10.02.0 zerschießt OCR.** Das ist der Debian-12-Default. In Kombination aus `[ocr].pdfa_level` + `skip_text = true` blockiert ocrmypdf komplett (Issue #3). Deshalb ist `pdfa_level = ""` der sichere Default, der Preflight bricht mit Exit 2 ab, wenn `pdfa_level` gesetzt **und** die GS-Version betroffen ist, und `--check-config` warnt bei gesetztem `pdfa_level` grundsätzlich. Abhilfe: Ghostscript ≥ 10.02.1 aus bookworm-backports (der Installer bietet das an).
|
||||
- **Ghostscript 10.0.0–10.02.0 zerschießt OCR.** Das ist der Debian-12-Default. ocrmypdf verweigert damit die Arbeit — aber die Bedingung dafür hängt an der **ocrmypdf-Version**, und genau daran ist 0.6.0 gescheitert:
|
||||
- **ocrmypdf ≤ 16.x**: die Prüfung in `builtin_plugins/ghostscript.py::check_options()` läuft **bedingungslos**. `skip_text = true` allein reicht — `output_type` wird nicht geprüft. Auf Debian 12 scheitert damit **jede** Datei.
|
||||
- **ocrmypdf ≥ 17.0**: derselbe Block steckt in einem `if options.output_type.startswith('pdfa'):`. Ohne PDF/A wird Ghostscript nicht angefasst.
|
||||
|
||||
`pdfa_level = ""` ist deshalb **kein** Schutz für sich genommen — es wirkt nur mit ocrmypdf ≥ 17. `requirements.txt` pinnt daher 17.x; ein Downgrade auf 16.x macht jede Debian-12-Instanz unbrauchbar, bei grünem `systemctl status`. Der Preflight bildet die reale Bedingung ab (`_gs_block_reason()`) und bricht mit Exit 2 ab, `--check-config` meldet denselben Zustand als Fehler. `redo_ocr` ist bewusst **nicht** in der Bedingung: die Config kennt keinen solchen Key. Abhilfe: Ghostscript ≥ 10.02.1 aus bookworm-backports (der Installer bietet das an) oder `skip_text = false`.
|
||||
- **`[ocr].timeout` ist ein Timeout PRO SEITE**, kein Gesamt-Timeout pro PDF. Der Wert geht als `tesseract_timeout` (ocrmypdf-Option `--tesseract-timeout`) durch; ocrmypdf kennt kein Dokument-Timeout. Wer noch den alten Default `1800` in einer Config stehen hat, gibt Tesseract 30 Minuten **je Seite** — Richtwert ist 300, ab 900 warnt `--check-config`. Ein durchgereichtes `0` würde ocrmypdf dazu bringen, OCR **still zu überspringen**, deshalb wird bei `0` (oder negativ) gar nichts übergeben und der ocrmypdf-Default greift.
|
||||
- **`TimeoutStopSec=300` in der Unit ist Absicht.** Ein laufendes OCR soll beim Stoppen zu Ende laufen dürfen — ein `systemctl stop` kann deshalb pro Instanz bis zu 5 Minuten dauern, und `update.sh` (das nacheinander stoppt) entsprechend länger. Bei SIGKILL bliebe das Original in `working/` liegen; das wird zwar wiederaufgenommen, kostet aber den kompletten Durchlauf.
|
||||
- **Die venv hängt an der Python-Version der Distribution.** Nach einem Debian-Major-Upgrade ist `venv/bin/python` tot (systemd: `203/EXEC`) oder eine andere Version als das System-Python. Der Weg dahin und zurück steht in [docs/OS-UPGRADE.md](docs/OS-UPGRADE.md); im Code prüfen `install.sh` und `update.sh` das je mit einem eigenen `venv_is_healthy()` (die Variante in `update.sh` ist die gründlichere und schaut zusätzlich in `pyvenv.cfg`).
|
||||
@@ -312,14 +316,14 @@ python -m pdf_ocr_hotfolder --config /tmp/config.toml
|
||||
|
||||
Tests (aus dem Repo-Root, `pytest.ini` setzt `testpaths = tests`):
|
||||
```bash
|
||||
pytest # aktuell 135 Tests
|
||||
pytest # aktuell 152 Tests
|
||||
```
|
||||
|
||||
`ocrmypdf` muss dafür **nicht** installiert sein: der Import in `processor.py` ist lazy, und `tests/test_ocr_timeout.py` schiebt ein Dummy-Modul in `sys.modules`. Die übrigen Tests mocken `process_pdf` bzw. arbeiten nur auf Config-Ebene.
|
||||
|
||||
## 📋 Roadmap / TODO
|
||||
|
||||
- [x] Tests (`pytest`) für `processor` und `uploaders` — 135 Tests
|
||||
- [x] Tests (`pytest`) für `processor` und `uploaders` — 152 Tests
|
||||
- [x] Wiederaufnahme abgebrochener Läufe aus `working/`
|
||||
- [x] Config-Prüfung ohne Verarbeitung (`--check-config`) + Auswertung im Updater
|
||||
- [x] Updater übersteht Debian-Major-Upgrades (venv-Rebuild, Pins, Rollback)
|
||||
|
||||
Reference in New Issue
Block a user