ophyd-async 0.8.0a6__py3-none-any.whl → 0.9.0__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 (110) hide show
  1. ophyd_async/_version.py +2 -2
  2. ophyd_async/core/__init__.py +15 -46
  3. ophyd_async/core/_detector.py +68 -44
  4. ophyd_async/core/_device.py +120 -79
  5. ophyd_async/core/_device_filler.py +17 -8
  6. ophyd_async/core/_flyer.py +2 -2
  7. ophyd_async/core/_protocol.py +0 -28
  8. ophyd_async/core/_readable.py +30 -23
  9. ophyd_async/core/_settings.py +104 -0
  10. ophyd_async/core/_signal.py +91 -151
  11. ophyd_async/core/_signal_backend.py +4 -1
  12. ophyd_async/core/_soft_signal_backend.py +2 -1
  13. ophyd_async/core/_table.py +18 -10
  14. ophyd_async/core/_utils.py +30 -5
  15. ophyd_async/core/_yaml_settings.py +64 -0
  16. ophyd_async/epics/adandor/__init__.py +9 -0
  17. ophyd_async/epics/adandor/_andor.py +45 -0
  18. ophyd_async/epics/adandor/_andor_controller.py +49 -0
  19. ophyd_async/epics/adandor/_andor_io.py +36 -0
  20. ophyd_async/epics/adaravis/__init__.py +3 -1
  21. ophyd_async/epics/adaravis/_aravis.py +23 -37
  22. ophyd_async/epics/adaravis/_aravis_controller.py +21 -30
  23. ophyd_async/epics/adaravis/_aravis_io.py +4 -4
  24. ophyd_async/epics/adcore/__init__.py +15 -8
  25. ophyd_async/epics/adcore/_core_detector.py +41 -0
  26. ophyd_async/epics/adcore/_core_io.py +56 -31
  27. ophyd_async/epics/adcore/_core_logic.py +99 -86
  28. ophyd_async/epics/adcore/_core_writer.py +219 -0
  29. ophyd_async/epics/adcore/_hdf_writer.py +33 -59
  30. ophyd_async/epics/adcore/_jpeg_writer.py +26 -0
  31. ophyd_async/epics/adcore/_single_trigger.py +5 -4
  32. ophyd_async/epics/adcore/_tiff_writer.py +26 -0
  33. ophyd_async/epics/adcore/_utils.py +37 -36
  34. ophyd_async/epics/adkinetix/_kinetix.py +29 -24
  35. ophyd_async/epics/adkinetix/_kinetix_controller.py +15 -27
  36. ophyd_async/epics/adkinetix/_kinetix_io.py +7 -7
  37. ophyd_async/epics/adpilatus/__init__.py +2 -2
  38. ophyd_async/epics/adpilatus/_pilatus.py +28 -40
  39. ophyd_async/epics/adpilatus/_pilatus_controller.py +47 -25
  40. ophyd_async/epics/adpilatus/_pilatus_io.py +5 -5
  41. ophyd_async/epics/adsimdetector/__init__.py +3 -3
  42. ophyd_async/epics/adsimdetector/_sim.py +33 -17
  43. ophyd_async/epics/advimba/_vimba.py +23 -23
  44. ophyd_async/epics/advimba/_vimba_controller.py +21 -35
  45. ophyd_async/epics/advimba/_vimba_io.py +23 -23
  46. ophyd_async/epics/core/_aioca.py +52 -21
  47. ophyd_async/epics/core/_p4p.py +59 -16
  48. ophyd_async/epics/core/_pvi_connector.py +4 -2
  49. ophyd_async/epics/core/_signal.py +9 -2
  50. ophyd_async/epics/core/_util.py +10 -1
  51. ophyd_async/epics/eiger/_eiger_controller.py +4 -4
  52. ophyd_async/epics/eiger/_eiger_io.py +3 -3
  53. ophyd_async/epics/motor.py +26 -15
  54. ophyd_async/epics/sim/_ioc.py +29 -0
  55. ophyd_async/epics/{demo → sim}/_mover.py +12 -6
  56. ophyd_async/epics/{demo → sim}/_sensor.py +2 -2
  57. ophyd_async/epics/testing/__init__.py +14 -14
  58. ophyd_async/epics/testing/_example_ioc.py +53 -67
  59. ophyd_async/epics/testing/_utils.py +17 -45
  60. ophyd_async/epics/testing/test_records.db +22 -0
  61. ophyd_async/fastcs/core.py +2 -2
  62. ophyd_async/fastcs/panda/__init__.py +0 -2
  63. ophyd_async/fastcs/panda/_block.py +9 -9
  64. ophyd_async/fastcs/panda/_control.py +9 -4
  65. ophyd_async/fastcs/panda/_hdf_panda.py +7 -2
  66. ophyd_async/fastcs/panda/_table.py +4 -1
  67. ophyd_async/fastcs/panda/_trigger.py +7 -7
  68. ophyd_async/plan_stubs/__init__.py +14 -0
  69. ophyd_async/plan_stubs/_ensure_connected.py +11 -17
  70. ophyd_async/plan_stubs/_fly.py +2 -2
  71. ophyd_async/plan_stubs/_nd_attributes.py +7 -5
  72. ophyd_async/plan_stubs/_panda.py +13 -0
  73. ophyd_async/plan_stubs/_settings.py +125 -0
  74. ophyd_async/plan_stubs/_wait_for_awaitable.py +13 -0
  75. ophyd_async/sim/__init__.py +19 -0
  76. ophyd_async/sim/{demo/_pattern_detector → _pattern_detector}/_pattern_detector_controller.py +9 -2
  77. ophyd_async/sim/{demo/_pattern_detector → _pattern_detector}/_pattern_generator.py +13 -6
  78. ophyd_async/sim/{demo/_sim_motor.py → _sim_motor.py} +34 -32
  79. ophyd_async/tango/core/_signal.py +3 -1
  80. ophyd_async/tango/core/_tango_transport.py +13 -15
  81. ophyd_async/tango/{demo → sim}/_mover.py +5 -2
  82. ophyd_async/testing/__init__.py +52 -0
  83. ophyd_async/testing/__pytest_assert_rewrite.py +4 -0
  84. ophyd_async/testing/_assert.py +176 -0
  85. ophyd_async/{core → testing}/_mock_signal_utils.py +15 -11
  86. ophyd_async/testing/_one_of_everything.py +126 -0
  87. ophyd_async/testing/_wait_for_pending.py +22 -0
  88. {ophyd_async-0.8.0a6.dist-info → ophyd_async-0.9.0.dist-info}/METADATA +4 -2
  89. ophyd_async-0.9.0.dist-info/RECORD +129 -0
  90. {ophyd_async-0.8.0a6.dist-info → ophyd_async-0.9.0.dist-info}/WHEEL +1 -1
  91. ophyd_async/core/_device_save_loader.py +0 -274
  92. ophyd_async/epics/adsimdetector/_sim_controller.py +0 -51
  93. ophyd_async/fastcs/panda/_utils.py +0 -16
  94. ophyd_async/sim/demo/__init__.py +0 -19
  95. ophyd_async/sim/testing/__init__.py +0 -0
  96. ophyd_async-0.8.0a6.dist-info/RECORD +0 -116
  97. ophyd_async-0.8.0a6.dist-info/entry_points.txt +0 -2
  98. /ophyd_async/epics/{demo → sim}/__init__.py +0 -0
  99. /ophyd_async/epics/{demo → sim}/mover.db +0 -0
  100. /ophyd_async/epics/{demo → sim}/sensor.db +0 -0
  101. /ophyd_async/sim/{demo/_pattern_detector → _pattern_detector}/__init__.py +0 -0
  102. /ophyd_async/sim/{demo/_pattern_detector → _pattern_detector}/_pattern_detector.py +0 -0
  103. /ophyd_async/sim/{demo/_pattern_detector → _pattern_detector}/_pattern_detector_writer.py +0 -0
  104. /ophyd_async/tango/{demo → sim}/__init__.py +0 -0
  105. /ophyd_async/tango/{demo → sim}/_counter.py +0 -0
  106. /ophyd_async/tango/{demo → sim}/_detector.py +0 -0
  107. /ophyd_async/tango/{demo → sim}/_tango/__init__.py +0 -0
  108. /ophyd_async/tango/{demo → sim}/_tango/_servers.py +0 -0
  109. {ophyd_async-0.8.0a6.dist-info → ophyd_async-0.9.0.dist-info}/LICENSE +0 -0
  110. {ophyd_async-0.8.0a6.dist-info → ophyd_async-0.9.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,176 @@
1
+ import asyncio
2
+ import time
3
+ from contextlib import AbstractContextManager
4
+ from typing import Any
5
+
6
+ import pytest
7
+ from bluesky.protocols import Reading
8
+ from event_model import DataKey
9
+
10
+ from ophyd_async.core import (
11
+ AsyncConfigurable,
12
+ AsyncReadable,
13
+ SignalDatatypeT,
14
+ SignalR,
15
+ Table,
16
+ )
17
+
18
+
19
+ def approx_value(value: Any):
20
+ return ApproxTable(value) if isinstance(value, Table) else pytest.approx(value)
21
+
22
+
23
+ async def assert_value(signal: SignalR[SignalDatatypeT], value: Any) -> None:
24
+ """Assert a signal's value and compare it an expected signal.
25
+
26
+ Parameters
27
+ ----------
28
+ signal:
29
+ signal with get_value.
30
+ value:
31
+ The expected value from the signal.
32
+
33
+ Notes
34
+ -----
35
+ Example usage::
36
+ await assert_value(signal, value)
37
+
38
+ """
39
+ actual_value = await signal.get_value()
40
+ assert approx_value(value) == actual_value
41
+
42
+
43
+ async def assert_reading(
44
+ readable: AsyncReadable, expected_reading: dict[str, Reading]
45
+ ) -> None:
46
+ """Assert readings from readable.
47
+
48
+ Parameters
49
+ ----------
50
+ readable:
51
+ Callable with readable.read function that generate readings.
52
+
53
+ reading:
54
+ The expected readings from the readable.
55
+
56
+ Notes
57
+ -----
58
+ Example usage::
59
+ await assert_reading(readable, reading)
60
+
61
+ """
62
+ actual_reading = await readable.read()
63
+ approx_expected_reading = {
64
+ k: dict(v, value=approx_value(expected_reading[k]["value"]))
65
+ for k, v in expected_reading.items()
66
+ }
67
+ assert actual_reading == approx_expected_reading
68
+
69
+
70
+ async def assert_configuration(
71
+ configurable: AsyncConfigurable,
72
+ configuration: dict[str, Reading],
73
+ ) -> None:
74
+ """Assert readings from Configurable.
75
+
76
+ Parameters
77
+ ----------
78
+ configurable:
79
+ Configurable with Configurable.read function that generate readings.
80
+
81
+ configuration:
82
+ The expected readings from configurable.
83
+
84
+ Notes
85
+ -----
86
+ Example usage::
87
+ await assert_configuration(configurable configuration)
88
+
89
+ """
90
+ actual_configuration = await configurable.read_configuration()
91
+ approx_expected_configuration = {
92
+ k: dict(v, value=approx_value(configuration[k]["value"]))
93
+ for k, v in configuration.items()
94
+ }
95
+ assert actual_configuration == approx_expected_configuration
96
+
97
+
98
+ async def assert_describe_signal(signal: SignalR, /, **metadata):
99
+ actual_describe = await signal.describe()
100
+ assert list(actual_describe) == [signal.name]
101
+ (actual_datakey,) = actual_describe.values()
102
+ expected_datakey = DataKey(source=signal.source, **metadata)
103
+ assert actual_datakey == expected_datakey
104
+
105
+
106
+ def assert_emitted(docs: dict[str, list[dict]], **numbers: int):
107
+ """Assert emitted document generated by running a Bluesky plan
108
+
109
+ Parameters
110
+ ----------
111
+ Doc:
112
+ A dictionary
113
+
114
+ numbers:
115
+ expected emission in kwarg from
116
+
117
+ Notes
118
+ -----
119
+ Example usage::
120
+ docs = defaultdict(list)
121
+ RE.subscribe(lambda name, doc: docs[name].append(doc))
122
+ RE(my_plan())
123
+ assert_emitted(docs, start=1, descriptor=1, event=1, stop=1)
124
+ """
125
+ assert list(docs) == list(numbers)
126
+ actual_numbers = {name: len(d) for name, d in docs.items()}
127
+ assert actual_numbers == numbers
128
+
129
+
130
+ class ApproxTable:
131
+ def __init__(self, expected: Table, rel=None, abs=None, nan_ok: bool = False):
132
+ self.expected = expected
133
+ self.rel = rel
134
+ self.abs = abs
135
+ self.nan_ok = nan_ok
136
+
137
+ def __eq__(self, value):
138
+ approx_fields = {
139
+ k: pytest.approx(v, self.rel, self.abs, self.nan_ok)
140
+ for k, v in self.expected
141
+ }
142
+ expected = type(self.expected).model_construct(**approx_fields) # type: ignore
143
+ return expected == value
144
+
145
+
146
+ class MonitorQueue(AbstractContextManager):
147
+ def __init__(self, signal: SignalR):
148
+ self.signal = signal
149
+ self.updates: asyncio.Queue[dict[str, Reading]] = asyncio.Queue()
150
+ self.signal.subscribe(self.updates.put_nowait)
151
+
152
+ async def assert_updates(self, expected_value):
153
+ # Get an update, value and reading
154
+ expected_type = type(expected_value)
155
+ expected_value = approx_value(expected_value)
156
+ update = await self.updates.get()
157
+ value = await self.signal.get_value()
158
+ reading = await self.signal.read()
159
+ # Check they match what we expected
160
+ assert value == expected_value
161
+ assert type(value) is expected_type
162
+ expected_reading = {
163
+ self.signal.name: {
164
+ "value": expected_value,
165
+ "timestamp": pytest.approx(time.time(), rel=0.1),
166
+ "alarm_severity": 0,
167
+ }
168
+ }
169
+ assert reading == update == expected_reading
170
+
171
+ def __enter__(self):
172
+ self.signal.subscribe(self.updates.put_nowait)
173
+ return self
174
+
175
+ def __exit__(self, exc_type, exc_value, traceback):
176
+ self.signal.clear_sub(self.updates.put_nowait)
@@ -1,12 +1,16 @@
1
1
  from collections.abc import Awaitable, Callable, Iterable
2
- from contextlib import asynccontextmanager, contextmanager
2
+ from contextlib import contextmanager
3
3
  from unittest.mock import AsyncMock, Mock
4
4
 
5
- from ._device import Device
6
- from ._mock_signal_backend import MockSignalBackend
7
- from ._signal import Signal, SignalConnector, SignalR
8
- from ._soft_signal_backend import SignalDatatypeT
9
- from ._utils import LazyMock
5
+ from ophyd_async.core import (
6
+ Device,
7
+ LazyMock,
8
+ MockSignalBackend,
9
+ Signal,
10
+ SignalConnector,
11
+ SignalDatatypeT,
12
+ SignalR,
13
+ )
10
14
 
11
15
 
12
16
  def get_mock(device: Device | Signal) -> Mock:
@@ -18,9 +22,9 @@ def get_mock(device: Device | Signal) -> Mock:
18
22
  def _get_mock_signal_backend(signal: Signal) -> MockSignalBackend:
19
23
  connector = signal._connector # noqa: SLF001
20
24
  assert isinstance(connector, SignalConnector), f"Expected Signal, got {signal}"
21
- assert isinstance(
22
- connector.backend, MockSignalBackend
23
- ), f"Signal {signal} not connected in mock mode"
25
+ assert isinstance(connector.backend, MockSignalBackend), (
26
+ f"Signal {signal} not connected in mock mode"
27
+ )
24
28
  return connector.backend
25
29
 
26
30
 
@@ -40,8 +44,8 @@ def set_mock_put_proceeds(signal: Signal, proceeds: bool):
40
44
  backend.put_proceeds.clear()
41
45
 
42
46
 
43
- @asynccontextmanager
44
- async def mock_puts_blocked(*signals: Signal):
47
+ @contextmanager
48
+ def mock_puts_blocked(*signals: Signal):
45
49
  for signal in signals:
46
50
  set_mock_put_proceeds(signal, False)
47
51
  yield
@@ -0,0 +1,126 @@
1
+ from collections.abc import Sequence
2
+ from typing import Any
3
+
4
+ import numpy as np
5
+
6
+ from ophyd_async.core import (
7
+ Array1D,
8
+ Device,
9
+ DTypeScalar_co,
10
+ SignalRW,
11
+ StandardReadable,
12
+ StrictEnum,
13
+ Table,
14
+ soft_signal_r_and_setter,
15
+ soft_signal_rw,
16
+ )
17
+ from ophyd_async.core import StandardReadableFormat as Format
18
+ from ophyd_async.core._device import DeviceVector
19
+
20
+
21
+ class ExampleEnum(StrictEnum):
22
+ A = "Aaa"
23
+ B = "Bbb"
24
+ C = "Ccc"
25
+
26
+
27
+ 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]
33
+
34
+
35
+ def int_array_signal(
36
+ dtype: type[DTypeScalar_co], name: str = ""
37
+ ) -> 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)
40
+ return soft_signal_rw(Array1D[dtype], value, name)
41
+
42
+
43
+ def float_array_signal(
44
+ dtype: type[DTypeScalar_co], name: str = ""
45
+ ) -> SignalRW[Array1D[DTypeScalar_co]]:
46
+ finfo = np.finfo(dtype) # type: ignore
47
+ value = np.array(
48
+ [
49
+ finfo.min,
50
+ finfo.max,
51
+ finfo.smallest_normal,
52
+ finfo.smallest_subnormal,
53
+ 0,
54
+ 1.234,
55
+ 2.34e5,
56
+ 3.45e-6,
57
+ ],
58
+ dtype=dtype,
59
+ )
60
+ return soft_signal_rw(Array1D[dtype], value, name)
61
+
62
+
63
+ class OneOfEverythingDevice(StandardReadable):
64
+ # make a detector to test assert_configuration
65
+ def __init__(self, name=""):
66
+ # add all signals to configuration
67
+ 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)
73
+ self.int8a = int_array_signal(np.int8)
74
+ self.uint8a = int_array_signal(np.uint8)
75
+ self.int16a = int_array_signal(np.int16)
76
+ self.uint16a = int_array_signal(np.uint16)
77
+ self.int32a = int_array_signal(np.int32)
78
+ self.uint32a = int_array_signal(np.uint32)
79
+ self.int64a = int_array_signal(np.int64)
80
+ self.uint64a = int_array_signal(np.uint64)
81
+ self.float32a = float_array_signal(np.float32)
82
+ self.float64a = float_array_signal(np.float64)
83
+ self.stra = soft_signal_rw(
84
+ Sequence[str],
85
+ ["one", "two", "three"],
86
+ )
87
+ self.enuma = soft_signal_rw(
88
+ Sequence[ExampleEnum],
89
+ [ExampleEnum.A, ExampleEnum.C],
90
+ )
91
+ self.table = soft_signal_rw(
92
+ ExampleTable,
93
+ 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],
99
+ ),
100
+ )
101
+ self.ndarray = soft_signal_rw(np.ndarray, np.array(([1, 2, 3], [4, 5, 6])))
102
+ super().__init__(name)
103
+
104
+
105
+ async def _get_signal_values(child: Device) -> dict[SignalRW, Any]:
106
+ if isinstance(child, SignalRW):
107
+ return {child: await child.get_value()}
108
+ ret = {}
109
+ for _, c in child.children():
110
+ ret.update(await _get_signal_values(c))
111
+ return ret
112
+
113
+
114
+ class ParentOfEverythingDevice(Device):
115
+ def __init__(self, name=""):
116
+ self.child = OneOfEverythingDevice()
117
+ self.vector = DeviceVector(
118
+ {1: OneOfEverythingDevice(), 3: OneOfEverythingDevice()}
119
+ )
120
+ self.sig_rw = soft_signal_rw(str, "Top level SignalRW")
121
+ self.sig_r, _ = soft_signal_r_and_setter(str, "Top level SignalR")
122
+ self._sig_rw = soft_signal_rw(str, "Top level private SignalRW")
123
+ super().__init__(name=name)
124
+
125
+ async def get_signal_values(self):
126
+ return await _get_signal_values(self)
@@ -0,0 +1,22 @@
1
+ import asyncio
2
+
3
+
4
+ async def wait_for_pending_wakeups(max_yields=20, raise_if_exceeded=True):
5
+ """Allow any ready asyncio tasks to be woken up.
6
+
7
+ Used in:
8
+
9
+ - Tests to allow tasks like ``set()`` to start so that signal
10
+ puts can be tested
11
+ - `observe_value` to allow it to be wrapped in `asyncio.wait_for`
12
+ with a timeout
13
+ """
14
+ loop = asyncio.get_event_loop()
15
+ # If anything has called loop.call_soon or is scheduled a wakeup
16
+ # then let it run
17
+ for _ in range(max_yields):
18
+ await asyncio.sleep(0)
19
+ if not loop._ready: # type: ignore # noqa: SLF001
20
+ return
21
+ if raise_if_exceeded:
22
+ raise RuntimeError(f"Tasks still scheduling wakeups after {max_yields} yields")
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: ophyd-async
3
- Version: 0.8.0a6
3
+ Version: 0.9.0
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
@@ -37,6 +37,7 @@ Classifier: Development Status :: 3 - Alpha
37
37
  Classifier: License :: OSI Approved :: BSD License
