Source code for ophyd_async.core._mock_signal_backend
import asyncio
from collections.abc import Callable
from functools import cached_property
from unittest.mock import AsyncMock
from bluesky.protocols import Descriptor, Reading
from ._signal_backend import SignalBackend, SignalDatatypeT
from ._soft_signal_backend import SoftSignalBackend
from ._utils import Callback, LazyMock
[docs]
class MockSignalBackend(SignalBackend[SignalDatatypeT]):
"""Signal backend for testing, created by ``Device.connect(mock=True)``."""
def __init__(
self,
initial_backend: SignalBackend[SignalDatatypeT],
mock: LazyMock,
) -> None:
if isinstance(initial_backend, MockSignalBackend):
raise ValueError("Cannot make a MockSignalBackend for a MockSignalBackend")
self.initial_backend = initial_backend
if isinstance(self.initial_backend, SoftSignalBackend):
# Backend is already a SoftSignalBackend, so use it
self.soft_backend = self.initial_backend
else:
# Backend is not a SoftSignalBackend, so create one to mimic it
self.soft_backend = SoftSignalBackend(
datatype=self.initial_backend.datatype
)
# use existing Mock if provided
self.mock = mock
super().__init__(datatype=self.initial_backend.datatype)
@cached_property
def put_mock(self) -> AsyncMock:
put_mock = AsyncMock(name="put", spec=Callable)
self.mock().attach_mock(put_mock, "put")
return put_mock
def set_value(self, value: SignalDatatypeT):
self.soft_backend.set_value(value)
def source(self, name: str, read: bool) -> str:
return f"mock+{self.initial_backend.source(name, read)}"
async def connect(self, timeout: float) -> None:
raise RuntimeError("It is not possible to connect a MockSignalBackend")
@cached_property
def put_proceeds(self) -> asyncio.Event:
put_proceeds = asyncio.Event()
put_proceeds.set()
return put_proceeds
async def put(self, value: SignalDatatypeT | None, wait: bool):
await self.put_mock(value, wait=wait)
await self.soft_backend.put(value, wait=wait)
if wait:
await self.put_proceeds.wait()
async def get_reading(self) -> Reading:
return await self.soft_backend.get_reading()
async def get_value(self) -> SignalDatatypeT:
return await self.soft_backend.get_value()
async def get_setpoint(self) -> SignalDatatypeT:
return await self.soft_backend.get_setpoint()
async def get_datakey(self, source: str) -> Descriptor:
return await self.soft_backend.get_datakey(source)
def set_callback(self, callback: Callback[Reading[SignalDatatypeT]] | None) -> None:
self.soft_backend.set_callback(callback)