conftest.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. """
  2. Shared pytest fixtures and import setup for the seq_interp test suite.
  3. The source modules import themselves as ``seq_interp.src...`` — the name the
  4. Docker image mounts the tree under (``COPY services/seq-interp /app/seq_interp``).
  5. Locally the directory is ``seq-interp`` (with a hyphen), which is not a valid
  6. module name, so we register an in-process alias package ``seq_interp`` that
  7. points at the service root. This lets tests import the real source unchanged.
  8. """
  9. from __future__ import annotations
  10. import pathlib
  11. import sys
  12. import types
  13. import pytest
  14. SERVICE_ROOT = pathlib.Path(__file__).resolve().parents[1] # .../services/seq-interp
  15. if "seq_interp" not in sys.modules:
  16. _pkg = types.ModuleType("seq_interp")
  17. _pkg.__path__ = [str(SERVICE_ROOT)]
  18. sys.modules["seq_interp"] = _pkg
  19. class FakeSeq:
  20. """
  21. Minimal stand-in for a loaded pypulseq sequence, exposing only what
  22. ``Synchronizer.process`` touches: ``block_events`` and ``block_durations``.
  23. block_events layout (1-indexed, pypulseq order):
  24. [ ?, RF, GX, GY, GZ, ADC, EXT ]
  25. 0 1 2 3 4 5 6
  26. """
  27. def __init__(self, specs: list[dict]):
  28. self.block_events: dict[int, list[int]] = {}
  29. self.block_durations: dict[int, float] = {}
  30. for i, spec in enumerate(specs, start=1):
  31. ev = [0, 0, 0, 0, 0, 0, 0]
  32. if spec.get("rf"):
  33. ev[1] = 1
  34. if spec.get("adc"):
  35. ev[5] = 1
  36. self.block_events[i] = ev
  37. self.block_durations[i] = spec["dur"]
  38. @pytest.fixture
  39. def make_seq():
  40. """Factory: make_seq([{"rf": bool, "adc": bool, "dur": seconds}, ...])."""
  41. return FakeSeq