"""OCR subsystem: protocol + fake + real Surya client + factory. Real engines (Surya today, Azure DI / AWS Textract … deferred) plug in behind :class:`OCRClient`. The factory :func:`make_ocr_client` picks between :class:`FakeOCRClient` (when ``IX_TEST_MODE=fake``) and :class:`SuryaOCRClient` (production). Unknown engine names raise so a typo'd ``IX_OCR_ENGINE`` surfaces at startup, not later. """ from __future__ import annotations from ix.config import AppConfig from ix.contracts.response import OCRDetails, OCRResult from ix.ocr.client import OCRClient from ix.ocr.fake import FakeOCRClient from ix.ocr.surya_client import SuryaOCRClient def make_ocr_client(cfg: AppConfig) -> OCRClient: """Return the :class:`OCRClient` configured for the current run.""" if cfg.test_mode == "fake": return FakeOCRClient(canned=OCRResult(result=OCRDetails())) if cfg.ocr_engine == "surya": return SuryaOCRClient() raise ValueError(f"Unknown ocr_engine: {cfg.ocr_engine!r}") __all__ = [ "FakeOCRClient", "OCRClient", "SuryaOCRClient", "make_ocr_client", ]