ophyd-async 0.9.0a2__py3-none-any.whl → 0.10.0a2__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 (151) hide show
  1. ophyd_async/__init__.py +5 -8
  2. ophyd_async/_docs_parser.py +12 -0
  3. ophyd_async/_version.py +9 -4
  4. ophyd_async/core/__init__.py +97 -62
  5. ophyd_async/core/_derived_signal.py +271 -0
  6. ophyd_async/core/_derived_signal_backend.py +300 -0
  7. ophyd_async/core/_detector.py +106 -125
  8. ophyd_async/core/_device.py +69 -63
  9. ophyd_async/core/_device_filler.py +65 -1
  10. ophyd_async/core/_flyer.py +14 -5
  11. ophyd_async/core/_hdf_dataset.py +29 -22
  12. ophyd_async/core/_log.py +14 -23
  13. ophyd_async/core/_mock_signal_backend.py +11 -3
  14. ophyd_async/core/_protocol.py +65 -45
  15. ophyd_async/core/_providers.py +28 -9
  16. ophyd_async/core/_readable.py +44 -35
  17. ophyd_async/core/_settings.py +36 -27
  18. ophyd_async/core/_signal.py +262 -170
  19. ophyd_async/core/_signal_backend.py +56 -13
  20. ophyd_async/core/_soft_signal_backend.py +16 -11
  21. ophyd_async/core/_status.py +72 -24
  22. ophyd_async/core/_table.py +41 -11
  23. ophyd_async/core/_utils.py +96 -49
  24. ophyd_async/core/_yaml_settings.py +2 -0
  25. ophyd_async/epics/__init__.py +1 -0
  26. ophyd_async/epics/adandor/_andor.py +2 -2
  27. ophyd_async/epics/adandor/_andor_controller.py +4 -2
  28. ophyd_async/epics/adandor/_andor_io.py +2 -4
  29. ophyd_async/epics/adaravis/__init__.py +5 -0
  30. ophyd_async/epics/adaravis/_aravis.py +4 -8
  31. ophyd_async/epics/adaravis/_aravis_controller.py +20 -43
  32. ophyd_async/epics/adaravis/_aravis_io.py +13 -28
  33. ophyd_async/epics/adcore/__init__.py +23 -8
  34. ophyd_async/epics/adcore/_core_detector.py +42 -2
  35. ophyd_async/epics/adcore/_core_io.py +124 -99
  36. ophyd_async/epics/adcore/_core_logic.py +106 -27
  37. ophyd_async/epics/adcore/_core_writer.py +12 -8
  38. ophyd_async/epics/adcore/_hdf_writer.py +21 -38
  39. ophyd_async/epics/adcore/_single_trigger.py +2 -2
  40. ophyd_async/epics/adcore/_utils.py +2 -2
  41. ophyd_async/epics/adkinetix/__init__.py +2 -1
  42. ophyd_async/epics/adkinetix/_kinetix.py +3 -3
  43. ophyd_async/epics/adkinetix/_kinetix_controller.py +4 -2
  44. ophyd_async/epics/adkinetix/_kinetix_io.py +12 -13
  45. ophyd_async/epics/adpilatus/__init__.py +5 -0
  46. ophyd_async/epics/adpilatus/_pilatus.py +1 -1
  47. ophyd_async/epics/adpilatus/_pilatus_controller.py +5 -24
  48. ophyd_async/epics/adpilatus/_pilatus_io.py +11 -9
  49. ophyd_async/epics/adsimdetector/__init__.py +8 -1
  50. ophyd_async/epics/adsimdetector/_sim.py +4 -14
  51. ophyd_async/epics/adsimdetector/_sim_controller.py +17 -0
  52. ophyd_async/epics/adsimdetector/_sim_io.py +10 -0
  53. ophyd_async/epics/advimba/__init__.py +10 -1
  54. ophyd_async/epics/advimba/_vimba.py +3 -2
  55. ophyd_async/epics/advimba/_vimba_controller.py +4 -2
  56. ophyd_async/epics/advimba/_vimba_io.py +23 -28
  57. ophyd_async/epics/core/_aioca.py +35 -16
  58. ophyd_async/epics/core/_epics_connector.py +4 -0
  59. ophyd_async/epics/core/_epics_device.py +2 -0
  60. ophyd_async/epics/core/_p4p.py +10 -2
  61. ophyd_async/epics/core/_pvi_connector.py +65 -8
  62. ophyd_async/epics/core/_signal.py +51 -51
  63. ophyd_async/epics/core/_util.py +4 -4
  64. ophyd_async/epics/demo/__init__.py +16 -0
  65. ophyd_async/epics/demo/__main__.py +31 -0
  66. ophyd_async/epics/demo/_ioc.py +32 -0
  67. ophyd_async/epics/demo/_motor.py +82 -0
  68. ophyd_async/epics/demo/_point_detector.py +42 -0
  69. ophyd_async/epics/demo/_point_detector_channel.py +22 -0
  70. ophyd_async/epics/demo/_stage.py +15 -0
  71. ophyd_async/epics/{sim/mover.db → demo/motor.db} +2 -1
  72. ophyd_async/epics/demo/point_detector.db +59 -0
  73. ophyd_async/epics/demo/point_detector_channel.db +21 -0
  74. ophyd_async/epics/eiger/_eiger.py +1 -3
  75. ophyd_async/epics/eiger/_eiger_controller.py +11 -4
  76. ophyd_async/epics/eiger/_eiger_io.py +2 -0
  77. ophyd_async/epics/eiger/_odin_io.py +1 -2
  78. ophyd_async/epics/motor.py +65 -28
  79. ophyd_async/epics/signal.py +4 -1
  80. ophyd_async/epics/testing/_example_ioc.py +21 -9
  81. ophyd_async/epics/testing/_utils.py +3 -0
  82. ophyd_async/epics/testing/test_records.db +8 -0
  83. ophyd_async/epics/testing/test_records_pva.db +17 -16
  84. ophyd_async/fastcs/__init__.py +1 -0
  85. ophyd_async/fastcs/core.py +6 -0
  86. ophyd_async/fastcs/odin/__init__.py +1 -0
  87. ophyd_async/fastcs/panda/__init__.py +8 -6
  88. ophyd_async/fastcs/panda/_block.py +29 -9
  89. ophyd_async/fastcs/panda/_control.py +5 -0
  90. ophyd_async/fastcs/panda/_hdf_panda.py +2 -0
  91. ophyd_async/fastcs/panda/_table.py +9 -6
  92. ophyd_async/fastcs/panda/_trigger.py +23 -9
  93. ophyd_async/fastcs/panda/_writer.py +27 -30
  94. ophyd_async/plan_stubs/__init__.py +2 -0
  95. ophyd_async/plan_stubs/_ensure_connected.py +1 -0
  96. ophyd_async/plan_stubs/_fly.py +2 -4
  97. ophyd_async/plan_stubs/_nd_attributes.py +2 -0
  98. ophyd_async/plan_stubs/_panda.py +1 -0
  99. ophyd_async/plan_stubs/_settings.py +43 -16
  100. ophyd_async/plan_stubs/_utils.py +3 -0
  101. ophyd_async/plan_stubs/_wait_for_awaitable.py +1 -1
  102. ophyd_async/sim/__init__.py +24 -14
  103. ophyd_async/sim/__main__.py +43 -0
  104. ophyd_async/sim/_blob_detector.py +33 -0
  105. ophyd_async/sim/_blob_detector_controller.py +48 -0
  106. ophyd_async/sim/_blob_detector_writer.py +105 -0
  107. ophyd_async/sim/_mirror_horizontal.py +46 -0
  108. ophyd_async/sim/_mirror_vertical.py +74 -0
  109. ophyd_async/sim/_motor.py +233 -0
  110. ophyd_async/sim/_pattern_generator.py +124 -0
  111. ophyd_async/sim/_point_detector.py +86 -0
  112. ophyd_async/sim/_stage.py +19 -0
  113. ophyd_async/tango/__init__.py +1 -0
  114. ophyd_async/tango/core/__init__.py +6 -1
  115. ophyd_async/tango/core/_base_device.py +41 -33
  116. ophyd_async/tango/core/_converters.py +81 -0
  117. ophyd_async/tango/core/_signal.py +18 -32
  118. ophyd_async/tango/core/_tango_readable.py +2 -19
  119. ophyd_async/tango/core/_tango_transport.py +136 -60
  120. ophyd_async/tango/core/_utils.py +47 -0
  121. ophyd_async/tango/{sim → demo}/_counter.py +2 -0
  122. ophyd_async/tango/{sim → demo}/_detector.py +2 -0
  123. ophyd_async/tango/{sim → demo}/_mover.py +5 -4
  124. ophyd_async/tango/{sim → demo}/_tango/_servers.py +4 -0
  125. ophyd_async/tango/testing/__init__.py +6 -0
  126. ophyd_async/tango/testing/_one_of_everything.py +200 -0
  127. ophyd_async/testing/__init__.py +29 -7
  128. ophyd_async/testing/_assert.py +145 -83
  129. ophyd_async/testing/_mock_signal_utils.py +56 -70
  130. ophyd_async/testing/_one_of_everything.py +41 -21
  131. ophyd_async/testing/_single_derived.py +89 -0
  132. ophyd_async/testing/_utils.py +3 -0
  133. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a2.dist-info}/METADATA +25 -26
  134. ophyd_async-0.10.0a2.dist-info/RECORD +149 -0
  135. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a2.dist-info}/WHEEL +1 -1
  136. ophyd_async/epics/sim/__init__.py +0 -54
  137. ophyd_async/epics/sim/_ioc.py +0 -29
  138. ophyd_async/epics/sim/_mover.py +0 -101
  139. ophyd_async/epics/sim/_sensor.py +0 -37
  140. ophyd_async/epics/sim/sensor.db +0 -19
  141. ophyd_async/sim/_pattern_detector/__init__.py +0 -13
  142. ophyd_async/sim/_pattern_detector/_pattern_detector.py +0 -42
  143. ophyd_async/sim/_pattern_detector/_pattern_detector_controller.py +0 -69
  144. ophyd_async/sim/_pattern_detector/_pattern_detector_writer.py +0 -41
  145. ophyd_async/sim/_pattern_detector/_pattern_generator.py +0 -214
  146. ophyd_async/sim/_sim_motor.py +0 -107
  147. ophyd_async-0.9.0a2.dist-info/RECORD +0 -129
  148. /ophyd_async/tango/{sim → demo}/__init__.py +0 -0
  149. /ophyd_async/tango/{sim → demo}/_tango/__init__.py +0 -0
  150. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a2.dist-info/licenses}/LICENSE +0 -0
  151. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a2.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- from collections.abc import Awaitable, Callable, Iterable
