"""Shared pytest fixtures and path setup. Stubs heavy optional dependencies (``fitz``/PyMuPDF, ``bs4``/BeautifulSoup, ``openai``) so the test suite can run without the full prod requirements installed. The tests in this directory are pure unit tests over parser logic and prompt formatters — they neither parse PDFs nor make HTTP calls, so the stubs are inert placeholders that satisfy the import machinery but never get exercised. If a test ever does need real PyMuPDF or httpx integration, give it a fixture marked with ``@pytest.mark.integration`` and skip it by default. """ import sys import types from pathlib import Path # Make the `app` package importable when pytest is run from the webapp/ root. ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) def _stub(name: str, **attrs) -> None: if name in sys.modules: return mod = types.ModuleType(name) for k, v in attrs.items(): setattr(mod, k, v) sys.modules[name] = mod # `fitz` ist tricky: PyPI haelt unter "fitz" eine andere Library, das # echte PyMuPDF importiert man via `pymupdf` oder `fitz` (alias). Wenn # das echte PyMuPDF installiert ist, soll die echte Lib genutzt werden; # sonst stubben wir, damit Imports klappen. Tests, die wirklich PDFs # rendern (test_embeddings TestRenderHighlightedPage), brauchen die # echte Lib — wenn die fehlt, skippen sie ueber ihre Fixtures. try: import pymupdf as _pymupdf # type: ignore sys.modules["fitz"] = _pymupdf except ImportError: try: import fitz as _fitz_check # noqa: F401 (Real PyMuPDF unter fitz-Namen) if not hasattr(_fitz_check, "open"): _stub("fitz") except ImportError: _stub("fitz") _stub("bs4", BeautifulSoup=lambda *a, **kw: None) # only needed by NRWAdapter live calls _stub("openai", OpenAI=lambda **kw: None) # only needed by embeddings live calls # pydantic_settings is a small but external dep that's not in the test # environment. Stub it with a minimal BaseSettings shim so app.config can # import without crashing — the tests don't actually read settings values. class _BaseSettingsShim: model_config: dict = {} def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) def _settings_config_dict(**kwargs): return kwargs _stub("pydantic_settings", BaseSettings=_BaseSettingsShim, SettingsConfigDict=_settings_config_dict)