From 2260a451a5d04bc82dddb1eb2a24ce5c565c23db Mon Sep 17 00:00:00 2001 From: StyxX65 <150797939+StyxX65@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:55:07 +0200 Subject: [PATCH] Fix deprecated fitz import, log unhandled scan-thread crashes document_scanner.py: `import fitz` is PyMuPDF's deprecated import alias, scheduled for removal - switched both sites to `import pymupdf as _fitz`. Pure rename, no behavior change (all 227 tests still pass). routes/scan.py: the background scan thread caught no exceptions, so an unexpected crash in run_scan() escaped into Python's default unhandled-thread-exception hook instead of the app's own logging/audit trail. The scan lock was already released correctly via `finally` - now the crash itself is also logged (`_log.exception`, full traceback) and audit-recorded before that. Confirmed by test_lock_released_when_ run_scan_raises: the PytestUnhandledThreadExceptionWarning it triggered is now gone, with no change to the test's own assertions. --- document_scanner.py | 4 ++-- routes/scan.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/document_scanner.py b/document_scanner.py index 66407d9..1e15976 100644 --- a/document_scanner.py +++ b/document_scanner.py @@ -106,7 +106,7 @@ except ImportError: MASK_AVAILABLE = False try: - import fitz as _fitz # PyMuPDF — for secure (sanitised) PDF redaction + import pymupdf as _fitz # PyMuPDF — for secure (sanitised) PDF redaction PYMUPDF_AVAILABLE = True except ImportError: PYMUPDF_AVAILABLE = False @@ -2727,7 +2727,7 @@ def count_faces_in_file(path, poppler_path=None, neighbors: int = 4) -> int: elif ext == ".pdf": if PYMUPDF_AVAILABLE: - import fitz as _fitz + import pymupdf as _fitz doc = _fitz.open(str(path)) for page_idx in range(min(5, len(doc))): pix = doc[page_idx].get_pixmap(dpi=100) diff --git a/routes/scan.py b/routes/scan.py index 1c76f08..02db7e4 100644 --- a/routes/scan.py +++ b/routes/scan.py @@ -114,6 +114,9 @@ def scan_start(): try: run_scan(options) _maybe_send_auto_email() + except Exception: + _log.exception("[scan] background scan thread crashed") + _audit("scan_error", "background scan thread crashed", ip="") finally: state._scan_lock.release() threading.Thread(target=_run, daemon=True).start()