1
+ from collections.abc import Awaitable, Callable, Iterable, Iterator
2
2
  from contextlib import contextmanager
3
3
  from unittest.mock import AsyncMock, Mock
4
4
 
@@ -14,6 +14,10 @@ from ophyd_async.core import (
14
14
 
15
15
 
16
16
  def get_mock(device: Device | Signal) -> Mock:
17
+ """Return the mock (which may have child mocks attached) for a Device.
18
+
19
+ The device must have been connected in mock mode.
20
+ """
17
21
  mock = device._mock # noqa: SLF001
18
22
  assert isinstance(mock, LazyMock), f"Device {device} not connected in mock mode"
19
23
  return mock()
@@ -34,36 +38,7 @@ def set_mock_value(signal: Signal[SignalDatatypeT], value: SignalDatatypeT):
34
38
  backend.set_value(value)
35
39
 
36
40
 
37
- def set_mock_put_proceeds(signal: Signal, proceeds: bool):
38
- """Allow or block a put with wait=True from proceeding"""
39
- backend = _get_mock_signal_backend(signal)
40
-
41
- if proceeds:
42
- backend.put_proceeds.set()
43
- else:
44
- backend.put_proceeds.clear()
45
-
46
-
47
- @contextmanager
48
- def mock_puts_blocked(*signals: Signal):
49
- for signal in signals:
50
- set_mock_put_proceeds(signal, False)
51
- yield
52
- for signal in signals:
53
- set_mock_put_proceeds(signal, True)
54
-
55
-
56
- def get_mock_put(signal: Signal) -> AsyncMock:
57
- """Get the mock associated with the put call on the signal."""
58
- return _get_mock_signal_backend(signal).put_mock
59
-
60
-
61
- def reset_mock_put_calls(signal: Signal):
62
- backend = _get_mock_signal_backend(signal)
63
- backend.put_mock.reset_mock()
64
-
65
-
66
- class _SetValuesIterator:
41
+ class _SetValuesIterator(Iterator[SignalDatatypeT]):
67
42
  # Garbage collected by the time __del__ is called unless we put it as a
68
43
  # global attrbute here.
69
44
  require_all_consumed: bool = False
@@ -78,13 +53,9 @@ class _SetValuesIterator:
78
53
  self.values = values
79
54
  self.require_all_consumed = require_all_consumed
80
55
  self.index = 0
81
-
82
56
  self.iterator = enumerate(values, start=1)
83
57
 
84
- def __iter__(self):
85
- return self
86
-
87
- def __next__(self):
58
+ def __next__(self) -> SignalDatatypeT:
88
59
  # Will propogate StopIteration
89
60
  self.index, next_value = next(self.iterator)
90
61
  set_mock_value(self.signal, next_value)
@@ -113,33 +84,26 @@ def set_mock_values(
113
84
  signal: SignalR[SignalDatatypeT],
114
85
  values: Iterable[SignalDatatypeT],
115
86
  require_all_consumed: bool = False,
116
- ) -> _SetValuesIterator:
117
- """Iterator to set a signal to a sequence of values, optionally repeating the
118
- sequence.
119
-
120
- Parameters
121
- ----------
122
- signal:
123
- A signal with a `MockSignalBackend` backend.
124
- values:
125
- An iterable of the values to set the signal to, on each iteration
126
- the value will be set.
127
- require_all_consumed:
128
- If True, an AssertionError will be raised if the iterator is deleted before
129
- all values have been consumed.
130
-
131
- Notes
132
- -----
133
- Example usage::
134
-
135
- for value_set in set_mock_values(signal, [1, 2, 3]):
136
- # do something
137
-
138
- cm = set_mock_values(signal, 1, 2, 3, require_all_consumed=True):
139
- next(cm)
140
- # do something
87
+ ) -> Iterator[SignalDatatypeT]:
88
+ """Set a signal to a sequence of values, optionally repeating.
89
+
90
+ :param signal: A signal connected in mock mode.
91
+ :param values:
92
+ An iterable of the values to set the signal to, on each iteration the
93
+ next value will be set.
94
+ :param require_all_consumed:
95
+ If True, an AssertionError will be raised if the iterator is deleted
96
+ before all values have been consumed.
97
+
98
+ :example:
99
+ ```python
100
+ for value_set in set_mock_values(signal, range(3)):
101
+ # do something
102
+
103
+ cm = set_mock_values(signal, [1, 3, 8], require_all_consumed=True):
104
+ next(cm) # do something
105
+ ```
141
106
  """
142
-
143
107
  return _SetValuesIterator(
144
108
  signal,
145
109
  values,
@@ -160,16 +124,38 @@ def callback_on_mock_put(
160
124
  ):
161
125
  """For setting a callback when a backend is put to.
162
126
 
163
- Can either be used in a context, with the callback being
164
- unset on exit, or as an ordinary function.
127
+ Can either be used in a context, with the callback being unset on exit, or
128
+ as an ordinary function.
165
129
 
166
- Parameters
167
- ----------
168
- signal:
169
- A signal with a `MockSignalBackend` backend.
170
- callback:
171
- The callback to call when the backend is put to during the context.
130
+ :param signal: A signal with a `MockSignalBackend` backend.
131
+ :param callback: The callback to call when the backend is put to during the
132
+ context.
172
133
  """
173
134
  backend = _get_mock_signal_backend(signal)
174
135
  backend.put_mock.side_effect = callback
175
136
  return _unset_side_effect_cm(backend.put_mock)
137
+
138
+
139
+ def set_mock_put_proceeds(signal: Signal, proceeds: bool):
140
+ """Allow or block a put with wait=True from proceeding."""
141
+ backend = _get_mock_signal_backend(signal)
142
+
143
+ if proceeds:
144
+ backend.put_proceeds.set()
145
+ else:
146
+ backend.put_proceeds.clear()
147
+
148
+
149
+ @contextmanager
150
+ def mock_puts_blocked(*signals: Signal):
151
+ """Context manager to block puts at the start and unblock at the end."""
152
+ for signal in signals:
153
+ set_mock_put_proceeds(signal, False)
154
+ yield
155
+ for signal in signals:
156
+ set_mock_put_proceeds(signal, True)
157
+
158
+
159
+ def get_mock_put(signal: Signal) -> AsyncMock:
160
+ """Get the mock associated with the put call on the signal."""
161
+ return _get_mock_signal_backend(signal).put_mock
@@ -19,32 +19,36 @@ from ophyd_async.core._device import DeviceVector
19
19
 
20
20
 
21
21
  class ExampleEnum(StrictEnum):
22
+ """Example of a strict Enum datatype."""
23
+
22
24
  A = "Aaa"
23
25
  B = "Bbb"
24
26
  C = "Ccc"
25
27
 
26
28
 
27
29
  class ExampleTable(Table):
28
- bool: Array1D[np.bool_]
29
- int: Array1D[np.int32]
30
- float: Array1D[np.float64]
31
- str: Sequence[str]
32
- enum: Sequence[ExampleEnum]
30
+ a_bool: Array1D[np.bool_]
31
+ a_int: Array1D[np.int32]
32
+ a_float: Array1D[np.float64]
33
+ a_str: Sequence[str]
34
+ a_enum: Sequence[ExampleEnum]
35
+
36
+
37
+ def int_array_value(dtype: type[DTypeScalar_co]):
38
+ iinfo = np.iinfo(dtype) # type: ignore
39
+ return np.array([iinfo.min, iinfo.max, 0, 1, 2, 3, 4], dtype=dtype)
33
40
 
34
41
 
35
42
  def int_array_signal(
36
43
  dtype: type[DTypeScalar_co], name: str = ""
37
44
  ) -> SignalRW[Array1D[DTypeScalar_co]]:
38
- iinfo = np.iinfo(dtype) # type: ignore
39
- value = np.array([iinfo.min, iinfo.max, 0, 1, 2, 3, 4], dtype=dtype)
45
+ value = int_array_value(dtype)
40
46
  return soft_signal_rw(Array1D[dtype], value, name)
41
47
 
42
48
 
43
- def float_array_signal(
44
- dtype: type[DTypeScalar_co], name: str = ""
45
- ) -> SignalRW[Array1D[DTypeScalar_co]]:
49
+ def float_array_value(dtype: type[DTypeScalar_co]):
46
50
  finfo = np.finfo(dtype) # type: ignore
47
- value = np.array(
51
+ return np.array(
48
52
  [
49
53
  finfo.min,
50
54
  finfo.max,
@@ -57,19 +61,30 @@ def float_array_signal(
57
61
  ],
58
62
  dtype=dtype,
59
63
  )
64
+
65
+
66
+ def float_array_signal(
67
+ dtype: type[DTypeScalar_co], name: str = ""
68
+ ) -> SignalRW[Array1D[DTypeScalar_co]]:
69
+ value = float_array_value(dtype)
60
70
  return soft_signal_rw(Array1D[dtype], value, name)
61
71
 
62
72
 
63
73
  class OneOfEverythingDevice(StandardReadable):
74
+ """A device with one of every datatype allowed on signals."""
75
+
64
76
  # make a detector to test assert_configuration
65
77
  def __init__(self, name=""):
66
78
  # add all signals to configuration
67
79
  with self.add_children_as_readables(Format.CONFIG_SIGNAL):
68
- self.int = soft_signal_rw(int, 1)
69
- self.float = soft_signal_rw(float, 1.234)
70
- self.str = soft_signal_rw(str, "test_string")
71
- self.bool = soft_signal_rw(bool, True)
72
- self.enum = soft_signal_rw(ExampleEnum, ExampleEnum.B)
80
+ self.a_int = soft_signal_rw(int, 1)
81
+ self.a_float = soft_signal_rw(float, 1.234)
82
+ self.a_str = soft_signal_rw(str, "test_string")
83
+ self.a_bool = soft_signal_rw(bool, True)
84
+ self.a_enum = soft_signal_rw(ExampleEnum, ExampleEnum.B)
85
+ self.boola = soft_signal_rw(
86
+ Array1D[np.bool_], np.array([False, False, True])
87
+ )
73
88
  self.int8a = int_array_signal(np.int8)
74
89
  self.uint8a = int_array_signal(np.uint8)
75
90
  self.int16a = int_array_signal(np.int16)
@@ -91,16 +106,19 @@ class OneOfEverythingDevice(StandardReadable):
91
106
  self.table = soft_signal_rw(
92
107
  ExampleTable,
93
108
  ExampleTable(
94
- bool=np.array([False, False, True, True], np.bool_),
95
- int=np.array([1, 8, -9, 32], np.int32),
96
- float=np.array([1.8, 8.2, -6, 32.9887], np.float64),
97
- str=["Hello", "World", "Foo", "Bar"],
98
- enum=[ExampleEnum.A, ExampleEnum.B, ExampleEnum.A, ExampleEnum.C],
109
+ a_bool=np.array([False, False, True, True], np.bool_),
110
+ a_int=np.array([1, 8, -9, 32], np.int32),
111
+ a_float=np.array([1.8, 8.2, -6, 32.9887], np.float64),
112
+ a_str=["Hello", "World", "Foo", "Bar"],
113
+ a_enum=[ExampleEnum.A, ExampleEnum.B, ExampleEnum.A, ExampleEnum.C],
99
114
  ),
100
115
  )
101
116
  self.ndarray = soft_signal_rw(np.ndarray, np.array(([1, 2, 3], [4, 5, 6])))
102
117
  super().__init__(name)
103
118
 
119
+ async def get_signal_values(self):
120
+ return await _get_signal_values(self)
121
+
104
122
 
105
123
  async def _get_signal_values(child: Device) -> dict[SignalRW, Any]:
106
124
  if isinstance(child, SignalRW):
@@ -112,6 +130,8 @@ async def _get_signal_values(child: Device) -> dict[SignalRW, Any]:
112
130
 
113
131
 
114
132
  class ParentOfEverythingDevice(Device):
133
+ """Device containing subdevices with one of every datatype allowed on signals."""
134
+
115
135
  def __init__(self, name=""):
116
136
  self.child = OneOfEverythingDevice()
117
137
  self.vector = DeviceVector(
@@ -0,0 +1,89 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+
5
+ from ophyd_async.core import (
6
+ Device,
7
+ DeviceVector,
8
+ StandardReadable,
9
+ StrictEnum,
10
+ derived_signal_r,
11
+ derived_signal_rw,
12
+ derived_signal_w,
13
+ soft_signal_rw,
14
+ )
15
+
16
+
17
+ class BeamstopPosition(StrictEnum):
18
+ IN_POSITION = "In position"
19
+ OUT_OF_POSITION = "Out of position"
20
+
21
+
22
+ class ReadOnlyBeamstop(Device):
23
+ """Reads from 2 motors to work out if the beamstop is in position.
24
+
25
+ E.g. bps.rd(beamstop.position)
26
+ """
27
+
28
+ def __init__(self, name=""):
29
+ # Raw signals
30
+ self.x = soft_signal_rw(float)
31
+ self.y = soft_signal_rw(float)
32
+ # Derived signals
33
+ self.position = derived_signal_r(self._get_position, x=self.x, y=self.y)
34
+ super().__init__(name=name)
35
+
36
+ def _get_position(self, x: float, y: float) -> BeamstopPosition:
37
+ if abs(x) < 1 and abs(y) < 2:
38
+ return BeamstopPosition.IN_POSITION
39
+ else:
40
+ return BeamstopPosition.OUT_OF_POSITION
41
+
42
+
43
+ class MovableBeamstop(Device):
44
+ """As well as reads, this one allows you to move it.
45
+
46
+ E.g. bps.mv(beamstop.position, BeamstopPosition.IN_POSITION)
47
+ """
48
+
49
+ def __init__(self, name=""):
50
+ # Raw signals
51
+ self.x = soft_signal_rw(float)
52
+ self.y = soft_signal_rw(float)
53
+ # Derived signals
54
+ self.position = derived_signal_rw(
55
+ self._get_position, self._set_from_position, x=self.x, y=self.y
56
+ )
57
+ super().__init__(name=name)
58
+
59
+ def _get_position(self, x: float, y: float) -> BeamstopPosition:
60
+ if abs(x) < 1 and abs(y) < 2:
61
+ return BeamstopPosition.IN_POSITION
62
+ else:
63
+ return BeamstopPosition.OUT_OF_POSITION
64
+
65
+ async def _set_from_position(self, position: BeamstopPosition) -> None:
66
+ if position == BeamstopPosition.IN_POSITION:
67
+ await asyncio.gather(self.x.set(0), self.y.set(0))
68
+ else:
69
+ await asyncio.gather(self.x.set(3), self.y.set(5))
70
+
71
+
72
+ class Exploder(StandardReadable):
73
+ """This one takes a value and sets all its signal to that value.
74
+
75
+ This allows convenience "set all" functions, while the individual
76
+ signals are still free to be set to different values.
77
+ """
78
+
79
+ def __init__(self, num_signals: int, name=""):
80
+ with self.add_children_as_readables():
81
+ self.signals = DeviceVector(
82
+ {i: soft_signal_rw(int, units="cts") for i in range(1, num_signals + 1)}
83
+ )
84
+ self.set_all = derived_signal_w(self._set_all, derived_units="cts")
85
+ super().__init__(name=name)
86
+
87
+ async def _set_all(self, value: int) -> None:
88
+ coros = [sig.set(value) for sig in self.signals.values()]
89
+ await asyncio.gather(*coros)
@@ -0,0 +1,3 @@
1
+ from typing import TypeVar
2
+
3
+ T = TypeVar("T")
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: ophyd-async
3
- Version: 0.9.0a2
3
+ Version: 0.10.0a2
4
4
  Summary: Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
5
5
  Author-email: Tom Cobb <tom.cobb@diamond.ac.uk>
6
6
  License: BSD 3-Clause License
@@ -41,35 +41,33 @@ Classifier: Programming Language :: Python :: 3.12
41
41
  Requires-Python: >=3.10
42
42
  Description-Content-Type: text/markdown
43
43
  License-File: LICENSE
44
- Requires-Dist: networkx>=2.0
45
44
  Requires-Dist: numpy
46
- Requires-Dist: packaging
47
- Requires-Dist: pint
48
- Requires-Dist: bluesky>=1.13
45
+ Requires-Dist: bluesky>=1.13.1rc2
49
46
  Requires-Dist: event-model>=1.22.1
50
- Requires-Dist: p4p>=4.2.0a3
51
47
  Requires-Dist: pyyaml
52
48
  Requires-Dist: colorlog
53
49
  Requires-Dist: pydantic>=2.0
54
50
  Requires-Dist: pydantic-numpy
51
+ Provides-Extra: sim
52
+ Requires-Dist: h5py; extra == "sim"
55
53
  Provides-Extra: ca
56
54
  Requires-Dist: aioca>=1.6; extra == "ca"
57
55
  Provides-Extra: pva
58
- Requires-Dist: p4p; extra == "pva"
59
- Provides-Extra: sim
60
- Requires-Dist: h5py; extra == "sim"
56
+ Requires-Dist: p4p>=4.2.0; extra == "pva"
61
57
  Provides-Extra: tango
62
- Requires-Dist: pytango>=10.0.0; extra == "tango"
58
+ Requires-Dist: pytango==10.0.0; extra == "tango"
59
+ Provides-Extra: demo
60
+ Requires-Dist: ipython; extra == "demo"
61
+ Requires-Dist: matplotlib; extra == "demo"
62
+ Requires-Dist: pyqt6; extra == "demo"
63
63
  Provides-Extra: dev
64
- Requires-Dist: ophyd_async[pva]; extra == "dev"
65
64
  Requires-Dist: ophyd_async[sim]; extra == "dev"
66
65
  Requires-Dist: ophyd_async[ca]; extra == "dev"
66
+ Requires-Dist: ophyd_async[pva]; extra == "dev"
67
67
  Requires-Dist: ophyd_async[tango]; extra == "dev"
68
+ Requires-Dist: ophyd_async[demo]; extra == "dev"
68
69
  Requires-Dist: inflection; extra == "dev"
69
- Requires-Dist: ipython; extra == "dev"
70
- Requires-Dist: ipywidgets; extra == "dev"
71
70
  Requires-Dist: import-linter; extra == "dev"
72
- Requires-Dist: matplotlib; extra == "dev"
73
71
  Requires-Dist: myst-parser; extra == "dev"
74
72
  Requires-Dist: numpydoc; extra == "dev"
75
73
  Requires-Dist: ophyd; extra == "dev"
@@ -79,7 +77,6 @@ Requires-Dist: pre-commit; extra == "dev"
79
77
  Requires-Dist: pydata-sphinx-theme>=0.12; extra == "dev"
80
78
  Requires-Dist: pyepics>=3.4.2; extra == "dev"
81
79
  Requires-Dist: pyright; extra == "dev"
82
- Requires-Dist: pyside6==6.7.0; extra == "dev"
83
80
  Requires-Dist: pytest; extra == "dev"
84
81
  Requires-Dist: pytest-asyncio; extra == "dev"
85
82
  Requires-Dist: pytest-cov; extra == "dev"
@@ -88,16 +85,15 @@ Requires-Dist: pytest-forked; extra == "dev"
88
85
  Requires-Dist: pytest-rerunfailures; extra == "dev"
89
86
  Requires-Dist: pytest-timeout; extra == "dev"
90
87
  Requires-Dist: ruff; extra == "dev"
91
- Requires-Dist: sphinx<7.4.0; extra == "dev"
92
88
  Requires-Dist: sphinx-autobuild; extra == "dev"
93
- Requires-Dist: autodoc-pydantic; extra == "dev"
89
+ Requires-Dist: sphinx-autodoc2; extra == "dev"
94
90
  Requires-Dist: sphinxcontrib-mermaid; extra == "dev"
95
91
  Requires-Dist: sphinx-copybutton; extra == "dev"
96
92
  Requires-Dist: sphinx-design; extra == "dev"
97
- Requires-Dist: super_state_machine; extra == "dev"
98
93
  Requires-Dist: tox-direct; extra == "dev"
99
94
  Requires-Dist: types-mock; extra == "dev"
100
95
  Requires-Dist: types-pyyaml; extra == "dev"
96
+ Dynamic: license-file
101
97
 
102
98
  [![CI](https://github.com/bluesky/ophyd-async/actions/workflows/ci.yml/badge.svg)](https://github.com/bluesky/ophyd-async/actions/workflows/ci.yml)
103
99
  [![Coverage](https://codecov.io/gh/bluesky/ophyd-async/branch/main/graph/badge.svg)](https://codecov.io/gh/bluesky/ophyd-async)
@@ -114,16 +110,19 @@ Asynchronous Bluesky hardware abstraction code, compatible with control systems
114
110
  | Documentation | <https://bluesky.github.io/ophyd-async> |
115
111
  | Releases | <https://github.com/bluesky/ophyd-async/releases> |
116
112
 
117
- Ophyd-async is a Python library for asynchronously interfacing with hardware, intended to
118
- be used as an abstraction layer that enables experiment orchestration and data acquisition code to operate above the specifics of particular devices and control
119
- systems.
113
+ Ophyd-async is a Python library for asynchronously interfacing with hardware, intended to be used as an abstraction layer that enables experiment orchestration and data acquisition code to operate above the specifics of particular devices and control systems.
114
+
115
+ Both ophyd sync and ophyd-async are typically used with the [Bluesky Run Engine][] for experiment orchestration and data acquisition.
116
+
117
+ The main differences from ophyd sync are:
120
118
 
121
- Both ophyd and ophyd-async are typically used with the [Bluesky Run Engine][] for experiment orchestration and data acquisition.
119
+ - Asynchronous Signal access, simplifying the parallel control of multiple Signals
120
+ - Support for [EPICS][] PVA and [Tango][] as well as the traditional EPICS CA
121
+ - Better library support for splitting the logic from the hardware interface to avoid complex class heirarchies
122
122
 
123
- While [EPICS][] is the most common control system layer that ophyd-async can interface with, support for other control systems like [Tango][] will be supported in the future. The focus of ophyd-async is:
123
+ It was written with the aim of implementing flyscanning in a generic and extensible way with highly customizable devices like PandABox and the Delta Tau PMAC products. Using async code makes it possible to do the "put 3 PVs in parallel, then get from another PV" logic that is common in flyscanning without the performance and complexity overhead of multiple threads.
124
124
 
125
- * Asynchronous signal access, opening the possibility for hardware-triggered scanning (also known as fly-scanning)
126
- * Simpler instantiation of devices (groupings of signals) with less reliance upon complex class hierarchies
125
+ Devices from both ophyd sync and ophyd-async can be used in the same RunEngine and even in the same scan. This allows a per-device migration where devices are reimplemented in ophyd-async one by one.
127
126
 
128
127
  [Bluesky Run Engine]: http://blueskyproject.io/bluesky
129
128
  [EPICS]: http://www.aps.anl.gov/epics/
@@ -0,0 +1,149 @@
1
+ ophyd_async/__init__.py,sha256=dcAA3qsj1nNIMe5l-v2tlduZ_ypwBmyuHe45Lsq4k4w,206
2
+ ophyd_async/__main__.py,sha256=n_U4O9bgm97OuboUB_9eK7eFiwy8BZSgXJ0OzbE0DqU,481
3
+ ophyd_async/_docs_parser.py,sha256=gPYrigfSbYCF7QoSf2UvE-cpQu4snSssl7ZWN-kKDzI,352
4
+ ophyd_async/_version.py,sha256=vwU_BgU9ApXpWH564vijXNOtjK-ww1iSaNC4uWmoIT4,515
5
+ ophyd_async/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ ophyd_async/core/__init__.py,sha256=eFRVN5WJQKNcZbFtP8abDcra6d_mwFLA0A60AbXL2Vw,4484
7
+ ophyd_async/core/_derived_signal.py,sha256=DS2-t_N8WOGjZjzt-0xRHaWIr3VzKFyV-WiRKRxf7ks,10404
8
+ ophyd_async/core/_derived_signal_backend.py,sha256=5_J9AfRPueJZ-CEgpE7GSG9B1nHUFzanD0N2D1mrGrY,12216
9
+ ophyd_async/core/_detector.py,sha256=J5Chu4sI9WgupB_3qh1c7ZOtlv9tSMJ3tXkHnsc9WIw,14517
10
+ ophyd_async/core/_device.py,sha256=UjpKuGvwCYN0-I0qpdWzBI9uLSLieHryDsLf_9Qeu-Y,14593
11
+ ophyd_async/core/_device_filler.py,sha256=MDz8eQQ-eEAwo-UEMxfqPfpcBuMG01tLCGR6utwVnmE,14825
12
+ ophyd_async/core/_flyer.py,sha256=YPCGAokF0GofOOO2OLrsSLoZSXs_RzmmrNglBunA31o,1924
13
+ ophyd_async/core/_hdf_dataset.py,sha256=eKz5wJQrhpnfnnEG9kliFqlEEdaN4oHy98JXsp-tGNE,2956
14
+ ophyd_async/core/_log.py,sha256=DxKR4Nz3SgTaTzKBZWqt-w48yT8WUAr_3Qr223TEWRw,3587
15
+ ophyd_async/core/_mock_signal_backend.py,sha256=SPdCbVWss6-iL9C3t9u0IvR_Ln9JeDypVd18WlivdjE,3156
16
+ ophyd_async/core/_protocol.py,sha256=wQ_snxhTprHqEjQb1HgFwBljwolMY6A8C3xgV1PXwdU,4051
17
+ ophyd_async/core/_providers.py,sha256=VbpRqV9hjv-GV8ngiy52FUoQGnR0XpQ0ZzQ1SPo0NwU,7765
18
+ ophyd_async/core/_readable.py,sha256=o96tsAxOK81554TQtwJobDn6moDimu5u-k-IXfLttO8,11053
19
+ ophyd_async/core/_settings.py,sha256=_ZccbXKP7j5rG6-bMKk7aaLr8hChdRDAPY_YSR71XXM,4213
20
+ ophyd_async/core/_signal.py,sha256=kqIvQXRP3n34-uhgTmbwm2fTIz_phJYyTT4Rm7P-gSs,26412
21
+ ophyd_async/core/_signal_backend.py,sha256=T8vJi-QuMfjB_uBB6iu_aApAY0j5pAFkDn5g2oSCbmI,6826
22
+ ophyd_async/core/_soft_signal_backend.py,sha256=zrE7H2ojHY6oQBucLkFgukszrkdvbIZuavLjEUqc_xM,6227
23
+ ophyd_async/core/_status.py,sha256=h4TtWFM7wFtpxxyAYYSITgcVzArYZdYBHbya6qIX5t0,6553
24
+ ophyd_async/core/_table.py,sha256=l5GzL3La68ZkXpcOOVntnYr8ofFV8kWGr1hzY1ek83w,6897
25
+ ophyd_async/core/_utils.py,sha256=zEA3lLeOP0N17XGUH8irxvEW8hq0slkxY4gJV3f4YzE,11382
26
+ ophyd_async/core/_yaml_settings.py,sha256=txy4_Igbsr8Yo132yv8jnCcsLpal8klM7DcPNow2KBs,2078
27
+ ophyd_async/epics/__init__.py,sha256=ou4yEaH9VZHz70e8oM614-arLMQvUfQyXhRJsnEpWn8,60
28
+ ophyd_async/epics/motor.py,sha256=6AyLQmgqzabcJ4T2yTJBP1omSxxWeya5RbR_r4zYr10,10458
29
+ ophyd_async/epics/signal.py,sha256=0A-supp9ajr63O6aD7F9oG0-Q26YmRjk-ZGh57-jo1Y,239
30
+ ophyd_async/epics/adandor/__init__.py,sha256=qsBoZdljSaqM-kJSvTf0uq5TNwXAih9lP3yOZpKxOFQ,204
31
+ ophyd_async/epics/adandor/_andor.py,sha256=SxAIP9OLefUqKcxrxhjNzil5D8-59Ps0vADdR6scO44,1281
32
+ ophyd_async/epics/adandor/_andor_controller.py,sha256=BqHNo0CqQR9WoxkTYNy0wP0vHKmkQk7PTvEbigLZG6I,1757
33
+ ophyd_async/epics/adandor/_andor_io.py,sha256=L1HmugU6sHK3F_pT0LaN3U1hKlDkzmSwdqr6-LHieTg,1036
34
+ ophyd_async/epics/adaravis/__init__.py,sha256=ZQaJVQiwcQn9hUZADrYgBE1sDfFEwjhVBJRPth1_LBo,395
35
+ ophyd_async/epics/adaravis/_aravis.py,sha256=Ju2wuebz9_ovl-Kza39s5VQ1pV-Omt_BaIWKqP4kcGA,1315
36
+ ophyd_async/epics/adaravis/_aravis_controller.py,sha256=SP3Zpgv8xpOYKJECIrLisQkQMfvfbswHeW5W_mHHhWU,1906
37
+ ophyd_async/epics/adaravis/_aravis_io.py,sha256=af5RxeXF2ligvAXwMNMKHA4QHTR_WmNFz-f18qD2dbg,855
38
+ ophyd_async/epics/adcore/__init__.py,sha256=GipuBZwaAju4g15WjvGs78S4zjGVxmbPel4E29zHFvE,1583
39
+ ophyd_async/epics/adcore/_core_detector.py,sha256=a7S9RViLXd9XnKFWFOhcMrSbubqZoxdQt09BZr8apUQ,2617
40
+ ophyd_async/epics/adcore/_core_io.py,sha256=-MEsDO736idCrAxvT4BnX-NBWLvZGHTNO22c5H09_J8,7406
41
+ ophyd_async/epics/adcore/_core_logic.py,sha256=OPY-yF2lTHDC_KM5AarAfJnvhmmEA63FxKaIRaCCQ_4,8062
42
+ ophyd_async/epics/adcore/_core_writer.py,sha256=D3qOcW8n3FMSLNACpBdCbQG0hmXE3nweTqZNuxoTYME,8207
43
+ ophyd_async/epics/adcore/_hdf_writer.py,sha256=PTciHPAAqsQULncPBXUJ2tS_I232Ko6Hc6IdLHFfKmU,5519
44
+ ophyd_async/epics/adcore/_jpeg_writer.py,sha256=DFv3YdqKjNq0QCb-bLBlxTaGzmHSvdU_rLB29beI46w,748
45
+ ophyd_async/epics/adcore/_single_trigger.py,sha256=tFGLT1b_rZzAvbqWP-hyCccxJMRY26T5IER-VAqKXmc,1275
46
+ ophyd_async/epics/adcore/_tiff_writer.py,sha256=5WXdW0thL9nv2jSMSqF-bMGQjztQZEnx3enY-nGsLiY,749
47
+ ophyd_async/epics/adcore/_utils.py,sha256=wGWpvm2hi-80N-RxbKOO0-GcMf-vs7B9ZDBxpzGd4mA,3952
48
+ ophyd_async/epics/adkinetix/__init__.py,sha256=A9xq3lGMrmza9lfukRixC0Up_kUDVFII8JguLr2x7Bw,308
49
+ ophyd_async/epics/adkinetix/_kinetix.py,sha256=zZv0JZ8i1RSx7KBDn_1HGNOY0BoIP81mRK5TKq7d4eA,1302
50
+ ophyd_async/epics/adkinetix/_kinetix_controller.py,sha256=cL2nf9ntmXDq3BGku9aIUYdm85DdfB7PYhypGuY1PPg,1480
51
+ ophyd_async/epics/adkinetix/_kinetix_io.py,sha256=5u4TknhcoCSjyp16HQIEp_aOmvfNAKOBoGlMRJoVxuw,770
52
+ ophyd_async/epics/adpilatus/__init__.py,sha256=So7PrLHij7LWOqMbsHUhfqRzKp9iKtrojuWTDS1lID8,406
53
+ ophyd_async/epics/adpilatus/_pilatus.py,sha256=SqNjGpZde_9RVSghjx6h9g2SnoJP-EWU4ew3TMXPayc,1511
54
+ ophyd_async/epics/adpilatus/_pilatus_controller.py,sha256=gzGE3eTpsC-CFcNH_g_xQf3M08DcKO3Q0_LnAzKvpFc,2850
55
+ ophyd_async/epics/adpilatus/_pilatus_io.py,sha256=rzH0ciyzIOJUqDe7qdNwG1RhXyQqbJa-4h_88R1vTKc,827
56
+ ophyd_async/epics/adsimdetector/__init__.py,sha256=EQqxP5DUvZGLxpvSXPagTPy3ROwE-PikyRfcnZfD1KM,281
57
+ ophyd_async/epics/adsimdetector/_sim.py,sha256=r3SuBENGkOU-8X-i3zDyZljFxf0SmsUfryNPFvP1_os,1147
58
+ ophyd_async/epics/adsimdetector/_sim_controller.py,sha256=EmoorPTvRomEwfioA9UcrnhYaUBkvtLI2WY3zBLd4ec,476
59
+ ophyd_async/epics/adsimdetector/_sim_io.py,sha256=TOQcawMtb0ypwUlPcbwGfvp5ZI9jceB9OXm53WBF1_o,233
60
+ ophyd_async/epics/advimba/__init__.py,sha256=Onoe4N1DgjUZ0-00krm2-iJPXnNF8nPGs6I8pY9wB1g,429
61
+ ophyd_async/epics/advimba/_vimba.py,sha256=4XlEnsJMGDzHLuYaIDUmaxx0gtOAehn5BKBZMUAzoHQ,1241
62
+ ophyd_async/epics/advimba/_vimba_controller.py,sha256=vv133Eqgk9AI_P5Yy8ZUlry7w-ip56QZ2bPaWenspHo,1979
63
+ ophyd_async/epics/advimba/_vimba_io.py,sha256=cb2Nfp05fBZAcNVXpz-rqRIRS-TiZW5DPUJOmaFyAw0,1589
64
+ ophyd_async/epics/core/__init__.py,sha256=8NoQxEEc2Ny_L9nrD2fnGSf_2gJr1wCR1LwUeLNcIJo,588
65
+ ophyd_async/epics/core/_aioca.py,sha256=HcGYyYUQZmhdUgovf0M9xxL5Ly56ELJDAoRvyRCPq8U,13003
66
+ ophyd_async/epics/core/_epics_connector.py,sha256=S4z_wbj-aogVcjqCyUgjhcq5Y4gDC7y6wXbsSz2nODY,1918
67
+ ophyd_async/epics/core/_epics_device.py,sha256=wGdR24I7GSPh3HmM7jsWKZhBZgt4IyLrCn4Ut7Wx_xo,510
68
+ ophyd_async/epics/core/_p4p.py,sha256=EqelV3Uc7UO7KJ0Bnj5JoISnGVcrm3Hj3v8aTeVbFCo,16398
69
+ ophyd_async/epics/core/_pvi_connector.py,sha256=GSIcul0g6zMEFo_7f6YJCGhekZOm0bJfay_uASw1Hng,5521
70
+ ophyd_async/epics/core/_signal.py,sha256=2Cp5f5Xb2junnVigypjb3hWu4MuMmbrcHOBgPl5Mhv4,5776
71
+ ophyd_async/epics/core/_util.py,sha256=DcfX4VUTeqLrMhVlt1Q7cvBTuYzHePAA-jdR-OWcxMM,2056
72
+ ophyd_async/epics/demo/__init__.py,sha256=WR2M3D8dbHcisJW2OIU2ManZu5SWez8ytZEp4jSBfDY,416
73
+ ophyd_async/epics/demo/__main__.py,sha256=o6M0FSWduPHe2lN9yNEdsXb48NckSd54-XJGoLe20Pc,1116
74
+ ophyd_async/epics/demo/_ioc.py,sha256=UtwTReKTR-1_tPIhdGBr7OxP_Vqi6xWyCcFABd9BYPY,1040
75
+ ophyd_async/epics/demo/_motor.py,sha256=7A-htbAISgB8ZBipouSoSGmpe1wN00VH7H4To16sE4E,3218
76
+ ophyd_async/epics/demo/_point_detector.py,sha256=5m00mBh5knkChnuZD3JNDPaHIGLN0g0toksYm_hpFKo,1398
77
+ ophyd_async/epics/demo/_point_detector_channel.py,sha256=UkidtyaHR_u00lxLb64F7xYhqJowFQQe6kUXKMPHDqE,721
78
+ ophyd_async/epics/demo/_stage.py,sha256=KPnwr5EX8f_0xxkNWT-70a0AqB0D9DoiTbxMmy0iOTo,485
79
+ ophyd_async/epics/demo/motor.db,sha256=3xb6WTXo4crrvk-M8Y16G9pUidp27vD5vIKKBpLTUlk,1017
80
+ ophyd_async/epics/demo/point_detector.db,sha256=8kBa3XKpmfXCxetT4tq5_RFXa_XqS1Z2ZNzsa2AtLds,1366
81
+ ophyd_async/epics/demo/point_detector_channel.db,sha256=FZ9H6HjqplhcF2jgimv_dT1nn-CBlfjs7Y--iCfHp5Y,632
82
+ ophyd_async/epics/eiger/__init__.py,sha256=b3Tt4pVLk23Giyj50R4e94d2MxWDDmNHWhWwNq2jlaw,221
83
+ ophyd_async/epics/eiger/_eiger.py,sha256=YBEGPHFqAwrA6tvNqn9HlPkN0d7GoXlDcT6vjFhhT5Y,1123
84
+ ophyd_async/epics/eiger/_eiger_controller.py,sha256=p_SdYPfSSQvQ3QXZIr7TLOSpPjC-Ce0C7azVOLfZnwY,2544
85
+ ophyd_async/epics/eiger/_eiger_io.py,sha256=AorI8ybAMYQqJZG8QoE3wioPode7fwzRWptNzD5Ynfo,1873
86
+ ophyd_async/epics/eiger/_odin_io.py,sha256=_KdvMEk-c2jrWYflx2a0k5RLDGal-6SVtlGqG10iQA8,4123
87
+ ophyd_async/epics/testing/__init__.py,sha256=aTIv4D2DYrpnGco5RQF8QuLG1SfFkIlTyM2uYEKXltA,522
88
+ ophyd_async/epics/testing/_example_ioc.py,sha256=lGPubU3aXP-8N-Y-6xW1ksRqoawKExFFe1l8zMZqmjk,3864
89
+ ophyd_async/epics/testing/_utils.py,sha256=6sqJ0BCwubSkK-WOJbmpKNqZKG0AmCoevzaMGaRmuJs,1702
90
+ ophyd_async/epics/testing/test_records.db,sha256=hUD9jIzFmN6DgRDGv4-PkeJxCjRjfjvDq5GoTXMz4Zo,3492
91
+ ophyd_async/epics/testing/test_records_pva.db,sha256=HJAJSvLtPWG5B5dKv8OZ0_hPJxRFrDoYp6ROcF2lqyA,4202
92
+ ophyd_async/fastcs/__init__.py,sha256=qlIM9-pjJ8yWfnzTM9-T9cw7zQLKjeeNROQTni5Dr6M,80
93
+ ophyd_async/fastcs/core.py,sha256=pL_srtTrfuoBHUjDFpxES92owFq9M4Jve0Skk1oeuFA,517
94
+ ophyd_async/fastcs/odin/__init__.py,sha256=da1PTClDMl-IBkrSvq6JC1lnS-K_BASzCvxVhNxN5Ls,13
95
+ ophyd_async/fastcs/panda/__init__.py,sha256=ugrScVm4HPQFc-d1kTAfZ5UUzW9T3SPgTi0OD2s8ZH0,1003
96
+ ophyd_async/fastcs/panda/_block.py,sha256=YzAxdMsE-kzyz5v47TZHRvCbdbYrSvSrfega53MyX9U,2342
97
+ ophyd_async/fastcs/panda/_control.py,sha256=xtW3dH_MLQoycgP-4vJtYx1M9alHjWo13iu9UFTgwzY,1306
98
+ ophyd_async/fastcs/panda/_hdf_panda.py,sha256=eDxEO5L3tlmPsH06fe2AluXjbGclTpPTj0CnMcVQceU,1277
99
+ ophyd_async/fastcs/panda/_table.py,sha256=maKGoKypEuYqTSVWGgDO6GMEKOtlDm9Dn5YiYdBzu6c,2486
100
+ ophyd_async/fastcs/panda/_trigger.py,sha256=dy4kYdVIU4T90a2bhD7cdnfGrqMxZ_n0AZxkFI5txfA,3388
101
+ ophyd_async/fastcs/panda/_writer.py,sha256=Xh3fNA7wr2tFuqCtnMfAbJT00rziiNypHWDnStGolXg,6143
102
+ ophyd_async/plan_stubs/__init__.py,sha256=2ngpkB4wwqlx1dn9JPSHjQdbyWLmY6n-3XVh3RDE8-g,939
103
+ ophyd_async/plan_stubs/_ensure_connected.py,sha256=YR6VRj7koccJ4x35NV-Ugl4ZbxgAoGN9PjVIjhv0gpw,894
104
+ ophyd_async/plan_stubs/_fly.py,sha256=QdodnmBJ0zrUGxcNY7EzLsiPSD8O3Rq9lE9VrWUX5ik,6233
105
+ ophyd_async/plan_stubs/_nd_attributes.py,sha256=kwzyUSeidUH714gaZQtJLxCgDZtmIRyyoKBBRbvqg38,2350
106
+ ophyd_async/plan_stubs/_panda.py,sha256=5_Mf9kGzNjXpf_YscpCUE8tgq284nOHWCG7o_LNFfII,463
107
+ ophyd_async/plan_stubs/_settings.py,sha256=e3dGVSUV-Htay_9fKXyQTAQLdjunetGI3OBYp_oC_FY,5574
108
+ ophyd_async/plan_stubs/_utils.py,sha256=zClRo5ve8RGia7wQnby41W-Zprj-slOA5da1LfYnuhw,45
109
+ ophyd_async/plan_stubs/_wait_for_awaitable.py,sha256=PGct_dGezKrLhm0W_GD83dwevSccG_vsmj0WSlMNVWc,364
110
+ ophyd_async/sim/__init__.py,sha256=PzmOQS7suApaZros4h9ec5K6ehFWEjf3qYMvwFGeKsc,749
111
+ ophyd_async/sim/__main__.py,sha256=mx6natJxnvUBTQXbS4R5OGH_MZVgYiXQkoh3JBJ8NxU,1693
112
+ ophyd_async/sim/_blob_detector.py,sha256=4zWsVdn21TM2bHLA-uZRK98t5c2II68fr3Al37apCmc,1082
113
+ ophyd_async/sim/_blob_detector_controller.py,sha256=DBPX3Ig0tS1kzu7uOkFzSdmRjsRP-epA7iMZsggaxhw,1787
114
+ ophyd_async/sim/_blob_detector_writer.py,sha256=ao6RJ9DM_64HoMOp-vR-BaweKwQstLs3E4_MpRzXXZ4,3623
115
+ ophyd_async/sim/_mirror_horizontal.py,sha256=_AfsHxp5V3rYbK-goI0iwPuDDvx1BrNoUQ4smXzqFbc,1452
116
+ ophyd_async/sim/_mirror_vertical.py,sha256=PyWpyCrW_FCzzGN7Dk0tTB-SKbDIV4GD1fl8AXUJbEI,2029
117
+ ophyd_async/sim/_motor.py,sha256=-YMANsq4ZvI7nZolrYaTYe44kMoIcvPKCpBbCeC7pxw,10167
118
+ ophyd_async/sim/_pattern_generator.py,sha256=QU6Hk3TK0TslrDcITTzcB_UDLVIYQ_a8x4nBGJGx_ig,3652
119
+ ophyd_async/sim/_point_detector.py,sha256=nXgL_1aJZciNBw8Zr2wMYaMbzzAEKXV3yV8FQz2nS_4,2940
120
+ ophyd_async/sim/_stage.py,sha256=qaeyZbUVL1v2pTHJiZxq-y6BKpA1l_DAKyzAQppQx70,772
121
+ ophyd_async/tango/__init__.py,sha256=g9xzjlzPpUAP12YI-kYwfAoLSYPAQdL1S11R2c-cius,60
122
+ ophyd_async/tango/core/__init__.py,sha256=IMvQ7MWcTof99h_pr483KWKvQV2-h7zo_iRpLA2PUYQ,1108
123
+ ophyd_async/tango/core/_base_device.py,sha256=mXQnhCzFAdSrynelubhz7iLx_akINJ6s1M08mikFFME,5032
124
+ ophyd_async/tango/core/_converters.py,sha256=auBUdvbsEU8XXNDzX-fiBap0SvvID3ZOAUEP_wjHgBU,2201
125
+ ophyd_async/tango/core/_signal.py,sha256=XZ38hPnThZ-__RDgwH8UfUk78NLcrZ8zVCH8sklr_3U,5798
126
+ ophyd_async/tango/core/_tango_readable.py,sha256=ctR6YcBGGatW6Jp2kvddA1hVZ2v1CidPsF9FmJK9BYg,406
127
+ ophyd_async/tango/core/_tango_transport.py,sha256=FlvadKRW9H_ggcQ3MTiAGHE4HDTKu_rAk5WODMxwk_E,31903
128
+ ophyd_async/tango/core/_utils.py,sha256=FrX524jwa-0EQxpcGaKF6yqyHm5BWIFSE82FcIB0aAY,1430
129
+ ophyd_async/tango/demo/__init__.py,sha256=_j-UicTnckuIBp8PnieFMOMnLFGivnaKdmo9o0hYtzc,256
130
+ ophyd_async/tango/demo/_counter.py,sha256=2J4SCHnBWLF0O5mFWlJdO4tmnElvlx5sRrk4op_AC9U,1139
131
+ ophyd_async/tango/demo/_detector.py,sha256=X5YWHAjukKZ7iYF1fBNle4CBDj1X5rvj0lnPMOcnRCU,1340
132
+ ophyd_async/tango/demo/_mover.py,sha256=c-IxrWQN0YX-Iuf720xlKfsPbNfh7bUz_AVnbwYkW08,2984
133
+ ophyd_async/tango/demo/_tango/__init__.py,sha256=FfONT7vM49nNo3a1Lv-LcMZO9EHv6bv91yY-RnxIib4,85
134
+ ophyd_async/tango/demo/_tango/_servers.py,sha256=nyuKgufKKqtngDeaufbUcHO6byV5MEElf9442ivtUk0,2992
135
+ ophyd_async/tango/testing/__init__.py,sha256=SYXPAS00ny3jlUMOJKpaewO4ljPjK1_z1smj7IfsBQg,148
136
+ ophyd_async/tango/testing/_one_of_everything.py,sha256=rPAgOoNGvaHMVhB79Gz70NI9tWk3QV5iKg5wAlAtqxU,6571
137
+ ophyd_async/testing/__init__.py,sha256=f53HUj2hpIfrza9OlcOpHmq5wnziQNwixawAK4F1xgc,1698
138
+ ophyd_async/testing/__pytest_assert_rewrite.py,sha256=_SU2UfChPgEf7CFY7aYH2B7MLp-07_qYnVLyu6QtDL8,129
139
+ ophyd_async/testing/_assert.py,sha256=FrMgMfo-ABq_cMT-hJmoaTxhAY4TwAvGe4ae1SF1rME,7657
140
+ ophyd_async/testing/_mock_signal_utils.py,sha256=d-n_923ii59-ae9TbqVuIK9MAJpDmu0k47fzgJLj8t8,5195
141
+ ophyd_async/testing/_one_of_everything.py,sha256=Di0hPoKwrDOSsx50-2UdSHM2EbIKrPG9s0Vp11nE9V8,4773
142
+ ophyd_async/testing/_single_derived.py,sha256=5-HOTzgePcZ354NK_ssVpyIbJoJmKyjVQCxSwQXUC-4,2730
143
+ ophyd_async/testing/_utils.py,sha256=zClRo5ve8RGia7wQnby41W-Zprj-slOA5da1LfYnuhw,45
144
+ ophyd_async/testing/_wait_for_pending.py,sha256=YZAR48n-CW0GsPey3zFRzMJ4byDAr3HvMIoawjmTrHw,732
145
+ ophyd_async-0.10.0a2.dist-info/licenses/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
146
+ ophyd_async-0.10.0a2.dist-info/METADATA,sha256=HhNyZ27Piz8QHIz_DzFZnRD_ZJ5oCRRxfEGY5YF9WlU,7075
147
+ ophyd_async-0.10.0a2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
148
+ ophyd_async-0.10.0a2.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
149
+ ophyd_async-0.10.0a2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5