38
38
  Classifier: Programming Language :: Python :: 3.10
39
39
  Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
40
41
  Requires-Python: >=3.10
41
42
  Description-Content-Type: text/markdown
42
43
  License-File: LICENSE
@@ -67,6 +68,7 @@ Requires-Dist: ophyd_async[tango]; extra == "dev"
67
68
  Requires-Dist: inflection; extra == "dev"
68
69
  Requires-Dist: ipython; extra == "dev"
69
70
  Requires-Dist: ipywidgets; extra == "dev"
71
+ Requires-Dist: import-linter; extra == "dev"
70
72
  Requires-Dist: matplotlib; extra == "dev"
71
73
  Requires-Dist: myst-parser; extra == "dev"
72
74
  Requires-Dist: numpydoc; extra == "dev"
@@ -0,0 +1,129 @@
1
+ ophyd_async/__init__.py,sha256=tEfgj45lRItQ-_u8SRFPM-mpBh3gWvHXr3emhiJJG_M,225
2
+ ophyd_async/__main__.py,sha256=n_U4O9bgm97OuboUB_9eK7eFiwy8BZSgXJ0OzbE0DqU,481
3
+ ophyd_async/_version.py,sha256=dEuABWaRk7ju3R5JrWbpUVQ4xq7RBpvl2clGJceWAS4,411
4
+ ophyd_async/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ ophyd_async/core/__init__.py,sha256=jNna-9AJLt9ZLpkjnNpE1im8Kv_IT5t4ftjsRMrVcgI,3739
6
+ ophyd_async/core/_detector.py,sha256=ZpoBmTmPqrOQZ8Y8zyMmsHz78VJVeAcZU7AHrdQf8lM,15241
7
+ ophyd_async/core/_device.py,sha256=OZlz4xeVvqM3l85OBXYpcv47TTe6HiahDLu4LNKaw9o,13731
8
+ ophyd_async/core/_device_filler.py,sha256=8pxE-TjWM4fyidE_GAZNw9tEaZKYV-sFTBuQUzJ_sfk,11796
9
+ ophyd_async/core/_flyer.py,sha256=PmVikIGaw_HcU9_M6rfQOclgNt7GQ7qNaZX_AoI9WFg,1713
10
+ ophyd_async/core/_hdf_dataset.py,sha256=wW_OL8OYLGOsE01ny3hGaapOrxK7BzhWTxKgz8CIXK0,2492
11
+ ophyd_async/core/_log.py,sha256=UbL9AtnHVUg7r9LofzgmuKEtBESy03usCp7ejmDltG4,3679
12
+ ophyd_async/core/_mock_signal_backend.py,sha256=8Upnz6QrSigeDXemjZ-jB4sV2yIPUzid-6GOfTZ-7Io,2805
13
+ ophyd_async/core/_protocol.py,sha256=0pwF_EUu7LZjr-Hg6LKy6B1-5y4gpsU81JsPiNI5g_s,3317
14
+ ophyd_async/core/_providers.py,sha256=ff9ZT5-PZ6rhTTdE-q8w9l_k9DuZqLWLebsKZLeJ0Ds,7112
15
+ ophyd_async/core/_readable.py,sha256=DNst8B6Yai2A4TLjn3TMUzhBz6cS7MqT6-hPZG1IXns,10938
16
+ ophyd_async/core/_settings.py,sha256=RGr9MqiF9ifKBBVIAXPLvkHzrJ5qGqFW5Hr_GL1WzdY,3707
17
+ ophyd_async/core/_signal.py,sha256=uPv4kKD_SOggRTdHNrQusGU2nJdWTJenRuLsPdEgE-4,21856
18
+ ophyd_async/core/_signal_backend.py,sha256=LweJnF3n5cucpBX8XV20Pbh0k5pBnXhMg3GQeTwK9Ns,5252
19
+ ophyd_async/core/_soft_signal_backend.py,sha256=IJp2Teu8WGRG9To6PBmkp_sVOlxh_vfLbJYkKop9zZg,5959
20
+ ophyd_async/core/_status.py,sha256=OUKhblRQ4KU5PDsWbpvYduM7G60JMk1NqeV4eqyPtKc,5131
21
+ ophyd_async/core/_table.py,sha256=BSlLrgYA2rAeJl5J1bdZvGDB-YFqXUIUMiAtCWcy0xw,5897
22
+ ophyd_async/core/_utils.py,sha256=kPi8YO8_OHkCMnfn27qDCu1JrKuOXPcU5YcBC7WCXdg,10526
23
+ ophyd_async/core/_yaml_settings.py,sha256=nfnebGXrnLKJgzd5D9In3ZPi2hATsgrehjrR0XRHTsk,2022
24
+ ophyd_async/epics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ ophyd_async/epics/motor.py,sha256=Sz3bxIKxxlCd8r-25eZgF81QvoetKPY0At8d4h0yi7Q,9352
26
+ ophyd_async/epics/signal.py,sha256=hJCGIIWjRVhjEHkeL1I_oPEaaN7dDFKmm7G7ZmgoTYQ,219
27
+ ophyd_async/epics/adandor/__init__.py,sha256=qsBoZdljSaqM-kJSvTf0uq5TNwXAih9lP3yOZpKxOFQ,204
28
+ ophyd_async/epics/adandor/_andor.py,sha256=lrTyYTBjs_4f4K_Te0Wwt9je2OMofShpeZt52xtM2ho,1285
29
+ ophyd_async/epics/adandor/_andor_controller.py,sha256=MYnpi1-yGIW1SG9oOEL08o8dbr2PiZilHcGgEVYHfzM,1712
30
+ ophyd_async/epics/adandor/_andor_io.py,sha256=taRJXTISVG_yzFxKr78Cfxv-wOdGxp-pjP15xM2Pu04,1029
31
+ ophyd_async/epics/adaravis/__init__.py,sha256=B7xOTKud0TIZRQ-gI_BpX1piRW2jCdAspMqAgBUXKVc,299
32
+ ophyd_async/epics/adaravis/_aravis.py,sha256=WUCS5JMe-eSBSmw_LyLtz3x8FYgKkipJ0pVjRF5OF5w,1449
33
+ ophyd_async/epics/adaravis/_aravis_controller.py,sha256=8yMnZtvcfEIoq6iv4jrdPxuLPyjHbijIzjoYri0qj6o,2579
34
+ ophyd_async/epics/adaravis/_aravis_io.py,sha256=_RViDrTDaTutitRbHlJ5VV23X70lvfhyY3DTzgXy6yI,1603
35
+ ophyd_async/epics/adcore/__init__.py,sha256=bB7V1pdNpFH1pkCsym6jYtHchvqMYXWisbRrcmHH7Ks,1217
36
+ ophyd_async/epics/adcore/_core_detector.py,sha256=-c5FDeMTJWniogtiyA9-8Yu67e7UgZjC7QBj8iwbU5U,1258
37
+ ophyd_async/epics/adcore/_core_io.py,sha256=VNlpOL7cN8hExk_cIeushgDrUwDz33gm0K4iSpNB15w,6956
38
+ ophyd_async/epics/adcore/_core_logic.py,sha256=wevdDKYcoXiwAxchb__KjAPNtJe2g8Z6k9OzzGzP9p8,4356
39
+ ophyd_async/epics/adcore/_core_writer.py,sha256=JuEe4INxHW5SC37orhh8Q0sbI3RUdX1kaa0f2536Gr4,8010
40
+ ophyd_async/epics/adcore/_hdf_writer.py,sha256=tLu7MKXO7TOBLECdlV-O4IWj6w6fvzZoR6419E7iJVc,5815
41
+ ophyd_async/epics/adcore/_jpeg_writer.py,sha256=DFv3YdqKjNq0QCb-bLBlxTaGzmHSvdU_rLB29beI46w,748
42
+ ophyd_async/epics/adcore/_single_trigger.py,sha256=OGgZCQnicHr6IZ69nHCwzlA4YLUo3O-Zkgl6fQTZ0eg,1271
43
+ ophyd_async/epics/adcore/_tiff_writer.py,sha256=5WXdW0thL9nv2jSMSqF-bMGQjztQZEnx3enY-nGsLiY,749
44
+ ophyd_async/epics/adcore/_utils.py,sha256=EDHbtldcae701sovFmhBPr_uKo7Hh34-AHq2sk7aL_U,3948
45
+ ophyd_async/epics/adkinetix/__init__.py,sha256=cvnwOqbvEENf70eFp6bPGwayP0u14UTIhs3WiZEcF_Q,262
46
+ ophyd_async/epics/adkinetix/_kinetix.py,sha256=uTbkeDyveCayrtrLNw2ENmCZ7XQ8wwLLeUSdu76AmSE,1305
47
+ ophyd_async/epics/adkinetix/_kinetix_controller.py,sha256=PjZ6fWvzGdh0zBa8re55vmHElI-d3LTjKldYpCkMYyY,1438
48
+ ophyd_async/epics/adkinetix/_kinetix_io.py,sha256=3zqfmoTCTkhd7kiqD4wiYrnu5EADzzegaCRJFBaZuVk,910
49
+ ophyd_async/epics/adpilatus/__init__.py,sha256=UKpd8qRRbFFhCo8fgUwPHqIobNVA-i_3fyvZoac_Ms0,308
50
+ ophyd_async/epics/adpilatus/_pilatus.py,sha256=0iA9Yrm-qJ73CC0W_y8F7tpVaaJL-1KHVlU-4kU59a8,1510
51
+ ophyd_async/epics/adpilatus/_pilatus_controller.py,sha256=Udq3Z8Gom4HgKUFXBMvWFTFoc4JLyp89YfvlA9N9q-8,3701
52
+ ophyd_async/epics/adpilatus/_pilatus_io.py,sha256=Jznmhwidmr_YaUdWXazWFYNQq4wn_sI1dXeo9Zhyf0M,738
53
+ ophyd_async/epics/adsimdetector/__init__.py,sha256=2TLBnXxEb1Ik1rFA3voROgbmnPPn_6q_8xLxwykdZPs,132
54
+ ophyd_async/epics/adsimdetector/_sim.py,sha256=-aPpU7xlT4ykgHzpFVN_LKgBbU6ptAdaMX1TCJd__h0,1425
55
+ ophyd_async/epics/advimba/__init__.py,sha256=l0ElP3Zyff_pzrTRdj9oUO9xigCfmzo3pMVjstlVsJY,320
56
+ ophyd_async/epics/advimba/_vimba.py,sha256=1ccSakYY4J-5dSw8Ttzvf4HzRk0hSrpOjAgkMfHGHOU,1201
57
+ ophyd_async/epics/advimba/_vimba_controller.py,sha256=NW_QNxTTWjiGmZNZY_nNcdZlOCfgOhZ3U0GcQzAZw8g,1937
58
+ ophyd_async/epics/advimba/_vimba_io.py,sha256=il-SZSiApx5OUQCYHUGoa0Ywu9pY01DSDvOttU15khQ,1864
59
+ ophyd_async/epics/core/__init__.py,sha256=8NoQxEEc2Ny_L9nrD2fnGSf_2gJr1wCR1LwUeLNcIJo,588
60
+ ophyd_async/epics/core/_aioca.py,sha256=uVLIyUFiL5abAM__eNYtik3SafQ7YJ9zQvuS43cg__4,12727
61
+ ophyd_async/epics/core/_epics_connector.py,sha256=n1FlQYui8HdobPxaX3VAflrzi2UT7QCe3cFasssmVLw,1789
62
+ ophyd_async/epics/core/_epics_device.py,sha256=kshNiKQhevsL2OZXa-r093L_sQGvGK_0J4PWVLg3Eqw,437
63
+ ophyd_async/epics/core/_p4p.py,sha256=axxV8iKpFJl9fNEW54IkXz32ki6_IOcilwnxQFnb0Vo,16169
64
+ ophyd_async/epics/core/_pvi_connector.py,sha256=wi9PiiWtWWE8mlHAfgDd6zKHvXn35E5DaqDvk4k5KD0,3755
65
+ ophyd_async/epics/core/_signal.py,sha256=0_g2dd60tUl1inEY9hUQvWrEka4uvNW8hylrhnB76Q8,4842
66
+ ophyd_async/epics/core/_util.py,sha256=kSTjrVZQA1mb2RbTaiVgBKleDMJtRdC2vRcQMgHwoRg,2062
67
+ ophyd_async/epics/eiger/__init__.py,sha256=b3Tt4pVLk23Giyj50R4e94d2MxWDDmNHWhWwNq2jlaw,221
68
+ ophyd_async/epics/eiger/_eiger.py,sha256=hkMsjVwrzDcE1u5BRIQtn8RSR2e0b1JMpDvuIONoNaI,1133
69
+ ophyd_async/epics/eiger/_eiger_controller.py,sha256=ZJGTwSjQam15mtgG4GQ9nPNv_cA-lSLMFgTMkTK79Gg,2343
70
+ ophyd_async/epics/eiger/_eiger_io.py,sha256=qTBT0SebqzlcNXtLQywSoTmAbVC2wl4i0Wn2fbcEISM,1806
71
+ ophyd_async/epics/eiger/_odin_io.py,sha256=3E33ysvMlf8t0bbSVPnzUrvPgUwA7491uoViWpivpf8,4153
72
+ ophyd_async/epics/sim/__init__.py,sha256=wCrgemEo-zR4TTvaqCKnQ-AIUHorotV5jhftbq1tXz0,1368
73
+ ophyd_async/epics/sim/_ioc.py,sha256=izVXHEpsk2bRF67EdUoghsGL-PxGuKtSuaJJSS-ySpo,926
74
+ ophyd_async/epics/sim/_mover.py,sha256=LEemFN_S07c9aeTSschA5k3fFXLXBOOIbpOJn9HRiQY,3831
75
+ ophyd_async/epics/sim/_sensor.py,sha256=VMxsjLV_V3LeLqnSqIsDHVJgpu5SmASV-rlzok_lLws,1040
76
+ ophyd_async/epics/sim/mover.db,sha256=RFz0rxZue689Wh1sWTZwWeFMUrH04ttPq2u5xJH_Fp4,998
77
+ ophyd_async/epics/sim/sensor.db,sha256=AstyG9E0R4KZBz2FZQSrV_QlrfLoU6M2cvYc15Lf548,553
78
+ ophyd_async/epics/testing/__init__.py,sha256=aTIv4D2DYrpnGco5RQF8QuLG1SfFkIlTyM2uYEKXltA,522
79
+ ophyd_async/epics/testing/_example_ioc.py,sha256=dv286YeoePB-AuhW6LjTIfghQUz7SHH3ZQ9gVgJOspQ,3576
80
+ ophyd_async/epics/testing/_utils.py,sha256=Y5aokH545rJfu-0JDZCha91Y8p08KYiIfxDc2wnq9CQ,1599
81
+ ophyd_async/epics/testing/test_records.db,sha256=hUD9jIzFmN6DgRDGv4-PkeJxCjRjfjvDq5GoTXMz4Zo,3492
82
+ ophyd_async/epics/testing/test_records_pva.db,sha256=NyceNGaCZXNYaXjH2VLhvKl8Z-L6dwfE_kYZKqdIcTU,4054
83
+ ophyd_async/fastcs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
+ ophyd_async/fastcs/core.py,sha256=MpbRLaPJwmaAuunnIV34oq1AUjT1nfv5ggtgw4I42vY,376
85
+ ophyd_async/fastcs/odin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
+ ophyd_async/fastcs/panda/__init__.py,sha256=YwmF5yjfa7TxfIqjNfajIHYbxcfdfpR04eFcDCM8RmA,927
87
+ ophyd_async/fastcs/panda/_block.py,sha256=UZBWos3g4yhxGhX9oB3g_GU7jGGelgoQ2Yt2sm1MPJM,1709
88
+ ophyd_async/fastcs/panda/_control.py,sha256=b2BWhjKDHgUV1ggalvwBEbAELWsrDWK3EsMozog_a6w,1124
89
+ ophyd_async/fastcs/panda/_hdf_panda.py,sha256=7uGEFw5Jvjk4IxzSQx9LBSOfqtG_7HCcRuzxLvxclKI,1215
90
+ ophyd_async/fastcs/panda/_table.py,sha256=Ct4Ur4F_kEvBeUURrGKVpSxp_pnyRK-xv6uqzrJ39Ho,2368
91
+ ophyd_async/fastcs/panda/_trigger.py,sha256=z9VGb4XPaw3xrOsvTbgpLHbduDbQJB0M4HP3w5YPB_E,3056
92
+ ophyd_async/fastcs/panda/_writer.py,sha256=wDN6uWX1ENofmI3JBXJ7_CGooI7WsZP-JJQrRiSc6sM,6000
93
+ ophyd_async/plan_stubs/__init__.py,sha256=qW9xqnzKyR7W1-oQH34sLPV9aEAesIS5of9oq3IWGdk,874
94
+ ophyd_async/plan_stubs/_ensure_connected.py,sha256=yUFDqmTauoI-1A4QT0be8m1Ta-A-jyadOd0jZn2FVq0,820
95
+ ophyd_async/plan_stubs/_fly.py,sha256=sJf-JQk57-WSwU-iH8Ab-l3kB2j-vDGslRJej2OBwkw,6225
96
+ ophyd_async/plan_stubs/_nd_attributes.py,sha256=RBooW9E-UgqwKqe3INmfdZH9dGy-PyWKSLfEWJINv5I,2260
97
+ ophyd_async/plan_stubs/_panda.py,sha256=2DoJK26K68MOFPN2bqdbhKE6XNCTnXOvEJoOeAhfKfU,413
98
+ ophyd_async/plan_stubs/_settings.py,sha256=edAgaGqPaBxfHkplakWqB0_OFt-yUNxK910LMoJ9JWU,4397
99
+ ophyd_async/plan_stubs/_wait_for_awaitable.py,sha256=QttArcYwi9TPF8r0r_5VoHdsNexV8O-1a4up0jU9Jkg,373
100
+ ophyd_async/sim/__init__.py,sha256=JKWFnHqmFuRRMvvU0aBuclke3OdF0iq89yvHEd4J7Bg,371
101
+ ophyd_async/sim/_sim_motor.py,sha256=gfvhW9TSgolAf5iAk30GviuHh680pT_RcxxTviZCzvk,3997
102
+ ophyd_async/sim/_pattern_detector/__init__.py,sha256=o_dSZDIl_CyS3YPSNKpGiQiR9UaC4cNzZ8_ByEN9dIk,402
103
+ ophyd_async/sim/_pattern_detector/_pattern_detector.py,sha256=R-UbcxHLFfCK9tBryKZN5Dit0IjYeJGP-QKV2ssKFoQ,1275
104
+ ophyd_async/sim/_pattern_detector/_pattern_detector_controller.py,sha256=BLBFMri5IQiQfddpoYFelgj_FEZ2AMcTiz8MHKaUEaU,2341
105
+ ophyd_async/sim/_pattern_detector/_pattern_detector_writer.py,sha256=nQOks4EK1Ax0Ib1pkCrmJPF8Jqr7tPusMnby-HGUnP0,1370
106
+ ophyd_async/sim/_pattern_detector/_pattern_generator.py,sha256=gYBjE0tl_4oTb1qn5dGMS7nLS_a3vY6e5Z-OvpPbFXY,7330
107
+ ophyd_async/tango/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
+ ophyd_async/tango/core/__init__.py,sha256=pBslTNkIt22-g-CDbG9N7pKLQVJqFe6DYXHFFYJZIo8,905
109
+ ophyd_async/tango/core/_base_device.py,sha256=IN1HF1DOf9W9_FhVlzWyuU58gBFu86rYOD1vDZ_a7Wc,4717
110
+ ophyd_async/tango/core/_signal.py,sha256=Shuyjt31dnTGzkzGa0CthisSwnLJ0pNI9ABEx5GuFus,6463
111
+ ophyd_async/tango/core/_tango_readable.py,sha256=c6xVH56oBp5o3C3y3PuHA5MftvmjKm20BBvrgsTO260,913
112
+ ophyd_async/tango/core/_tango_transport.py,sha256=5m_4TPya3Mn4WviLA9fUh2zd_PTxEzkPguFRKgOluhs,28922
113
+ ophyd_async/tango/sim/__init__.py,sha256=_j-UicTnckuIBp8PnieFMOMnLFGivnaKdmo9o0hYtzc,256
114
+ ophyd_async/tango/sim/_counter.py,sha256=efBqrFj6ejzDh1aggtPXpn1iub1zB4XocRvHqBEiwcs,1105
115
+ ophyd_async/tango/sim/_detector.py,sha256=0wwk7Y-Dl9QF1YsCIU_BxqI6-PQ40qN_0gknrYBkxsY,1292
116
+ ophyd_async/tango/sim/_mover.py,sha256=8MCorX6e5AaIXP00kwLOwu2smE4Y5RhbeMA_4mGbcFQ,2957
117
+ ophyd_async/tango/sim/_tango/__init__.py,sha256=FfONT7vM49nNo3a1Lv-LcMZO9EHv6bv91yY-RnxIib4,85
118
+ ophyd_async/tango/sim/_tango/_servers.py,sha256=MwkkoZWJQm_cgafCBBXeQfwyAiOgU8cE90_uNfcdcGA,2916
119
+ ophyd_async/testing/__init__.py,sha256=UqU_3GH0th3s4jwgDRqxJn8mqq9My8jzk55Q-69OeeQ,1156
120
+ ophyd_async/testing/__pytest_assert_rewrite.py,sha256=_SU2UfChPgEf7CFY7aYH2B7MLp-07_qYnVLyu6QtDL8,129
121
+ ophyd_async/testing/_assert.py,sha256=FvGhGVoYPul2-2ByM5U0AAdrIKc1y6gqLRK_CfYut-Y,4941
122
+ ophyd_async/testing/_mock_signal_utils.py,sha256=PABE_2Hexx5mtINuaVLASHKJEYulO-nUqiI20vE9j6s,5212
123
+ ophyd_async/testing/_one_of_everything.py,sha256=pzj4-yM3buOKQJyUNfpMCKlg57cdALFY6hr0NDHQYZU,4160
124
+ ophyd_async/testing/_wait_for_pending.py,sha256=YZAR48n-CW0GsPey3zFRzMJ4byDAr3HvMIoawjmTrHw,732
125
+ ophyd_async-0.9.0.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
126
+ ophyd_async-0.9.0.dist-info/METADATA,sha256=Lnnb3TO75N-BVFdg4txFdhU8CelKsZPOWA0Su1o4Ty0,6751
127
+ ophyd_async-0.9.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
128
+ ophyd_async-0.9.0.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
129
+ ophyd_async-0.9.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5