from collections.abc import Generator from dataclasses import dataclass from pathlib import Path from types import SimpleNamespace from typing import Any import pytest @pytest.fixture(scope="session", autouse=True) def db() -> Generator[None, None, None]: """The engine holds no database state, so these tests need no database.""" yield @dataclass class FakeTarget: name: str type: str value: Any values: list[str] | None = None range: list[float] | None = None description: str = "" unit: str | None = None readonly: bool = False @dataclass class FakeCall: target: str value: Any = None delay_s: float | None = None confidence: float = 1.0 class FakeWren: """The model package's surface: ``act`` answers whatever a test sets ``answer`` to, and ``load_pack`` returns ``pack``.""" Target = FakeTarget Call = FakeCall runtime = SimpleNamespace(MODEL=Path("demo.bin")) def __init__(self) -> None: self.answer: list[FakeCall] = [] self.pack: dict[str, Any] = {"meta": {"threshold": 0.9, "targets": []}} self.loaded: list[Path] = [] self.commands: list[str] = [] self.targets: list[list[FakeTarget]] = [] self.models: list[Any] = [] def load_pack(self, path: Path) -> dict[str, Any]: self.loaded.append(path) return self.pack def act( self, command: str, targets: list[FakeTarget], *, model: Any = None ) -> list[FakeCall]: self.commands.append(command) self.targets.append(targets) self.models.append(model) return self.answer @pytest.fixture def fake_wren(monkeypatch: pytest.MonkeyPatch) -> FakeWren: """Stands in for the optional model package the wren node imports.""" fake = FakeWren() monkeypatch.setattr("fluksio.flow.nodes.wren._wren", lambda: fake) return fake