Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow PVI devices to be initialized before connection #241

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
914324a
Make backend optional on Signal initialisation
noemifrisina Apr 18, 2024
276d3ce
Run pre-commits
noemifrisina Apr 18, 2024
7a3dc47
Add small test for connection failure
noemifrisina Apr 18, 2024
0169d85
Merge branch 'main' into 194_initialise-devices-pre-connection
noemifrisina Apr 18, 2024
aaf6a29
Merge branch 'main' into 194_initialise-devices-pre-connection
noemifrisina Apr 19, 2024
53090ce
Merge branch 'main' into 194_initialise-devices-pre-connection
noemifrisina May 8, 2024
34ea837
Merge branch 'main' into 194_initialise-devices-pre-connection
noemifrisina May 9, 2024
a4d4ccc
DeviceVector change in _sim_common_blocks
noemifrisina May 10, 2024
66ad14d
Merge branch 'main' into 194_initialise-devices-pre-connection
noemifrisina May 30, 2024
719bcac
Save stashed change
noemifrisina May 30, 2024
1c33413
Fix typo
noemifrisina May 30, 2024
e293ed2
Fix error created from merging
noemifrisina May 30, 2024
acb4729
Remove leftover else
noemifrisina May 30, 2024
29cb033
Save the rest of the stashed changes
noemifrisina May 30, 2024
f21901a
Update src/ophyd_async/core/signal.py
noemifrisina May 31, 2024
b33c9a2
Keep initial_backend as None and change _backend
noemifrisina May 31, 2024
c043c4d
Update src/ophyd_async/epics/pvi/pvi.py
noemifrisina May 31, 2024
8200c76
Fix tests
noemifrisina May 31, 2024
22a6c37
Merge branch 'main' into 194_initialise-devices-pre-connection
noemifrisina May 31, 2024
be3768a
Update src/ophyd_async/core/signal.py
noemifrisina Jun 5, 2024
699b8d8
Update tests/core/test_signal.py
noemifrisina Jun 5, 2024
b071d78
Fix signal tests
noemifrisina Jun 5, 2024
7c1c659
Attempt at pvi test
noemifrisina Jun 6, 2024
06079fc
Fix test
noemifrisina Jun 6, 2024
72611f4
Merge branch 'main' into 194_initialise-devices-pre-connection
noemifrisina Jun 6, 2024
96695fa
Update src/ophyd_async/epics/pvi/pvi.py
noemifrisina Jun 7, 2024
47b998c
Update src/ophyd_async/epics/pvi/pvi.py
noemifrisina Jun 7, 2024
dbfad01
Update src/ophyd_async/epics/pvi/pvi.py
noemifrisina Jun 7, 2024
fd30e8e
_mock_common_blocks change
noemifrisina Jun 7, 2024
0ccf203
Remove double test case
noemifrisina Jun 7, 2024
bb5f4b1
Update tests/epics/test_pvi.py
noemifrisina Jun 10, 2024
dcc432b
Add optional block and remove device collector
noemifrisina Jun 10, 2024
6431e33
Test that even if optional signal still isn't initialised
noemifrisina Jun 10, 2024
ccae84b
Test that even if optional signal still isn't initialised
noemifrisina Jun 10, 2024
5bdf629
Update comment
noemifrisina Jun 10, 2024
bb9a9e5
Merge branch 'main' into 194_initialise-devices-pre-connection
evalott100 Jun 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/ophyd_async/core/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Signal(Device, Generic[T]):

