File size: 2,462 Bytes
eed2172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8400d8c
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""Suite-wide test fixtures: the deterministic "mock data" the app no longer ships.

The app has no offline product mode — it requires a real event store
(``DATABASE_URL``) and live inference, and refuses to run without them.  The test
suite must still run with zero network, no credentials, and full reproducibility,
so it supplies that infrastructure as *mock data* instead:

  * an ephemeral in-memory SQLite event store (a real ``SqlAlchemyLedger``, no server);
  * the :class:`~src.models.provider.DeterministicTinyModel` stub for every profile,
    via ``ModelRouter(offline=True)`` — wired in by patching ``Registry.build_router``.

A test that needs the *real* production wiring (e.g. to assert that a missing DB
URL or missing credentials raises) opts out with ``@pytest.mark.real_infra`` and
sets up its own environment.
"""

from __future__ import annotations

import pytest


def pytest_configure(config):
    config.addinivalue_line(
        "markers",
        "real_infra: use the real make_ledger/build_router wiring instead of the mock fixtures",
    )


@pytest.fixture(autouse=True)
def _mock_infra(request, monkeypatch):
    # An ephemeral SQLite store stands in for the required durable event store.
    monkeypatch.setenv("DATABASE_URL", "sqlite://")

    if request.node.get_closest_marker("real_infra"):
        return

    # Route every profile to the deterministic stub so tests never reach live
    # inference. Patching build_router (rather than env) keeps production code's
    # "live credentials required" contract intact while tests get reproducible data.
    from src.core.registry import Registry
    from src.models.router import ModelRouter, ProfileSpec

    def _stub_build_router(self) -> ModelRouter:
        specs = {profile: ProfileSpec(**cfg.model_dump()) for profile, cfg in self.models.profiles.items()}
        return ModelRouter(offline=True, specs=specs)

    monkeypatch.setattr(Registry, "build_router", _stub_build_router)

    # Media (image / TTS) also defaults to the deterministic stub in tests, mirroring the
    # text router — so a dev with MODAL_WORKSPACE set never makes live media calls in the
    # suite. ``default_tool_registry`` re-imports this name on each call, so the patch sticks.
    from src.media import inference as media_inference
    from src.media.router import MediaRouter

    monkeypatch.setattr(media_inference, "build_media_router", lambda env=None: MediaRouter(offline=True))