ophyd-async 0.11__py3-none-any.whl → 0.12.1__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.
- ophyd_async/_version.py +2 -2
- ophyd_async/core/_flyer.py +4 -4
- ophyd_async/core/_hdf_dataset.py +2 -15
- ophyd_async/core/_providers.py +69 -11
- ophyd_async/core/_signal.py +15 -2
- ophyd_async/core/_soft_signal_backend.py +1 -1
- ophyd_async/epics/adcore/__init__.py +2 -0
- ophyd_async/epics/adcore/_core_io.py +15 -5
- ophyd_async/epics/adcore/_core_writer.py +34 -26
- ophyd_async/epics/adcore/_hdf_writer.py +4 -3
- ophyd_async/epics/adcore/_jpeg_writer.py +3 -3
- ophyd_async/epics/adcore/_tiff_writer.py +3 -3
- ophyd_async/epics/core/_aioca.py +3 -0
- ophyd_async/epics/core/_signal.py +8 -3
- ophyd_async/epics/motor.py +2 -2
- ophyd_async/epics/testing/_utils.py +1 -1
- ophyd_async/fastcs/panda/_trigger.py +4 -4
- ophyd_async/fastcs/panda/_writer.py +1 -3
- ophyd_async/plan_stubs/__init__.py +0 -8
- ophyd_async/plan_stubs/_fly.py +0 -204
- ophyd_async/sim/__main__.py +2 -1
- ophyd_async/sim/_blob_detector_writer.py +4 -5
- ophyd_async/sim/_pattern_generator.py +3 -3
- ophyd_async/testing/__init__.py +2 -0
- ophyd_async/testing/_assert.py +34 -6
- {ophyd_async-0.11.dist-info → ophyd_async-0.12.1.dist-info}/METADATA +3 -2
- {ophyd_async-0.11.dist-info → ophyd_async-0.12.1.dist-info}/RECORD +30 -30
- {ophyd_async-0.11.dist-info → ophyd_async-0.12.1.dist-info}/WHEEL +0 -0
- {ophyd_async-0.11.dist-info → ophyd_async-0.12.1.dist-info}/licenses/LICENSE +0 -0
- {ophyd_async-0.11.dist-info → ophyd_async-0.12.1.dist-info}/top_level.txt +0 -0
|
@@ -15,7 +15,7 @@ from ._table import SeqTable
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class SeqTableInfo(ConfinedModel):
|
|
18
|
-
"""Info for the PandA `SeqTable` for
|
|
18
|
+
"""Info for the PandA `SeqTable` for fly scanning."""
|
|
19
19
|
|
|
20
20
|
sequence_table: SeqTable = Field(strict=True)
|
|
21
21
|
repeats: int = Field(ge=0)
|
|
@@ -23,7 +23,7 @@ class SeqTableInfo(ConfinedModel):
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class StaticSeqTableTriggerLogic(FlyerController[SeqTableInfo]):
|
|
26
|
-
"""For controlling the PandA `SeqTable` when
|
|
26
|
+
"""For controlling the PandA `SeqTable` when fly scanning."""
|
|
27
27
|
|
|
28
28
|
def __init__(self, seq: SeqBlock) -> None:
|
|
29
29
|
self.seq = seq
|
|
@@ -52,7 +52,7 @@ class StaticSeqTableTriggerLogic(FlyerController[SeqTableInfo]):
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
class PcompInfo(ConfinedModel):
|
|
55
|
-
"""Info for the PandA `PcompBlock` for
|
|
55
|
+
"""Info for the PandA `PcompBlock` for fly scanning."""
|
|
56
56
|
|
|
57
57
|
start_postion: int = Field(description="start position in counts")
|
|
58
58
|
pulse_width: int = Field(description="width of a single pulse in counts", gt=0)
|
|
@@ -76,7 +76,7 @@ class PcompInfo(ConfinedModel):
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
class StaticPcompTriggerLogic(FlyerController[PcompInfo]):
|
|
79
|
-
"""For controlling the PandA `PcompBlock` when
|
|
79
|
+
"""For controlling the PandA `PcompBlock` when fly scanning."""
|
|
80
80
|
|
|
81
81
|
def __init__(self, pcomp: PcompBlock) -> None:
|
|
82
82
|
self.pcomp = pcomp
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from collections.abc import AsyncGenerator, AsyncIterator
|
|
3
|
-
from pathlib import Path
|
|
4
3
|
|
|
5
4
|
from bluesky.protocols import StreamAsset
|
|
6
5
|
from event_model import DataKey
|
|
@@ -67,8 +66,7 @@ class PandaHDFWriter(DetectorWriter):
|
|
|
67
66
|
describe = await self._describe(name)
|
|
68
67
|
|
|
69
68
|
self._composer = HDFDocumentComposer(
|
|
70
|
-
|
|
71
|
-
/ Path(await self.panda_data_block.hdf_file_name.get_value()),
|
|
69
|
+
f"{info.directory_uri}{info.filename}.h5",
|
|
72
70
|
self._datasets,
|
|
73
71
|
)
|
|
74
72
|
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
"""Plan stubs for connecting, setting up and flying devices."""
|
|
2
2
|
|
|
3
3
|
from ._ensure_connected import ensure_connected
|
|
4
|
-
from ._fly import (
|
|
5
|
-
fly_and_collect,
|
|
6
|
-
prepare_static_seq_table_flyer_and_detectors_with_same_trigger,
|
|
7
|
-
time_resolved_fly_and_collect_with_static_seq_table,
|
|
8
|
-
)
|
|
9
4
|
from ._nd_attributes import setup_ndattributes, setup_ndstats_sum
|
|
10
5
|
from ._panda import apply_panda_settings
|
|
11
6
|
from ._settings import (
|
|
@@ -17,9 +12,6 @@ from ._settings import (
|
|
|
17
12
|
)
|
|
18
13
|
|
|
19
14
|
__all__ = [
|
|
20
|
-
"fly_and_collect",
|
|
21
|
-
"prepare_static_seq_table_flyer_and_detectors_with_same_trigger",
|
|
22
|
-
"time_resolved_fly_and_collect_with_static_seq_table",
|
|
23
15
|
"ensure_connected",
|
|
24
16
|
"setup_ndattributes",
|
|
25
17
|
"setup_ndstats_sum",
|
ophyd_async/plan_stubs/_fly.py
CHANGED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import bluesky.plan_stubs as bps
|
|
2
|
-
from bluesky.utils import short_uid
|
|
3
|
-
|
|
4
|
-
from ophyd_async.core import (
|
|
5
|
-
DetectorTrigger,
|
|
6
|
-
StandardDetector,
|
|
7
|
-
StandardFlyer,
|
|
8
|
-
TriggerInfo,
|
|
9
|
-
in_micros,
|
|
10
|
-
)
|
|
11
|
-
from ophyd_async.fastcs.panda import (
|
|
12
|
-
PandaPcompDirection,
|
|
13
|
-
PcompInfo,
|
|
14
|
-
SeqTable,
|
|
15
|
-
SeqTableInfo,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def prepare_static_pcomp_flyer_and_detectors(
|
|
20
|
-
flyer: StandardFlyer[PcompInfo],
|
|
21
|
-
detectors: list[StandardDetector],
|
|
22
|
-
pcomp_info: PcompInfo,
|
|
23
|
-
trigger_info: TriggerInfo,
|
|
24
|
-
):
|
|
25
|
-
"""Prepare a hardware triggered flyable and one or more detectors.
|
|
26
|
-
|
|
27
|
-
Prepare a hardware triggered flyable and one or more detectors with the
|
|
28
|
-
same trigger.
|
|
29
|
-
|
|
30
|
-
"""
|
|
31
|
-
for det in detectors:
|
|
32
|
-
yield from bps.prepare(det, trigger_info, wait=False, group="prep")
|
|
33
|
-
yield from bps.prepare(flyer, pcomp_info, wait=False, group="prep")
|
|
34
|
-
yield from bps.wait(group="prep")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
|
|
38
|
-
flyer: StandardFlyer[SeqTableInfo],
|
|
39
|
-
detectors: list[StandardDetector],
|
|
40
|
-
number_of_frames: int,
|
|
41
|
-
exposure: float,
|
|
42
|
-
shutter_time: float,
|
|
43
|
-
repeats: int = 1,
|
|
44
|
-
period: float = 0.0,
|
|
45
|
-
frame_timeout: float | None = None,
|
|
46
|
-
):
|
|
47
|
-
"""Prepare a hardware triggered flyable and one or more detectors.
|
|
48
|
-
|
|
49
|
-
Prepare a hardware triggered flyable and one or more detectors with the
|
|
50
|
-
same trigger. This method constructs TriggerInfo and a static sequence
|
|
51
|
-
table from required parameters. The table is required to prepare the flyer,
|
|
52
|
-
and the TriggerInfo is required to prepare the detector(s).
|
|
53
|
-
|
|
54
|
-
This prepares all supplied detectors with the same trigger.
|
|
55
|
-
|
|
56
|
-
"""
|
|
57
|
-
if not detectors:
|
|
58
|
-
raise ValueError("No detectors provided. There must be at least one.")
|
|
59
|
-
|
|
60
|
-
deadtime = max(det._controller.get_deadtime(exposure) for det in detectors) # noqa: SLF001
|
|
61
|
-
|
|
62
|
-
trigger_info = TriggerInfo(
|
|
63
|
-
number_of_events=number_of_frames * repeats,
|
|
64
|
-
trigger=DetectorTrigger.CONSTANT_GATE,
|
|
65
|
-
deadtime=deadtime,
|
|
66
|
-
livetime=exposure,
|
|
67
|
-
exposure_timeout=frame_timeout,
|
|
68
|
-
)
|
|
69
|
-
trigger_time = number_of_frames * (exposure + deadtime)
|
|
70
|
-
pre_delay = max(period - 2 * shutter_time - trigger_time, 0)
|
|
71
|
-
|
|
72
|
-
table = (
|
|
73
|
-
# Wait for pre-delay then open shutter
|
|
74
|
-
SeqTable.row(
|
|
75
|
-
time1=in_micros(pre_delay),
|
|
76
|
-
time2=in_micros(shutter_time),
|
|
77
|
-
outa2=True,
|
|
78
|
-
)
|
|
79
|
-
+
|
|
80
|
-
# Keeping shutter open, do N triggers
|
|
81
|
-
SeqTable.row(
|
|
82
|
-
repeats=number_of_frames,
|
|
83
|
-
time1=in_micros(exposure),
|
|
84
|
-
outa1=True,
|
|
85
|
-
outb1=True,
|
|
86
|
-
time2=in_micros(deadtime),
|
|
87
|
-
outa2=True,
|
|
88
|
-
)
|
|
89
|
-
+
|
|
90
|
-
# Add the shutter close
|
|
91
|
-
SeqTable.row(time2=in_micros(shutter_time))
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
table_info = SeqTableInfo(sequence_table=table, repeats=repeats)
|
|
95
|
-
|
|
96
|
-
for det in detectors:
|
|
97
|
-
yield from bps.prepare(det, trigger_info, wait=False, group="prep")
|
|
98
|
-
yield from bps.prepare(flyer, table_info, wait=False, group="prep")
|
|
99
|
-
yield from bps.wait(group="prep")
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
def fly_and_collect(
|
|
103
|
-
stream_name: str,
|
|
104
|
-
flyer: StandardFlyer[SeqTableInfo] | StandardFlyer[PcompInfo],
|
|
105
|
-
detectors: list[StandardDetector],
|
|
106
|
-
):
|
|
107
|
-
"""Kickoff, complete and collect with a flyer and multiple detectors.
|
|
108
|
-
|
|
109
|
-
This stub takes a flyer and one or more detectors that have been prepared. It
|
|
110
|
-
declares a stream for the detectors, then kicks off the detectors and the flyer.
|
|
111
|
-
The detectors are collected until the flyer and detectors have completed.
|
|
112
|
-
|
|
113
|
-
"""
|
|
114
|
-
yield from bps.declare_stream(*detectors, name=stream_name, collect=True)
|
|
115
|
-
yield from bps.kickoff(flyer, wait=True)
|
|
116
|
-
for detector in detectors:
|
|
117
|
-
yield from bps.kickoff(detector)
|
|
118
|
-
|
|
119
|
-
# collect_while_completing
|
|
120
|
-
group = short_uid(label="complete")
|
|
121
|
-
|
|
122
|
-
yield from bps.complete(flyer, wait=False, group=group)
|
|
123
|
-
for detector in detectors:
|
|
124
|
-
yield from bps.complete(detector, wait=False, group=group)
|
|
125
|
-
|
|
126
|
-
done = False
|
|
127
|
-
while not done:
|
|
128
|
-
try:
|
|
129
|
-
yield from bps.wait(group=group, timeout=0.5)
|
|
130
|
-
except TimeoutError:
|
|
131
|
-
pass
|
|
132
|
-
else:
|
|
133
|
-
done = True
|
|
134
|
-
yield from bps.collect(
|
|
135
|
-
*detectors,
|
|
136
|
-
return_payload=False,
|
|
137
|
-
name=stream_name,
|
|
138
|
-
)
|
|
139
|
-
yield from bps.wait(group=group)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def fly_and_collect_with_static_pcomp(
|
|
143
|
-
stream_name: str,
|
|
144
|
-
flyer: StandardFlyer[PcompInfo],
|
|
145
|
-
detectors: list[StandardDetector],
|
|
146
|
-
number_of_pulses: int,
|
|
147
|
-
pulse_width: int,
|
|
148
|
-
rising_edge_step: int,
|
|
149
|
-
direction: PandaPcompDirection,
|
|
150
|
-
trigger_info: TriggerInfo,
|
|
151
|
-
):
|
|
152
|
-
# Set up scan and prepare trigger
|
|
153
|
-
pcomp_info = PcompInfo(
|
|
154
|
-
start_postion=0,
|
|
155
|
-
pulse_width=pulse_width,
|
|
156
|
-
rising_edge_step=rising_edge_step,
|
|
157
|
-
number_of_pulses=number_of_pulses,
|
|
158
|
-
direction=direction,
|
|
159
|
-
)
|
|
160
|
-
yield from prepare_static_pcomp_flyer_and_detectors(
|
|
161
|
-
flyer, detectors, pcomp_info, trigger_info
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
# Run the fly scan
|
|
165
|
-
yield from fly_and_collect(stream_name, flyer, detectors)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def time_resolved_fly_and_collect_with_static_seq_table(
|
|
169
|
-
stream_name: str,
|
|
170
|
-
flyer: StandardFlyer[SeqTableInfo],
|
|
171
|
-
detectors: list[StandardDetector],
|
|
172
|
-
number_of_frames: int,
|
|
173
|
-
exposure: float,
|
|
174
|
-
shutter_time: float,
|
|
175
|
-
repeats: int = 1,
|
|
176
|
-
period: float = 0.0,
|
|
177
|
-
frame_timeout: float | None = None,
|
|
178
|
-
):
|
|
179
|
-
"""Run a scan wth a flyer and multiple detectors.
|
|
180
|
-
|
|
181
|
-
The stub demonstrates the standard basic flow for a flyscan:
|
|
182
|
-
|
|
183
|
-
- Prepare the flyer and detectors with a trigger
|
|
184
|
-
- Fly and collect:
|
|
185
|
-
- Declare the stream and kickoff the scan
|
|
186
|
-
- Collect while completing
|
|
187
|
-
|
|
188
|
-
This needs to be used in a plan that instantates detectors and a flyer,
|
|
189
|
-
stages/unstages the devices, and opens and closes the run.
|
|
190
|
-
|
|
191
|
-
"""
|
|
192
|
-
# Set up scan and prepare trigger
|
|
193
|
-
yield from prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
|
|
194
|
-
flyer,
|
|
195
|
-
detectors,
|
|
196
|
-
number_of_frames=number_of_frames,
|
|
197
|
-
exposure=exposure,
|
|
198
|
-
shutter_time=shutter_time,
|
|
199
|
-
repeats=repeats,
|
|
200
|
-
period=period,
|
|
201
|
-
frame_timeout=frame_timeout,
|
|
202
|
-
)
|
|
203
|
-
# Run the fly scan
|
|
204
|
-
yield from fly_and_collect(stream_name, flyer, detectors)
|
ophyd_async/sim/__main__.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Used for tutorial `Using Devices`."""
|
|
2
2
|
|
|
3
3
|
# Import bluesky and ophyd
|
|
4
|
+
from pathlib import PurePath
|
|
4
5
|
from tempfile import mkdtemp
|
|
5
6
|
|
|
6
7
|
import bluesky.plan_stubs as bps # noqa: F401
|
|
@@ -27,7 +28,7 @@ pattern_generator = sim.PatternGenerator()
|
|
|
27
28
|
|
|
28
29
|
# Make a path provider that makes UUID filenames within a static
|
|
29
30
|
# temporary directory
|
|
30
|
-
path_provider = StaticPathProvider(UUIDFilenameProvider(), mkdtemp())
|
|
31
|
+
path_provider = StaticPathProvider(UUIDFilenameProvider(), PurePath(mkdtemp()))
|
|
31
32
|
|
|
32
33
|
# All Devices created within this block will be
|
|
33
34
|
# connected and named at the end of the with block
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from collections.abc import AsyncGenerator, AsyncIterator
|
|
2
|
-
from pathlib import Path
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
5
4
|
from bluesky.protocols import Hints, StreamAsset
|
|
@@ -26,14 +25,14 @@ class BlobDetectorWriter(DetectorWriter):
|
|
|
26
25
|
) -> None:
|
|
27
26
|
self.pattern_generator = pattern_generator
|
|
28
27
|
self.path_provider = path_provider
|
|
29
|
-
self.path: Path | None = None
|
|
30
28
|
self.composer: HDFDocumentComposer | None = None
|
|
31
29
|
self.datasets: list[HDFDatasetDescription] = []
|
|
32
30
|
|
|
33
31
|
async def open(self, name: str, exposures_per_event: int = 1) -> dict[str, DataKey]:
|
|
34
32
|
path_info = self.path_provider(name)
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
write_path = path_info.directory_path / f"{path_info.filename}.h5"
|
|
34
|
+
read_path_uri = f"{path_info.directory_uri}{path_info.filename}.h5"
|
|
35
|
+
self.pattern_generator.open_file(write_path, WIDTH, HEIGHT)
|
|
37
36
|
self.exposures_per_event = exposures_per_event
|
|
38
37
|
# We know it will write data and sum, so emit those
|
|
39
38
|
self.datasets = [
|
|
@@ -52,7 +51,7 @@ class BlobDetectorWriter(DetectorWriter):
|
|
|
52
51
|
chunk_shape=(1024,),
|
|
53
52
|
),
|
|
54
53
|
]
|
|
55
|
-
self.composer = HDFDocumentComposer(
|
|
54
|
+
self.composer = HDFDocumentComposer(read_path_uri, self.datasets)
|
|
56
55
|
describe = {
|
|
57
56
|
ds.data_key: DataKey(
|
|
58
57
|
source="sim://pattern-generator-hdf-file",
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import time
|
|
5
|
-
from pathlib import
|
|
5
|
+
from pathlib import PurePath
|
|
6
6
|
|
|
7
7
|
import h5py
|
|
8
8
|
import numpy as np
|
|
@@ -35,7 +35,7 @@ def generate_interesting_pattern(
|
|
|
35
35
|
class PatternFile:
|
|
36
36
|
def __init__(
|
|
37
37
|
self,
|
|
38
|
-
path:
|
|
38
|
+
path: PurePath,
|
|
39
39
|
width: int = 320,
|
|
40
40
|
height: int = 240,
|
|
41
41
|
):
|
|
@@ -94,7 +94,7 @@ class PatternGenerator:
|
|
|
94
94
|
offset = 100 if high_energy else 10
|
|
95
95
|
return generate_interesting_pattern(self._x, self._y, channel, offset)
|
|
96
96
|
|
|
97
|
-
def open_file(self, path:
|
|
97
|
+
def open_file(self, path: PurePath, width: int, height: int):
|
|
98
98
|
self._file = PatternFile(path, width, height)
|
|
99
99
|
|
|
100
100
|
def _get_file(self) -> PatternFile:
|
ophyd_async/testing/__init__.py
CHANGED
|
@@ -11,6 +11,7 @@ from ._assert import (
|
|
|
11
11
|
assert_emitted,
|
|
12
12
|
assert_reading,
|
|
13
13
|
assert_value,
|
|
14
|
+
partial_reading,
|
|
14
15
|
)
|
|
15
16
|
from ._mock_signal_utils import (
|
|
16
17
|
callback_on_mock_put,
|
|
@@ -47,6 +48,7 @@ __all__ = [
|
|
|
47
48
|
"assert_configuration",
|
|
48
49
|
"assert_describe_signal",
|
|
49
50
|
"assert_emitted",
|
|
51
|
+
"partial_reading",
|
|
50
52
|
# Mocking utilities
|
|
51
53
|
"get_mock",
|
|
52
54
|
"set_mock_value",
|
ophyd_async/testing/_assert.py
CHANGED
|
@@ -21,6 +21,15 @@ from ophyd_async.core import (
|
|
|
21
21
|
from ._utils import T
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
def partial_reading(val: Any) -> dict[str, Any]:
|
|
25
|
+
"""Helper function for building expected reading or configuration dicts.
|
|
26
|
+
|
|
27
|
+
:param val: Value to be wrapped in dict with "value" as the key.
|
|
28
|
+
:return: The dict that has wrapped the val with key "value".
|
|
29
|
+
"""
|
|
30
|
+
return {"value": val}
|
|
31
|
+
|
|
32
|
+
|
|
24
33
|
def approx_value(value: Any):
|
|
25
34
|
"""Allow any value to be compared to another in tests.
|
|
26
35
|
|
|
@@ -45,14 +54,18 @@ async def assert_value(signal: SignalR[SignalDatatypeT], value: Any) -> None:
|
|
|
45
54
|
async def assert_reading(
|
|
46
55
|
readable: AsyncReadable,
|
|
47
56
|
expected_reading: Mapping[str, Mapping[str, Any]],
|
|
57
|
+
full_match: bool = True,
|
|
48
58
|
) -> None:
|
|
49
59
|
"""Assert that a readable Device has the given reading.
|
|
50
60
|
|
|
51
61
|
:param readable: Device with an async ``read()`` method to get the reading from.
|
|
52
62
|
:param expected_reading: The expected reading from the readable.
|
|
63
|
+
:param full_match: if expected_reading keys set is same as actual keys set.
|
|
64
|
+
true: exact match
|
|
65
|
+
false: expected_reading keys is subset of actual reading keys
|
|
53
66
|
"""
|
|
54
67
|
actual_reading = await readable.read()
|
|
55
|
-
_assert_readings_approx_equal(expected_reading, actual_reading)
|
|
68
|
+
_assert_readings_approx_equal(expected_reading, actual_reading, full_match)
|
|
56
69
|
|
|
57
70
|
|
|
58
71
|
def _approx_reading(expected: Mapping[str, Any], actual: Reading) -> Reading:
|
|
@@ -69,16 +82,26 @@ def _approx_reading(expected: Mapping[str, Any], actual: Reading) -> Reading:
|
|
|
69
82
|
|
|
70
83
|
|
|
71
84
|
def _assert_readings_approx_equal(
|
|
72
|
-
expected: Mapping[str, Mapping[str, Any]],
|
|
85
|
+
expected: Mapping[str, Mapping[str, Any]],
|
|
86
|
+
actual: Mapping[str, Reading],
|
|
87
|
+
full_match: bool = True,
|
|
73
88
|
):
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
# expand the expected keys to include actual if we allow partial matches
|
|
90
|
+
if not full_match:
|
|
91
|
+
expected = dict(actual, **expected)
|
|
92
|
+
# now make them approximate if they are in actual so we get a nicer diff
|
|
93
|
+
approx_expected = {
|
|
94
|
+
k: _approx_reading(v, actual[k]) if k in actual else v
|
|
95
|
+
for k, v in expected.items()
|
|
76
96
|
}
|
|
97
|
+
# now we can compare them
|
|
98
|
+
assert actual == approx_expected
|
|
77
99
|
|
|
78
100
|
|
|
79
101
|
async def assert_configuration(
|
|
80
102
|
configurable: AsyncConfigurable,
|
|
81
|
-
|
|
103
|
+
expected_configuration: dict[str, dict[str, Any]],
|
|
104
|
+
full_match: bool = True,
|
|
82
105
|
) -> None:
|
|
83
106
|
"""Assert that a configurable Device has the given configuration.
|
|
84
107
|
|
|
@@ -86,9 +109,14 @@ async def assert_configuration(
|
|
|
86
109
|
Device with an async ``read_configuration()`` method to get the
|
|
87
110
|
configuration from.
|
|
88
111
|
:param configuration: The expected configuration from the configurable.
|
|
112
|
+
:param full_match: if expected_reading keys set is same as actual keys set.
|
|
113
|
+
true: exact match
|
|
114
|
+
false: expected_reading keys is subset of actual reading keys
|
|
89
115
|
"""
|
|
90
116
|
actual_configuration = await configurable.read_configuration()
|
|
91
|
-
_assert_readings_approx_equal(
|
|
117
|
+
_assert_readings_approx_equal(
|
|
118
|
+
expected_configuration, actual_configuration, full_match
|
|
119
|
+
)
|
|
92
120
|
|
|
93
121
|
|
|
94
122
|
async def assert_describe_signal(signal: SignalR, /, **metadata):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.1
|
|
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
|
|
@@ -48,6 +48,7 @@ Requires-Dist: pyyaml
|
|
|
48
48
|
Requires-Dist: colorlog
|
|
49
49
|
Requires-Dist: pydantic>=2.0
|
|
50
50
|
Requires-Dist: pydantic-numpy
|
|
51
|
+
Requires-Dist: stamina>=23.1.0
|
|
51
52
|
Provides-Extra: sim
|
|
52
53
|
Requires-Dist: h5py; extra == "sim"
|
|
53
54
|
Provides-Extra: ca
|
|
@@ -120,7 +121,7 @@ The main differences from ophyd sync are:
|
|
|
120
121
|
- Support for [EPICS][] PVA and [Tango][] as well as the traditional EPICS CA
|
|
121
122
|
- Better library support for splitting the logic from the hardware interface to avoid complex class heirarchies
|
|
122
123
|
|
|
123
|
-
It was written with the aim of implementing
|
|
124
|
+
It was written with the aim of implementing fly scanning 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 fly scanning without the performance and complexity overhead of multiple threads.
|
|
124
125
|
|
|
125
126
|
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.
|
|
126
127
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
ophyd_async/__init__.py,sha256=dcAA3qsj1nNIMe5l-v2tlduZ_ypwBmyuHe45Lsq4k4w,206
|
|
2
2
|
ophyd_async/__main__.py,sha256=n_U4O9bgm97OuboUB_9eK7eFiwy8BZSgXJ0OzbE0DqU,481
|
|
3
3
|
ophyd_async/_docs_parser.py,sha256=gPYrigfSbYCF7QoSf2UvE-cpQu4snSssl7ZWN-kKDzI,352
|
|
4
|
-
ophyd_async/_version.py,sha256=
|
|
4
|
+
ophyd_async/_version.py,sha256=DzB47l1iPNTY8yuA60VuZvneNqNdRBd1svEjKxC37o4,513
|
|
5
5
|
ophyd_async/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
ophyd_async/core/__init__.py,sha256=RtYk6FdJxc7lxoSReRV1D7weTRYFu9ylhNNd3DyN904,4752
|
|
7
7
|
ophyd_async/core/_derived_signal.py,sha256=TuZza_j3J1Bw4QSqBYB9Ta2FyQP5BycO3nSHVtJ890Q,13015
|
|
@@ -9,23 +9,23 @@ ophyd_async/core/_derived_signal_backend.py,sha256=PYyyont_nUR9LBC9eqVwueHCMwLJf
|
|
|
9
9
|
ophyd_async/core/_detector.py,sha256=x1o-eSkvemQ-fTk47440owkTmYhuckA2ILNOCoJlHCY,15201
|
|
10
10
|
ophyd_async/core/_device.py,sha256=lSm8FBul9NTn9VO0rsAlV9pctJyUsMdU2ztEf5CqH5M,14716
|
|
11
11
|
ophyd_async/core/_device_filler.py,sha256=MDz8eQQ-eEAwo-UEMxfqPfpcBuMG01tLCGR6utwVnmE,14825
|
|
12
|
-
ophyd_async/core/_flyer.py,sha256=
|
|
13
|
-
ophyd_async/core/_hdf_dataset.py,sha256=
|
|
12
|
+
ophyd_async/core/_flyer.py,sha256=8zKyU5aQOr_t59GIUwsYeb8NSabdvBp0swwuRe4v5VQ,3457
|
|
13
|
+
ophyd_async/core/_hdf_dataset.py,sha256=0bIX_ZbFSMdXqDwRtEvV-0avHnwXhjPddE5GVNmo7H8,2608
|
|
14
14
|
ophyd_async/core/_log.py,sha256=DxKR4Nz3SgTaTzKBZWqt-w48yT8WUAr_3Qr223TEWRw,3587
|
|
15
15
|
ophyd_async/core/_mock_signal_backend.py,sha256=SPdCbVWss6-iL9C3t9u0IvR_Ln9JeDypVd18WlivdjE,3156
|
|
16
16
|
ophyd_async/core/_protocol.py,sha256=wQ_snxhTprHqEjQb1HgFwBljwolMY6A8C3xgV1PXwdU,4051
|
|
17
|
-
ophyd_async/core/_providers.py,sha256=
|
|
17
|
+
ophyd_async/core/_providers.py,sha256=WBht3QCgvGc0stNcwH6z4Zr6hAz3e01-88NjsYI2w6I,9740
|
|
18
18
|
ophyd_async/core/_readable.py,sha256=iBo1YwA5bsAbzLbznvmSnzKDWUuGkLh850Br3BXsgeU,11707
|
|
19
19
|
ophyd_async/core/_settings.py,sha256=_ZccbXKP7j5rG6-bMKk7aaLr8hChdRDAPY_YSR71XXM,4213
|
|
20
|
-
ophyd_async/core/_signal.py,sha256=
|
|
20
|
+
ophyd_async/core/_signal.py,sha256=wKbDJYpN7zWgRf_jAARFqZwCGXcdzPRDNXwvjGUR6dw,28217
|
|
21
21
|
ophyd_async/core/_signal_backend.py,sha256=PvwTbbSVEGqM-2s5BNRrKGwM_MiYL71qMxYAgyZ7wRM,6930
|
|
22
|
-
ophyd_async/core/_soft_signal_backend.py,sha256=
|
|
22
|
+
ophyd_async/core/_soft_signal_backend.py,sha256=NJUuyaCKtBZjggt8WKi7_lKQRHasToxviuQvl5xbhLU,6222
|
|
23
23
|
ophyd_async/core/_status.py,sha256=h4TtWFM7wFtpxxyAYYSITgcVzArYZdYBHbya6qIX5t0,6553
|
|
24
24
|
ophyd_async/core/_table.py,sha256=ai-_W-_WMZcy9f69BDYRv9vjVl-AVeOPN_uHYoGCSsc,6905
|
|
25
25
|
ophyd_async/core/_utils.py,sha256=fePvt3g7eQ6CRQcMVkMeqxcbvYZboZ2sf1fVVZL-26M,12450
|
|
26
26
|
ophyd_async/core/_yaml_settings.py,sha256=Qojhku9l5kPSkTnEylCRWTe0gpw6S_XP5av5dPpqFgQ,2089
|
|
27
27
|
ophyd_async/epics/__init__.py,sha256=ou4yEaH9VZHz70e8oM614-arLMQvUfQyXhRJsnEpWn8,60
|
|
28
|
-
ophyd_async/epics/motor.py,sha256=
|
|
28
|
+
ophyd_async/epics/motor.py,sha256=UFolYxuaePnWNJNOFzgI-He4kBTHhJqaTywtqFFSmsk,8475
|
|
29
29
|
ophyd_async/epics/signal.py,sha256=0A-supp9ajr63O6aD7F9oG0-Q26YmRjk-ZGh57-jo1Y,239
|
|
30
30
|
ophyd_async/epics/adandor/__init__.py,sha256=dlitllrAdhvh16PAcVMUSSEytTDNMu6_HuYk8KD1EoY,343
|
|
31
31
|
ophyd_async/epics/adandor/_andor.py,sha256=SxAIP9OLefUqKcxrxhjNzil5D8-59Ps0vADdR6scO44,1281
|
|
@@ -35,15 +35,15 @@ ophyd_async/epics/adaravis/__init__.py,sha256=ZQaJVQiwcQn9hUZADrYgBE1sDfFEwjhVBJ
|
|
|
35
35
|
ophyd_async/epics/adaravis/_aravis.py,sha256=Ju2wuebz9_ovl-Kza39s5VQ1pV-Omt_BaIWKqP4kcGA,1315
|
|
36
36
|
ophyd_async/epics/adaravis/_aravis_controller.py,sha256=WiFR7_FAAu6_88zG-yzGLsR9YcO4L6xR73Wnjw9n0i4,1908
|
|
37
37
|
ophyd_async/epics/adaravis/_aravis_io.py,sha256=af5RxeXF2ligvAXwMNMKHA4QHTR_WmNFz-f18qD2dbg,855
|
|
38
|
-
ophyd_async/epics/adcore/__init__.py,sha256=
|
|
38
|
+
ophyd_async/epics/adcore/__init__.py,sha256=sDvQO3TshdXfDvLGqzsSNJT95Wk7tUAmOowDwB00Td0,1625
|
|
39
39
|
ophyd_async/epics/adcore/_core_detector.py,sha256=mRDaHgXCTZF-MIVsU1csoQx9jObutYDpMWayugx2-jI,2631
|
|
40
|
-
ophyd_async/epics/adcore/_core_io.py,sha256=
|
|
40
|
+
ophyd_async/epics/adcore/_core_io.py,sha256=c1GqAUdv8lAQjklbKHtraLMhPOWEttDCsH9ow7M5I0U,7690
|
|
41
41
|
ophyd_async/epics/adcore/_core_logic.py,sha256=IH7iOSVIsVj4e97ClhdBFpmdMkb8TznSaLkd3ohEhUs,8884
|
|
42
|
-
ophyd_async/epics/adcore/_core_writer.py,sha256=
|
|
43
|
-
ophyd_async/epics/adcore/_hdf_writer.py,sha256=
|
|
44
|
-
ophyd_async/epics/adcore/_jpeg_writer.py,sha256=
|
|
42
|
+
ophyd_async/epics/adcore/_core_writer.py,sha256=6OEU8fcn7ATd3dml_aBZ_LmFgVGcdbNFyg1Sx2zqV7s,8522
|
|
43
|
+
ophyd_async/epics/adcore/_hdf_writer.py,sha256=AvCv_5dd2HdQoE12_CR6vH2hig2EdEIWklOu6CbPVlc,5816
|
|
44
|
+
ophyd_async/epics/adcore/_jpeg_writer.py,sha256=VYpUWQGEjrKG2kiRGQZlBCPXVJ1BzWb9GyB9KhxPWgo,688
|
|
45
45
|
ophyd_async/epics/adcore/_single_trigger.py,sha256=tFGLT1b_rZzAvbqWP-hyCccxJMRY26T5IER-VAqKXmc,1275
|
|
46
|
-
ophyd_async/epics/adcore/_tiff_writer.py,sha256=
|
|
46
|
+
ophyd_async/epics/adcore/_tiff_writer.py,sha256=197Ky9ltsJjUKNwl8_OAuoCe8dWIc7zCFs7wautwC7Y,689
|
|
47
47
|
ophyd_async/epics/adcore/_utils.py,sha256=jMmZnyDwRDBq-N_x8qOWjW2RMN9uw2KuoAmukPbb404,4252
|
|
48
48
|
ophyd_async/epics/adkinetix/__init__.py,sha256=A9xq3lGMrmza9lfukRixC0Up_kUDVFII8JguLr2x7Bw,308
|
|
49
49
|
ophyd_async/epics/adkinetix/_kinetix.py,sha256=zZv0JZ8i1RSx7KBDn_1HGNOY0BoIP81mRK5TKq7d4eA,1302
|
|
@@ -62,12 +62,12 @@ ophyd_async/epics/advimba/_vimba.py,sha256=4XlEnsJMGDzHLuYaIDUmaxx0gtOAehn5BKBZM
|
|
|
62
62
|
ophyd_async/epics/advimba/_vimba_controller.py,sha256=v0av2bGnaJ01w9Igksupt2IlkuBEFlAeRCPOVma-Xa4,1980
|
|
63
63
|
ophyd_async/epics/advimba/_vimba_io.py,sha256=cb2Nfp05fBZAcNVXpz-rqRIRS-TiZW5DPUJOmaFyAw0,1589
|
|
64
64
|
ophyd_async/epics/core/__init__.py,sha256=8NoQxEEc2Ny_L9nrD2fnGSf_2gJr1wCR1LwUeLNcIJo,588
|
|
65
|
-
ophyd_async/epics/core/_aioca.py,sha256=
|
|
65
|
+
ophyd_async/epics/core/_aioca.py,sha256=elNR5c2-YcDUoyzuvTEVURoqx92wkVoMDNjwjeZ0WmA,13136
|
|
66
66
|
ophyd_async/epics/core/_epics_connector.py,sha256=S4z_wbj-aogVcjqCyUgjhcq5Y4gDC7y6wXbsSz2nODY,1918
|
|
67
67
|
ophyd_async/epics/core/_epics_device.py,sha256=wGdR24I7GSPh3HmM7jsWKZhBZgt4IyLrCn4Ut7Wx_xo,510
|
|
68
68
|
ophyd_async/epics/core/_p4p.py,sha256=uWh3oWPme74G4YfeJ6k8ZlHdKOwcf8Xp1J82b9aa_JI,16407
|
|
69
69
|
ophyd_async/epics/core/_pvi_connector.py,sha256=nAReSiasZA3j_0f8XhuWVO4_ck0MrusnKR9Jg-RT-ok,5584
|
|
70
|
-
ophyd_async/epics/core/_signal.py,sha256=
|
|
70
|
+
ophyd_async/epics/core/_signal.py,sha256=qAEe8mgXRMgBTcxuwN-KDGSRtJTwrhygThTDe5vA3EQ,5916
|
|
71
71
|
ophyd_async/epics/core/_util.py,sha256=G2kYfwsQ5iS3EgGrGuPA8bgC_PEN_XxO28oBurIqJFQ,2522
|
|
72
72
|
ophyd_async/epics/demo/__init__.py,sha256=WR2M3D8dbHcisJW2OIU2ManZu5SWez8ytZEp4jSBfDY,416
|
|
73
73
|
ophyd_async/epics/demo/__main__.py,sha256=o6M0FSWduPHe2lN9yNEdsXb48NckSd54-XJGoLe20Pc,1116
|
|
@@ -85,7 +85,7 @@ ophyd_async/epics/pmac/__init__.py,sha256=RWqo5nYE2MMBdwvMxdeVG213MN38b9VPlpDHQW
|
|
|
85
85
|
ophyd_async/epics/pmac/_pmac_io.py,sha256=yMQpZ0Osh4l8VRd2aqWQE9ebJDfh5FwM_0pp1pe8-C0,3564
|
|
86
86
|
ophyd_async/epics/testing/__init__.py,sha256=aTIv4D2DYrpnGco5RQF8QuLG1SfFkIlTyM2uYEKXltA,522
|
|
87
87
|
ophyd_async/epics/testing/_example_ioc.py,sha256=uUmfMXV_Pd2SMFyb0y_4uTc6gkGRUqU1cJ-XQC2ROW8,3915
|
|
88
|
-
ophyd_async/epics/testing/_utils.py,sha256=
|
|
88
|
+
ophyd_async/epics/testing/_utils.py,sha256=9gxpwaWX0HGtacu1LTupcw7viXN8G78RmuNciU_-cjs,1702
|
|
89
89
|
ophyd_async/epics/testing/test_records.db,sha256=SgWQPZgtmc__JiLkH2VPwe5KZOua6ZCIgTLGT_5SDDc,3589
|
|
90
90
|
ophyd_async/epics/testing/test_records_pva.db,sha256=HJAJSvLtPWG5B5dKv8OZ0_hPJxRFrDoYp6ROcF2lqyA,4202
|
|
91
91
|
ophyd_async/fastcs/__init__.py,sha256=qlIM9-pjJ8yWfnzTM9-T9cw7zQLKjeeNROQTni5Dr6M,80
|
|
@@ -100,25 +100,25 @@ ophyd_async/fastcs/panda/_block.py,sha256=SM7NaWCRwLz2Pl4wgjZMrDgx3ZLdGPTw6nU0bA
|
|
|
100
100
|
ophyd_async/fastcs/panda/_control.py,sha256=xtW3dH_MLQoycgP-4vJtYx1M9alHjWo13iu9UFTgwzY,1306
|
|
101
101
|
ophyd_async/fastcs/panda/_hdf_panda.py,sha256=tL_OWHxlMQcMZGq9sxHLSeag6hP9MRIbTPn1W0u0iNI,1237
|
|
102
102
|
ophyd_async/fastcs/panda/_table.py,sha256=maKGoKypEuYqTSVWGgDO6GMEKOtlDm9Dn5YiYdBzu6c,2486
|
|
103
|
-
ophyd_async/fastcs/panda/_trigger.py,sha256=
|
|
104
|
-
ophyd_async/fastcs/panda/_writer.py,sha256=
|
|
105
|
-
ophyd_async/plan_stubs/__init__.py,sha256=
|
|
103
|
+
ophyd_async/fastcs/panda/_trigger.py,sha256=TLd0ST-ZgsCGpONGUe76qHOaH74TlZNIGNkh-10eRa8,3404
|
|
104
|
+
ophyd_async/fastcs/panda/_writer.py,sha256=UqsU44u0uIqkDNky3mIzhW3OhLeZ8TSqFS666qrRdmA,6181
|
|
105
|
+
ophyd_async/plan_stubs/__init__.py,sha256=sRe1Jna_6i7aKjE3pPzsP4iNMWeWdtiptLnOq9pov9M,619
|
|
106
106
|
ophyd_async/plan_stubs/_ensure_connected.py,sha256=YR6VRj7koccJ4x35NV-Ugl4ZbxgAoGN9PjVIjhv0gpw,894
|
|
107
|
-
ophyd_async/plan_stubs/_fly.py,sha256=
|
|
107
|
+
ophyd_async/plan_stubs/_fly.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
108
108
|
ophyd_async/plan_stubs/_nd_attributes.py,sha256=kwzyUSeidUH714gaZQtJLxCgDZtmIRyyoKBBRbvqg38,2350
|
|
109
109
|
ophyd_async/plan_stubs/_panda.py,sha256=5_Mf9kGzNjXpf_YscpCUE8tgq284nOHWCG7o_LNFfII,463
|
|
110
110
|
ophyd_async/plan_stubs/_settings.py,sha256=e3dGVSUV-Htay_9fKXyQTAQLdjunetGI3OBYp_oC_FY,5574
|
|
111
111
|
ophyd_async/plan_stubs/_utils.py,sha256=zClRo5ve8RGia7wQnby41W-Zprj-slOA5da1LfYnuhw,45
|
|
112
112
|
ophyd_async/plan_stubs/_wait_for_awaitable.py,sha256=PGct_dGezKrLhm0W_GD83dwevSccG_vsmj0WSlMNVWc,364
|
|
113
113
|
ophyd_async/sim/__init__.py,sha256=TC86iJGt4u5UtRJniNEaUJbYB2C03kmjZF-jr2zPExY,709
|
|
114
|
-
ophyd_async/sim/__main__.py,sha256=
|
|
114
|
+
ophyd_async/sim/__main__.py,sha256=TPN2nc4qYdBEKpNq4FYsRMvW5a0TEFx1sM92ScIybow,1732
|
|
115
115
|
ophyd_async/sim/_blob_detector.py,sha256=bJa-G2JF6pPLJx4YIEvFTG07DvQ18ZNSYbtde6qnWPY,1033
|
|
116
116
|
ophyd_async/sim/_blob_detector_controller.py,sha256=y1aSNQJUPnsT2qnj2sk254Mp18anmgQy7ctHlYQZ_B0,1788
|
|
117
|
-
ophyd_async/sim/_blob_detector_writer.py,sha256
|
|
117
|
+
ophyd_async/sim/_blob_detector_writer.py,sha256=_Pd0OaP4_mZfwxtUF35v7hsktLP_wYljR4nylr5CzJo,3346
|
|
118
118
|
ophyd_async/sim/_mirror_horizontal.py,sha256=Jsqa8Snjy1jQDboZtAQFJjGor5uKk8FBC7OCe-GoZDw,1478
|
|
119
119
|
ophyd_async/sim/_mirror_vertical.py,sha256=HUD44mYT0jQ0GKiQKxD7k_7y6o6OdE6TztgdPUJIK_g,2085
|
|
120
120
|
ophyd_async/sim/_motor.py,sha256=7s2jBNwWm4CI6I6l_LEpe7z61QdWy82JdZBKSFOnYe4,8994
|
|
121
|
-
ophyd_async/sim/_pattern_generator.py,sha256=
|
|
121
|
+
ophyd_async/sim/_pattern_generator.py,sha256=kuxvyX2gIxrywhQRhaO1g8YluBT7LBkE20IsurZS-6o,3734
|
|
122
122
|
ophyd_async/sim/_point_detector.py,sha256=nXgL_1aJZciNBw8Zr2wMYaMbzzAEKXV3yV8FQz2nS_4,2940
|
|
123
123
|
ophyd_async/sim/_stage.py,sha256=qaeyZbUVL1v2pTHJiZxq-y6BKpA1l_DAKyzAQppQx70,772
|
|
124
124
|
ophyd_async/tango/__init__.py,sha256=g9xzjlzPpUAP12YI-kYwfAoLSYPAQdL1S11R2c-cius,60
|
|
@@ -137,16 +137,16 @@ ophyd_async/tango/demo/_tango/__init__.py,sha256=FfONT7vM49nNo3a1Lv-LcMZO9EHv6bv
|
|
|
137
137
|
ophyd_async/tango/demo/_tango/_servers.py,sha256=putvERDyibibaTbhdWyqZB_axj2fURXqzDsZb9oSW14,2991
|
|
138
138
|
ophyd_async/tango/testing/__init__.py,sha256=SYXPAS00ny3jlUMOJKpaewO4ljPjK1_z1smj7IfsBQg,148
|
|
139
139
|
ophyd_async/tango/testing/_one_of_everything.py,sha256=tsxWgy2f_m9f0FH4XCVO_I8OtEquKbJQZbr4KaXMJL4,6571
|
|
140
|
-
ophyd_async/testing/__init__.py,sha256=
|
|
140
|
+
ophyd_async/testing/__init__.py,sha256=jDBzUAHGDMfkhd-_9u0CJWEq0E0sPrIGGlLmVzEyxY8,1742
|
|
141
141
|
ophyd_async/testing/__pytest_assert_rewrite.py,sha256=_SU2UfChPgEf7CFY7aYH2B7MLp-07_qYnVLyu6QtDL8,129
|
|
142
|
-
ophyd_async/testing/_assert.py,sha256=
|
|
142
|
+
ophyd_async/testing/_assert.py,sha256=zDTJh7QPhaJpzhnuFuejGKTKbKAs7ZNKx3sVsXBMrTU,8758
|
|
143
143
|
ophyd_async/testing/_mock_signal_utils.py,sha256=d-n_923ii59-ae9TbqVuIK9MAJpDmu0k47fzgJLj8t8,5195
|
|
144
144
|
ophyd_async/testing/_one_of_everything.py,sha256=Di0hPoKwrDOSsx50-2UdSHM2EbIKrPG9s0Vp11nE9V8,4773
|
|
145
145
|
ophyd_async/testing/_single_derived.py,sha256=5-HOTzgePcZ354NK_ssVpyIbJoJmKyjVQCxSwQXUC-4,2730
|
|
146
146
|
ophyd_async/testing/_utils.py,sha256=zClRo5ve8RGia7wQnby41W-Zprj-slOA5da1LfYnuhw,45
|
|
147
147
|
ophyd_async/testing/_wait_for_pending.py,sha256=YZAR48n-CW0GsPey3zFRzMJ4byDAr3HvMIoawjmTrHw,732
|
|
148
|
-
ophyd_async-0.
|
|
149
|
-
ophyd_async-0.
|
|
150
|
-
ophyd_async-0.
|
|
151
|
-
ophyd_async-0.
|
|
152
|
-
ophyd_async-0.
|
|
148
|
+
ophyd_async-0.12.1.dist-info/licenses/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
|
|
149
|
+
ophyd_async-0.12.1.dist-info/METADATA,sha256=Vn04AobiRZJ4KZJ7Na9c3whRj0M1eEmWBbtWuW03i3I,7112
|
|
150
|
+
ophyd_async-0.12.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
151
|
+
ophyd_async-0.12.1.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
|
|
152
|
+
ophyd_async-0.12.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|