def __init__(
self,
backend: SignalBackend[T],
backend: Optional[SignalBackend[T]] = None,
timeout: Optional[float] = DEFAULT_TIMEOUT,
name: str = "",
) -> None:
Expand All @@ -66,13 +66,21 @@ def __init__(
super().__init__(name)

async def connect(
self, mock=False, timeout=DEFAULT_TIMEOUT, force_reconnect: bool = False
self,
mock=False,
timeout=DEFAULT_TIMEOUT,
force_reconnect: bool = False,
backend: Optional[SignalBackend[T]] = None,
):
if backend:
if self._initial_backend and backend is not self._initial_backend:
raise ValueError(
"Backend at connection different from initialised one."
)
self._backend = backend
if mock and not isinstance(self._backend, MockSignalBackend):
# Using a soft backend, look to the initial value
self._backend = MockSignalBackend(
initial_backend=self._initial_backend,
)
self._backend = MockSignalBackend(initial_backend=self._backend)
self.log.debug(f"Connecting to {self.source}")
await self._backend.connect(timeout=timeout)
noemifrisina marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
17 changes: 13 additions & 4 deletions src/ophyd_async/epics/pvi/pvi.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,12 @@ def _mock_common_blocks(device: Device, stripped_type: Optional[Type] = None):
sub_device_2 = device_cls(SoftSignalBackend(signal_dtype))
sub_device = DeviceVector({1: sub_device_1, 2: sub_device_2})
else:
sub_device = DeviceVector({1: device_cls(), 2: device_cls()})
sub_device = DeviceVector(
{
1: getattr(device, device_name, device_cls()),
2: getattr(device, device_name, device_cls()),
}
)

for sub_device_in_vector in sub_device.values():
_mock_common_blocks(sub_device_in_vector, stripped_type=device_cls)
Expand Down Expand Up @@ -296,7 +301,9 @@ async def fill_pvi_entries(


def create_children_from_annotations(
evalott100 marked this conversation as resolved.
Show resolved Hide resolved
device: Device, included_optional_fields: Tuple[str, ...] = ()
device: Device,
included_optional_fields: Tuple[str, ...] = (),
device_vectors: Optional[Dict[str, int]] = None,
):
"""For intializing blocks at __init__ of ``device``."""
for name, device_type in get_type_hints(type(device)).items():
Expand All @@ -306,13 +313,15 @@ def create_children_from_annotations(
if is_optional and name not in included_optional_fields:
continue
is_device_vector, device_type = _strip_device_vector(device_type)
if is_device_vector and not device_vectors:
continue
noemifrisina marked this conversation as resolved.
Show resolved Hide resolved
if (
is_device_vector
(is_device_vector and name not in device_vectors.keys())
noemifrisina marked this conversation as resolved.
Show resolved Hide resolved
or ((origin := get_origin(device_type)) and issubclass(origin, Signal))
or (isclass(device_type) and issubclass(device_type, Signal))
):
continue

sub_device = device_type()
setattr(device, name, sub_device)
create_children_from_annotations(sub_device)
create_children_from_annotations(sub_device, device_vectors=device_vectors)
25 changes: 25 additions & 0 deletions tests/core/test_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
ConfigSignal,
DeviceCollector,
HintedSignal,
MockSignalBackend,
Signal,
SignalR,
SignalRW,
SoftSignalBackend,
Expand Down Expand Up @@ -50,6 +52,29 @@ async def test_signals_equality_raises():
s1 > 4

evalott100 marked this conversation as resolved.
Show resolved Hide resolved

async def test_signal_connect_fails_with_different_backend_on_connection():
sim_signal = Signal(MockSignalBackend(str))

with pytest.raises(ValueError):
await sim_signal.connect(mock=True, backend=MockSignalBackend(int))

with pytest.raises(ValueError):
await sim_signal.connect(mock=True, backend=SoftSignalBackend(str))

with pytest.raises(ValueError):
await sim_signal.connect(mock=False, backend=MockSignalBackend(str))
evalott100 marked this conversation as resolved.
Show resolved Hide resolved


async def test_signal_connect_fails_if_different_backend_but_same_by_value():
initial_backend = MockSignalBackend(str)
sim_signal = Signal(initial_backend)

with pytest.raises(ValueError):
await sim_signal.connect(mock=True, backend=MockSignalBackend(str))

await sim_signal.connect(mock=True, backend=initial_backend)
noemifrisina marked this conversation as resolved.
Show resolved Hide resolved


async def time_taken_by(coro) -> float:
start = time.monotonic()
await coro
Expand Down