"""Safe temp handling for uploaded bank statements. Bank data must never linger. Each upload is written into its OWN temp directory inside WORK_DIR, processed, and the whole directory is removed in a finally block — taking the PDF and any OCR scratch images (`.ocr_p*.png`, which the engine writes next to the PDF) with it. A per-request directory also keeps concurrent requests from clobbering each other's OCR scratch. """ from __future__ import annotations import contextlib import shutil import tempfile from collections.abc import Iterator from pathlib import Path from app.core.config import WORK_DIR @contextlib.contextmanager def temp_pdf(data: bytes) -> Iterator[Path]: """Write `data` to an isolated temp dir, yield the PDF path, then delete the whole dir (PDF + OCR scratch) no matter what.""" WORK_DIR.mkdir(parents=True, exist_ok=True) workdir = Path(tempfile.mkdtemp(dir=str(WORK_DIR))) pdf_path = workdir / "statement.pdf" try: pdf_path.write_bytes(data) yield pdf_path finally: with contextlib.suppress(OSError): shutil.rmtree(workdir, ignore_errors=True)