ophyd-async 0.8.0a2__py3-none-any.whl → 0.8.0a4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. ophyd_async/_version.py +1 -1
  2. ophyd_async/core/__init__.py +9 -1
  3. ophyd_async/core/_device.py +71 -49
  4. ophyd_async/core/_device_filler.py +208 -130
  5. ophyd_async/core/_mock_signal_backend.py +10 -7
  6. ophyd_async/core/_mock_signal_utils.py +14 -11
  7. ophyd_async/core/_readable.py +128 -129
  8. ophyd_async/core/_signal.py +22 -24
  9. ophyd_async/core/_soft_signal_backend.py +2 -0
  10. ophyd_async/core/_utils.py +64 -11
  11. ophyd_async/epics/adaravis/_aravis_io.py +1 -1
  12. ophyd_async/epics/adcore/_core_io.py +1 -1
  13. ophyd_async/epics/adcore/_single_trigger.py +6 -10
  14. ophyd_async/epics/adkinetix/_kinetix_io.py +1 -1
  15. ophyd_async/epics/adpilatus/_pilatus_io.py +1 -1
  16. ophyd_async/epics/advimba/_vimba_io.py +1 -1
  17. ophyd_async/epics/core/__init__.py +26 -0
  18. ophyd_async/epics/{signal → core}/_aioca.py +3 -6
  19. ophyd_async/epics/core/_epics_connector.py +53 -0
  20. ophyd_async/epics/core/_epics_device.py +13 -0
  21. ophyd_async/epics/{signal → core}/_p4p.py +3 -6
  22. ophyd_async/epics/core/_pvi_connector.py +91 -0
  23. ophyd_async/epics/{signal → core}/_signal.py +31 -16
  24. ophyd_async/epics/{signal/_common.py → core/_util.py} +19 -1
  25. ophyd_async/epics/demo/_mover.py +4 -5
  26. ophyd_async/epics/demo/_sensor.py +9 -12
  27. ophyd_async/epics/eiger/_eiger_io.py +1 -1
  28. ophyd_async/epics/eiger/_odin_io.py +1 -1
  29. ophyd_async/epics/motor.py +4 -5
  30. ophyd_async/epics/signal.py +11 -0
  31. ophyd_async/fastcs/core.py +2 -2
  32. ophyd_async/plan_stubs/_ensure_connected.py +2 -4
  33. ophyd_async/sim/demo/_sim_motor.py +3 -4
  34. ophyd_async/tango/base_devices/_base_device.py +48 -48
  35. ophyd_async/tango/demo/_counter.py +6 -16
  36. ophyd_async/tango/demo/_mover.py +3 -4
  37. {ophyd_async-0.8.0a2.dist-info → ophyd_async-0.8.0a4.dist-info}/METADATA +1 -1
  38. {ophyd_async-0.8.0a2.dist-info → ophyd_async-0.8.0a4.dist-info}/RECORD +42 -40
  39. {ophyd_async-0.8.0a2.dist-info → ophyd_async-0.8.0a4.dist-info}/WHEEL +1 -1
  40. ophyd_async/epics/pvi/__init__.py +0 -3
  41. ophyd_async/epics/pvi/_pvi.py +0 -73
  42. ophyd_async/epics/signal/__init__.py +0 -20
  43. {ophyd_async-0.8.0a2.dist-info → ophyd_async-0.8.0a4.dist-info}/LICENSE +0 -0
  44. {ophyd_async-0.8.0a2.dist-info → ophyd_async-0.8.0a4.dist-info}/entry_points.txt +0 -0
  45. {ophyd_async-0.8.0a2.dist-info → ophyd_async-0.8.0a4.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  from ophyd_async.core import StrictEnum
2
2
  from ophyd_async.epics import adcore
3
- from ophyd_async.epics.signal import epics_signal_rw_rbv
3
+ from ophyd_async.epics.core import epics_signal_rw_rbv
4
4
 
5
5
 
6
6
  class KinetixTriggerMode(StrictEnum):
@@ -1,6 +1,6 @@
1
1
  from ophyd_async.core import StrictEnum
2
2
  from ophyd_async.epics import adcore
3
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw_rbv
3
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw_rbv
4
4
 
5
5
 
6
6
  class PilatusTriggerMode(StrictEnum):
@@ -1,6 +1,6 @@
1
1
  from ophyd_async.core import StrictEnum
2
2
  from ophyd_async.epics import adcore
3
- from ophyd_async.epics.signal import epics_signal_rw_rbv
3
+ from ophyd_async.epics.core import epics_signal_rw_rbv
4
4
 
5
5
 
6
6
  class VimbaPixelFormat(StrictEnum):
@@ -0,0 +1,26 @@
1
+ from ._epics_connector import EpicsDeviceConnector, PvSuffix
2
+ from ._epics_device import EpicsDevice
3
+ from ._pvi_connector import PviDeviceConnector
4
+ from ._signal import (
5
+ CaSignalBackend,
6
+ PvaSignalBackend,
7
+ epics_signal_r,
8
+ epics_signal_rw,
9
+ epics_signal_rw_rbv,
10
+ epics_signal_w,
11
+ epics_signal_x,
12
+ )
13
+
14
+ __all__ = [
15
+ "PviDeviceConnector",
16
+ "EpicsDeviceConnector",
17
+ "PvSuffix",
18
+ "EpicsDevice",
19
+ "CaSignalBackend",
20
+ "PvaSignalBackend",
21
+ "epics_signal_r",
22
+ "epics_signal_rw",
23
+ "epics_signal_rw_rbv",
24
+ "epics_signal_w",
25
+ "epics_signal_x",
26
+ ]
@@ -24,7 +24,6 @@ from ophyd_async.core import (
24
24
  Array1D,
25
25
  Callback,
26
26
  NotConnected,
27
- SignalBackend,
28
27
  SignalDatatype,
29
28
  SignalDatatypeT,
30
29
  SignalMetadata,
@@ -34,7 +33,7 @@ from ophyd_async.core import (
34
33
  wait_for_connection,
35
34
  )
36
35
 
37
- from ._common import format_datatype, get_supported_values
36
+ from ._util import EpicsSignalBackend, format_datatype, get_supported_values
38
37
 
39
38
 
40
39
  def _limits_from_augmented_value(value: AugmentedValue) -> Limits:
@@ -227,19 +226,17 @@ def _use_pyepics_context_if_imported():
227
226
  _tried_pyepics = True
228
227
 
229
228
 
230
- class CaSignalBackend(SignalBackend[SignalDatatypeT]):
229
+ class CaSignalBackend(EpicsSignalBackend[SignalDatatypeT]):
231
230
  def __init__(
232
231
  self,
233
232
  datatype: type[SignalDatatypeT] | None,
234
233
  read_pv: str = "",
235
234
  write_pv: str = "",
236
235
  ):
237
- self.read_pv = read_pv
238
- self.write_pv = write_pv
239
236
  self.converter: CaConverter = DisconnectedCaConverter(float, dbr.DBR_DOUBLE)
240
237
  self.initial_values: dict[str, AugmentedValue] = {}
241
238
  self.subscription: Subscription | None = None
242
- super().__init__(datatype)
239
+ super().__init__(datatype, read_pv, write_pv)
243
240
 
244
241
  def source(self, name: str, read: bool):
245
242
  return f"ca://{self.read_pv if read else self.write_pv}"
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from ophyd_async.core import Device, DeviceConnector, DeviceFiller
7
+
8
+ from ._signal import EpicsSignalBackend, get_signal_backend_type, split_protocol_from_pv
9
+
10
+
11
+ @dataclass
12
+ class PvSuffix:
13
+ read_suffix: str
14
+ write_suffix: str | None = None
15
+
16
+ @classmethod
17
+ def rbv(cls, write_suffix: str, rbv_suffix: str = "_RBV") -> PvSuffix:
18
+ return cls(write_suffix + rbv_suffix, write_suffix)
19
+
20
+
21
+ def fill_backend_with_prefix(
22
+ prefix: str, backend: EpicsSignalBackend, annotations: list[Any]
23
+ ):
24
+ unhandled = []
25
+ while annotations:
26
+ annotation = annotations.pop(0)
27
+ if isinstance(annotation, PvSuffix):
28
+ backend.read_pv = prefix + annotation.read_suffix
29
+ backend.write_pv = prefix + (
30
+ annotation.write_suffix or annotation.read_suffix
31
+ )
32
+ else:
33
+ unhandled.append(annotation)
34
+ annotations.extend(unhandled)
35
+ # These leftover annotations will now be handled by the iterator
36
+
37
+
38
+ class EpicsDeviceConnector(DeviceConnector):
39
+ def __init__(self, prefix: str) -> None:
40
+ self.prefix = prefix
41
+
42
+ def create_children_from_annotations(self, device: Device):
43
+ if not hasattr(self, "filler"):
44
+ protocol, prefix = split_protocol_from_pv(self.prefix)
45
+ self.filler = DeviceFiller(
46
+ device,
47
+ signal_backend_factory=get_signal_backend_type(protocol),
48
+ device_connector_factory=DeviceConnector,
49
+ )
50
+ for backend, annotations in self.filler.create_signals_from_annotations():
51
+ fill_backend_with_prefix(prefix, backend, annotations)
52
+
53
+ list(self.filler.create_devices_from_annotations())
@@ -0,0 +1,13 @@
1
+ from ophyd_async.core import Device
2
+
3
+ from ._epics_connector import EpicsDeviceConnector
4
+ from ._pvi_connector import PviDeviceConnector
5
+
6
+
7
+ class EpicsDevice(Device):
8
+ def __init__(self, prefix: str, with_pvi: bool = False, name: str = ""):
9
+ if with_pvi:
10
+ connector = PviDeviceConnector(prefix)
11
+ else:
12
+ connector = EpicsDeviceConnector(prefix)
13
+ super().__init__(name=name, connector=connector)
@@ -18,7 +18,6 @@ from ophyd_async.core import (
18
18
  Array1D,
19
19
  Callback,
20
20
  NotConnected,
21
- SignalBackend,
22
21
  SignalDatatype,
23
22
  SignalDatatypeT,
24
23
  SignalMetadata,
@@ -30,7 +29,7 @@ from ophyd_async.core import (
30
29
  wait_for_connection,
31
30
  )
32
31
 
33
- from ._common import format_datatype, get_supported_values
32
+ from ._util import EpicsSignalBackend, format_datatype, get_supported_values
34
33
 
35
34
 
36
35
  def _limits_from_value(value: Any) -> Limits:
@@ -293,19 +292,17 @@ def _pva_request_string(fields: Sequence[str]) -> str:
293
292
  return f"field({','.join(fields)})"
294
293
 
295
294
 
296
- class PvaSignalBackend(SignalBackend[SignalDatatypeT]):
295
+ class PvaSignalBackend(EpicsSignalBackend[SignalDatatypeT]):
297
296
  def __init__(
298
297
  self,
299
298
  datatype: type[SignalDatatypeT] | None,
300
299
  read_pv: str = "",
301
300
  write_pv: str = "",
302
301
  ):
303
- self.read_pv = read_pv
304
- self.write_pv = write_pv
305
302
  self.converter: PvaConverter = DisconnectedPvaConverter(float)
306
303
  self.initial_values: dict[str, Any] = {}
307
304
  self.subscription: Subscription | None = None
308
- super().__init__(datatype)
305
+ super().__init__(datatype, read_pv, write_pv)
309
306
 
310
307
  def source(self, name: str, read: bool):
311
308
  return f"pva://{self.read_pv if read else self.write_pv}"
@@ -0,0 +1,91 @@
1
+ from __future__ import annotations
2
+
3
+ from ophyd_async.core import (
4
+ Device,
5
+ DeviceConnector,
6
+ DeviceFiller,
7
+ Signal,
8
+ SignalR,
9
+ SignalRW,
10
+ SignalX,
11
+ )
12
+ from ophyd_async.core._utils import LazyMock
13
+
14
+ from ._epics_connector import fill_backend_with_prefix
15
+ from ._signal import PvaSignalBackend, pvget_with_timeout
16
+
17
+ Entry = dict[str, str]
18
+
19
+
20
+ def _get_signal_details(entry: Entry) -> tuple[type[Signal], str, str]:
21
+ match entry:
22
+ case {"r": read_pv}:
23
+ return SignalR, read_pv, read_pv
24
+ case {"r": read_pv, "w": write_pv}:
25
+ return SignalRW, read_pv, write_pv
26
+ case {"rw": read_write_pv}:
27
+ return SignalRW, read_write_pv, read_write_pv
28
+ case {"x": execute_pv}:
29
+ return SignalX, execute_pv, execute_pv
30
+ case _:
31
+ raise TypeError(f"Can't process entry {entry}")
32
+
33
+
34
+ class PviDeviceConnector(DeviceConnector):
35
+ def __init__(self, prefix: str = "") -> None:
36
+ # TODO: what happens if we get a leading "pva://" here?
37
+ self.prefix = prefix
38
+ self.pvi_pv = prefix + "PVI"
39
+
40
+ def create_children_from_annotations(self, device: Device):
41
+ if not hasattr(self, "filler"):
42
+ self.filler = DeviceFiller(
43
+ device=device,
44
+ signal_backend_factory=PvaSignalBackend,
45
+ device_connector_factory=PviDeviceConnector,
46
+ )
47
+ # Devices will be created with unfilled PviDeviceConnectors
48
+ list(self.filler.create_devices_from_annotations(filled=False))
49
+ # Signals can be filled in with EpicsSignalSuffix and checked at runtime
50
+ for backend, annotations in self.filler.create_signals_from_annotations(
51
+ filled=False
52
+ ):
53
+ fill_backend_with_prefix(self.prefix, backend, annotations)
54
+ self.filler.check_created()
55
+
56
+ def _fill_child(self, name: str, entry: Entry, vector_index: int | None = None):
57
+ if set(entry) == {"d"}:
58
+ connector = self.filler.fill_child_device(name, vector_index=vector_index)
59
+ connector.pvi_pv = entry["d"]
60
+ else:
61
+ signal_type, read_pv, write_pv = _get_signal_details(entry)
62
+ backend = self.filler.fill_child_signal(name, signal_type, vector_index)
63
+ backend.read_pv = read_pv
64
+ backend.write_pv = write_pv
65
+
66
+ async def connect_mock(self, device: Device, mock: LazyMock):
67
+ self.filler.create_device_vector_entries_to_mock(2)
68
+ # Set the name of the device to name all children
69
+ device.set_name(device.name)
70
+ return await super().connect_mock(device, mock)
71
+
72
+ async def connect_real(
73
+ self, device: Device, timeout: float, force_reconnect: bool
74
+ ) -> None:
75
+ pvi_structure = await pvget_with_timeout(self.pvi_pv, timeout)
76
+ entries: dict[str, Entry | list[Entry | None]] = pvi_structure["value"].todict()
77
+ # Fill based on what PVI gives us
78
+ for name, entry in entries.items():
79
+ if isinstance(entry, dict):
80
+ # This is a child
81
+ self._fill_child(name, entry)
82
+ else:
83
+ # This is a DeviceVector of children
84
+ for i, e in enumerate(entry):
85
+ if e:
86
+ self._fill_child(name, e, i)
87
+ # Check that all the requested children have been filled
88
+ self.filler.check_filled(f"{self.pvi_pv}: {entries}")
89
+ # Set the name of the device to name all children
90
+ device.set_name(device.name)
91
+ return await super().connect_real(device, timeout, force_reconnect)
@@ -14,13 +14,7 @@ from ophyd_async.core import (
14
14
  get_unique,
15
15
  )
16
16
 
17
-
18
- def _make_unavailable_class(error: Exception) -> type:
19
- class TransportNotAvailable:
20
- def __init__(*args, **kwargs):
21
- raise NotImplementedError("Transport not available") from error
22
-
23
- return TransportNotAvailable
17
+ from ._util import EpicsSignalBackend
24
18
 
25
19
 
26
20
  class EpicsProtocol(Enum):
@@ -30,10 +24,26 @@ class EpicsProtocol(Enum):
30
24
 
31
25
  _default_epics_protocol = EpicsProtocol.CA
32
26
 
27
+
28
+ def _make_unavailable_function(error: Exception):
29
+ def transport_not_available(*args, **kwargs):
30
+ raise NotImplementedError("Transport not available") from error
31
+
32
+ return transport_not_available
33
+
34
+
35
+ def _make_unavailable_class(error: Exception) -> type[EpicsSignalBackend]:
36
+ class TransportNotAvailable(EpicsSignalBackend):
37
+ __init__ = _make_unavailable_function(error)
38
+
39
+ return TransportNotAvailable
40
+
41
+
33
42
  try:
34
- from ._p4p import PvaSignalBackend
43
+ from ._p4p import PvaSignalBackend, pvget_with_timeout
35
44
  except ImportError as pva_error:
36
45
  PvaSignalBackend = _make_unavailable_class(pva_error)
46
+ pvget_with_timeout = _make_unavailable_function(pva_error)
37
47
  else:
38
48
  _default_epics_protocol = EpicsProtocol.PVA
39
49
 
@@ -45,7 +55,7 @@ else:
45
55
  _default_epics_protocol = EpicsProtocol.CA
46
56
 
47
57
 
48
- def _protocol_pv(pv: str) -> tuple[EpicsProtocol, str]:
58
+ def split_protocol_from_pv(pv: str) -> tuple[EpicsProtocol, str]:
49
59
  split = pv.split("://", 1)
50
60
  if len(split) > 1:
51
61
  # We got something like pva://mydevice, so use specified comms mode
@@ -57,18 +67,23 @@ def _protocol_pv(pv: str) -> tuple[EpicsProtocol, str]:
57
67
  return protocol, pv
58
68
 
59
69
 
70
+ def get_signal_backend_type(protocol: EpicsProtocol) -> type[EpicsSignalBackend]:
71
+ match protocol:
72
+ case EpicsProtocol.CA:
73
+ return CaSignalBackend
74
+ case EpicsProtocol.PVA:
75
+ return PvaSignalBackend
76
+
77
+
60
78
  def _epics_signal_backend(
61
79
  datatype: type[SignalDatatypeT] | None, read_pv: str, write_pv: str
62
80
  ) -> SignalBackend[SignalDatatypeT]:
63
81
  """Create an epics signal backend."""
64
- r_protocol, r_pv = _protocol_pv(read_pv)
65
- w_protocol, w_pv = _protocol_pv(write_pv)
82
+ r_protocol, r_pv = split_protocol_from_pv(read_pv)
83
+ w_protocol, w_pv = split_protocol_from_pv(write_pv)
66
84
  protocol = get_unique({read_pv: r_protocol, write_pv: w_protocol}, "protocols")
67
- match protocol:
68
- case EpicsProtocol.CA:
69
- return CaSignalBackend(datatype, r_pv, w_pv)
70
- case EpicsProtocol.PVA:
71
- return PvaSignalBackend(datatype, r_pv, w_pv)
85
+ signal_backend_type = get_signal_backend_type(protocol)
86
+ return signal_backend_type(datatype, r_pv, w_pv)
72
87
 
73
88
 
74
89
  def epics_signal_rw(
@@ -3,7 +3,13 @@ from typing import Any, get_args, get_origin
3
3
 
4
4
  import numpy as np
5
5
 
6
- from ophyd_async.core import SubsetEnum, get_dtype, get_enum_cls
6
+ from ophyd_async.core import (
7
+ SignalBackend,
8
+ SignalDatatypeT,
9
+ SubsetEnum,
10
+ get_dtype,
11
+ get_enum_cls,
12
+ )
7
13
 
8
14
 
9
15
  def get_supported_values(
@@ -41,3 +47,15 @@ def format_datatype(datatype: Any) -> str:
41
47
  return datatype.__name__
42
48
  else:
43
49
  return str(datatype)
50
+
51
+
52
+ class EpicsSignalBackend(SignalBackend[SignalDatatypeT]):
53
+ def __init__(
54
+ self,
55
+ datatype: type[SignalDatatypeT] | None,
56
+ read_pv: str = "",
57
+ write_pv: str = "",
58
+ ):
59
+ self.read_pv = read_pv
60
+ self.write_pv = write_pv
61
+ super().__init__(datatype)
@@ -8,15 +8,14 @@ from ophyd_async.core import (
8
8
  DEFAULT_TIMEOUT,
9
9
  AsyncStatus,
10
10
  CalculatableTimeout,
11
- ConfigSignal,
12
11
  Device,
13
- HintedSignal,
14
12
  StandardReadable,
15
13
  WatchableAsyncStatus,
16
14
  WatcherUpdate,
17
15
  observe_value,
18
16
  )
19
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw, epics_signal_x
17
+ from ophyd_async.core import StandardReadableFormat as Format
18
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw, epics_signal_x
20
19
 
21
20
 
22
21
  class Mover(StandardReadable, Movable, Stoppable):
@@ -24,9 +23,9 @@ class Mover(StandardReadable, Movable, Stoppable):
24
23
 
25
24
  def __init__(self, prefix: str, name="") -> None:
26
25
  # Define some signals
27
- with self.add_children_as_readables(HintedSignal):
26
+ with self.add_children_as_readables(Format.HINTED_SIGNAL):
28
27
  self.readback = epics_signal_r(float, prefix + "Readback")
29
- with self.add_children_as_readables(ConfigSignal):
28
+ with self.add_children_as_readables(Format.CONFIG_SIGNAL):
30
29
  self.velocity = epics_signal_rw(float, prefix + "Velocity")
31
30
  self.units = epics_signal_r(str, prefix + "Readback.EGU")
32
31
  self.setpoint = epics_signal_rw(float, prefix + "Setpoint")
@@ -1,11 +1,14 @@
1
+ from typing import Annotated as A
2
+
1
3
  from ophyd_async.core import (
2
- ConfigSignal,
3
4
  DeviceVector,
4
- HintedSignal,
5
+ SignalR,
6
+ SignalRW,
5
7
  StandardReadable,
6
8
  StrictEnum,
7
9
  )
8
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
10
+ from ophyd_async.core import StandardReadableFormat as Format
11
+ from ophyd_async.epics.core import EpicsDevice, PvSuffix
9
12
 
10
13
 
11
14
  class EnergyMode(StrictEnum):
@@ -17,17 +20,11 @@ class EnergyMode(StrictEnum):
17
20
  high = "High Energy"
18
21
 
19
22
 
20
- class Sensor(StandardReadable):
23
+ class Sensor(StandardReadable, EpicsDevice):
21
24
  """A demo sensor that produces a scalar value based on X and Y Movers"""
22
25
 
23
- def __init__(self, prefix: str, name="") -> None:
24
- # Define some signals
25
- with self.add_children_as_readables(HintedSignal):
26
- self.value = epics_signal_r(float, prefix + "Value")
27
- with self.add_children_as_readables(ConfigSignal):
28
- self.mode = epics_signal_rw(EnergyMode, prefix + "Mode")
29
-
30
- super().__init__(name=name)
26
+ value: A[SignalR[float], PvSuffix("Value"), Format.HINTED_SIGNAL]
27
+ mode: A[SignalRW[EnergyMode], PvSuffix("Mode"), Format.CONFIG_SIGNAL]
31
28
 
32
29
 
33
30
  class SensorGroup(StandardReadable):
@@ -1,5 +1,5 @@
1
1
  from ophyd_async.core import Device, StrictEnum
2
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw_rbv, epics_signal_w
2
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw_rbv, epics_signal_w
3
3
 
4
4
 
5
5
  class EigerTriggerMode(StrictEnum):
@@ -15,7 +15,7 @@ from ophyd_async.core import (
15
15
  observe_value,
16
16
  set_and_wait_for_value,
17
17
  )
18
- from ophyd_async.epics.signal import (
18
+ from ophyd_async.epics.core import (
19
19
  epics_signal_r,
20
20
  epics_signal_rw,
21
21
  epics_signal_rw_rbv,
@@ -14,14 +14,13 @@ from ophyd_async.core import (
14
14
  DEFAULT_TIMEOUT,
15
15
  AsyncStatus,
16
16
  CalculatableTimeout,
17
- ConfigSignal,
18
- HintedSignal,
19
17
  StandardReadable,
20
18
  WatchableAsyncStatus,
21
19
  WatcherUpdate,
22
20
  observe_value,
23
21
  )
24
- from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw, epics_signal_x
22
+ from ophyd_async.core import StandardReadableFormat as Format
23
+ from ophyd_async.epics.core import epics_signal_r, epics_signal_rw, epics_signal_x
25
24
 
26
25
 
27
26
  class MotorLimitsException(Exception):
@@ -61,11 +60,11 @@ class Motor(StandardReadable, Locatable, Stoppable, Flyable, Preparable):
61
60
 
62
61
  def __init__(self, prefix: str, name="") -> None:
63
62
  # Define some signals
64
- with self.add_children_as_readables(ConfigSignal):
63
+ with self.add_children_as_readables(Format.CONFIG_SIGNAL):
65
64
  self.motor_egu = epics_signal_r(str, prefix + ".EGU")
66
65
  self.velocity = epics_signal_rw(float, prefix + ".VELO")
67
66
 
68
- with self.add_children_as_readables(HintedSignal):
67
+ with self.add_children_as_readables(Format.HINTED_SIGNAL):
69
68
  self.user_readback = epics_signal_r(float, prefix + ".RBV")
70
69
 
71
70
  self.user_setpoint = epics_signal_rw(float, prefix + ".VAL")
@@ -0,0 +1,11 @@
1
+ # back compat
2
+ import warnings
3
+
4
+ from .core import * # noqa: F403
5
+
6
+ warnings.warn(
7
+ DeprecationWarning(
8
+ "Use `ophyd_async.epics.core` instead of `ophyd_async.epics.signal` and `pvi`"
9
+ ),
10
+ stacklevel=2,
11
+ )
@@ -1,9 +1,9 @@
1
1
  from ophyd_async.core import Device, DeviceConnector
2
- from ophyd_async.epics.pvi import PviDeviceConnector
2
+ from ophyd_async.epics.core import PviDeviceConnector
3
3
 
4
4
 
5
5
  def fastcs_connector(device: Device, uri: str) -> DeviceConnector:
6
6
  # TODO: add Tango support based on uri scheme
7
- connector = PviDeviceConnector(uri + "PVI")
7
+ connector = PviDeviceConnector(uri)
8
8
  connector.create_children_from_annotations(device)
9
9
  return connector
@@ -1,13 +1,11 @@
1
- from unittest.mock import Mock
2
-
3
1
  import bluesky.plan_stubs as bps
4
2
 
5
- from ophyd_async.core import DEFAULT_TIMEOUT, Device, wait_for_connection
3
+ from ophyd_async.core import DEFAULT_TIMEOUT, Device, LazyMock, wait_for_connection
6
4
 
7
5
 
8
6
  def ensure_connected(
9
7
  *devices: Device,
10
- mock: bool | Mock = False,
8
+ mock: bool | LazyMock = False,
11
9
  timeout: float = DEFAULT_TIMEOUT,
12
10
  force_reconnect=False,
13
11
  ):
@@ -6,8 +6,6 @@ from bluesky.protocols import Movable, Stoppable
6
6
 
7
7
  from ophyd_async.core import (
8
8
  AsyncStatus,
9
- ConfigSignal,
10
- HintedSignal,
11
9
  StandardReadable,
12
10
  WatchableAsyncStatus,
13
11
  WatcherUpdate,
@@ -15,6 +13,7 @@ from ophyd_async.core import (
15
13
  soft_signal_r_and_setter,
16
14
  soft_signal_rw,
17
15
  )
16
+ from ophyd_async.core import StandardReadableFormat as Format
18
17
 
19
18
 
20
19
  class SimMotor(StandardReadable, Movable, Stoppable):
@@ -28,11 +27,11 @@ class SimMotor(StandardReadable, Movable, Stoppable):
28
27
  - instant: bool: whether to move instantly, or with a delay
29
28
  """
30
29
  # Define some signals
31
- with self.add_children_as_readables(HintedSignal):
30
+ with self.add_children_as_readables(Format.HINTED_SIGNAL):
32
31
  self.user_readback, self._user_readback_set = soft_signal_r_and_setter(
33
32
  float, 0
34
33
  )
35
- with self.add_children_as_readables(ConfigSignal):
34
+ with self.add_children_as_readables(Format.CONFIG_SIGNAL):
36
35
  self.velocity = soft_signal_rw(float, 0 if instant else 1.0)
37
36
  self.units = soft_signal_rw(str, "mm")
38
37
  self.user_setpoint = soft_signal_rw(float, 0)