ophyd-async 0.7.0__py3-none-any.whl → 0.8.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.
- ophyd_async/_version.py +2 -2
- ophyd_async/core/__init__.py +34 -9
- ophyd_async/core/_detector.py +5 -10
- ophyd_async/core/_device.py +170 -68
- ophyd_async/core/_device_filler.py +269 -0
- ophyd_async/core/_device_save_loader.py +6 -7
- ophyd_async/core/_mock_signal_backend.py +35 -40
- ophyd_async/core/_mock_signal_utils.py +25 -16
- ophyd_async/core/_protocol.py +28 -8
- ophyd_async/core/_readable.py +133 -134
- ophyd_async/core/_signal.py +219 -163
- ophyd_async/core/_signal_backend.py +131 -64
- ophyd_async/core/_soft_signal_backend.py +131 -194
- ophyd_async/core/_status.py +22 -6
- ophyd_async/core/_table.py +102 -100
- ophyd_async/core/_utils.py +143 -32
- ophyd_async/epics/adaravis/_aravis_controller.py +2 -2
- ophyd_async/epics/adaravis/_aravis_io.py +8 -6
- ophyd_async/epics/adcore/_core_io.py +5 -7
- ophyd_async/epics/adcore/_core_logic.py +3 -1
- ophyd_async/epics/adcore/_hdf_writer.py +2 -2
- ophyd_async/epics/adcore/_single_trigger.py +6 -10
- ophyd_async/epics/adcore/_utils.py +15 -10
- ophyd_async/epics/adkinetix/__init__.py +2 -1
- ophyd_async/epics/adkinetix/_kinetix_controller.py +6 -3
- ophyd_async/epics/adkinetix/_kinetix_io.py +4 -5
- ophyd_async/epics/adpilatus/_pilatus_controller.py +2 -2
- ophyd_async/epics/adpilatus/_pilatus_io.py +3 -4
- ophyd_async/epics/adsimdetector/_sim_controller.py +2 -2
- ophyd_async/epics/advimba/__init__.py +4 -1
- ophyd_async/epics/advimba/_vimba_controller.py +6 -3
- ophyd_async/epics/advimba/_vimba_io.py +8 -9
- ophyd_async/epics/core/__init__.py +26 -0
- ophyd_async/epics/core/_aioca.py +323 -0
- ophyd_async/epics/core/_epics_connector.py +53 -0
- ophyd_async/epics/core/_epics_device.py +13 -0
- ophyd_async/epics/core/_p4p.py +383 -0
- ophyd_async/epics/core/_pvi_connector.py +91 -0
- ophyd_async/epics/core/_signal.py +171 -0
- ophyd_async/epics/core/_util.py +61 -0
- ophyd_async/epics/demo/_mover.py +4 -5
- ophyd_async/epics/demo/_sensor.py +14 -13
- ophyd_async/epics/eiger/_eiger.py +1 -2
- ophyd_async/epics/eiger/_eiger_controller.py +7 -2
- ophyd_async/epics/eiger/_eiger_io.py +3 -5
- ophyd_async/epics/eiger/_odin_io.py +5 -5
- ophyd_async/epics/motor.py +4 -5
- ophyd_async/epics/signal.py +11 -0
- ophyd_async/epics/testing/__init__.py +24 -0
- ophyd_async/epics/testing/_example_ioc.py +105 -0
- ophyd_async/epics/testing/_utils.py +78 -0
- ophyd_async/epics/testing/test_records.db +152 -0
- ophyd_async/epics/testing/test_records_pva.db +177 -0
- ophyd_async/fastcs/core.py +9 -0
- ophyd_async/fastcs/panda/__init__.py +4 -4
- ophyd_async/fastcs/panda/_block.py +18 -13
- ophyd_async/fastcs/panda/_control.py +3 -5
- ophyd_async/fastcs/panda/_hdf_panda.py +5 -19
- ophyd_async/fastcs/panda/_table.py +30 -52
- ophyd_async/fastcs/panda/_trigger.py +8 -8
- ophyd_async/fastcs/panda/_writer.py +2 -5
- ophyd_async/plan_stubs/_ensure_connected.py +20 -13
- ophyd_async/plan_stubs/_fly.py +2 -2
- ophyd_async/plan_stubs/_nd_attributes.py +5 -4
- ophyd_async/py.typed +0 -0
- ophyd_async/sim/demo/_pattern_detector/_pattern_detector_controller.py +1 -2
- ophyd_async/sim/demo/_sim_motor.py +3 -4
- ophyd_async/tango/__init__.py +0 -45
- ophyd_async/tango/{signal → core}/__init__.py +9 -6
- ophyd_async/tango/core/_base_device.py +132 -0
- ophyd_async/tango/{signal → core}/_signal.py +42 -53
- ophyd_async/tango/{base_devices → core}/_tango_readable.py +3 -4
- ophyd_async/tango/{signal → core}/_tango_transport.py +38 -40
- ophyd_async/tango/demo/_counter.py +12 -23
- ophyd_async/tango/demo/_mover.py +13 -13
- {ophyd_async-0.7.0.dist-info → ophyd_async-0.8.0.dist-info}/METADATA +52 -55
- ophyd_async-0.8.0.dist-info/RECORD +116 -0
- {ophyd_async-0.7.0.dist-info → ophyd_async-0.8.0.dist-info}/WHEEL +1 -1
- ophyd_async/epics/pvi/__init__.py +0 -3
- ophyd_async/epics/pvi/_pvi.py +0 -338
- ophyd_async/epics/signal/__init__.py +0 -21
- ophyd_async/epics/signal/_aioca.py +0 -378
- ophyd_async/epics/signal/_common.py +0 -57
- ophyd_async/epics/signal/_epics_transport.py +0 -34
- ophyd_async/epics/signal/_p4p.py +0 -518
- ophyd_async/epics/signal/_signal.py +0 -114
- ophyd_async/tango/base_devices/__init__.py +0 -4
- ophyd_async/tango/base_devices/_base_device.py +0 -225
- ophyd_async-0.7.0.dist-info/RECORD +0 -108
- {ophyd_async-0.7.0.dist-info → ophyd_async-0.8.0.dist-info}/LICENSE +0 -0
- {ophyd_async-0.7.0.dist-info → ophyd_async-0.8.0.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.7.0.dist-info → ophyd_async-0.8.0.dist-info}/top_level.txt +0 -0
ophyd_async/epics/pvi/_pvi.py
DELETED
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import types
|
|
3
|
-
from collections.abc import Callable
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from inspect import isclass
|
|
6
|
-
from typing import (
|
|
7
|
-
Any,
|
|
8
|
-
Literal,
|
|
9
|
-
Union,
|
|
10
|
-
get_args,
|
|
11
|
-
get_origin,
|
|
12
|
-
get_type_hints,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
from ophyd_async.core import (
|
|
16
|
-
DEFAULT_TIMEOUT,
|
|
17
|
-
Device,
|
|
18
|
-
DeviceVector,
|
|
19
|
-
Signal,
|
|
20
|
-
SoftSignalBackend,
|
|
21
|
-
T,
|
|
22
|
-
)
|
|
23
|
-
from ophyd_async.epics.signal import (
|
|
24
|
-
PvaSignalBackend,
|
|
25
|
-
epics_signal_r,
|
|
26
|
-
epics_signal_rw,
|
|
27
|
-
epics_signal_w,
|
|
28
|
-
epics_signal_x,
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
Access = frozenset[
|
|
32
|
-
Literal["r"] | Literal["w"] | Literal["rw"] | Literal["x"] | Literal["d"]
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def _strip_number_from_string(string: str) -> tuple[str, int | None]:
|
|
37
|
-
match = re.match(r"(.*?)(\d*)$", string)
|
|
38
|
-
assert match
|
|
39
|
-
|
|
40
|
-
name = match.group(1)
|
|
41
|
-
number = match.group(2) or None
|
|
42
|
-
if number is None:
|
|
43
|
-
return name, None
|
|
44
|
-
else:
|
|
45
|
-
return name, int(number)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def _split_subscript(tp: T) -> tuple[Any, tuple[Any]] | tuple[T, None]:
|
|
49
|
-
"""Split a subscripted type into the its origin and args.
|
|
50
|
-
|
|
51
|
-
If `tp` is not a subscripted type, then just return the type and None as args.
|
|
52
|
-
|
|
53
|
-
"""
|
|
54
|
-
if get_origin(tp) is not None:
|
|
55
|
-
return get_origin(tp), get_args(tp)
|
|
56
|
-
|
|
57
|
-
return tp, None
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def _strip_union(field: T | T) -> tuple[T, bool]:
|
|
61
|
-
if get_origin(field) in [Union, types.UnionType]:
|
|
62
|
-
args = get_args(field)
|
|
63
|
-
is_optional = type(None) in args
|
|
64
|
-
for arg in args:
|
|
65
|
-
if arg is not type(None):
|
|
66
|
-
return arg, is_optional
|
|
67
|
-
return field, False
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def _strip_device_vector(field: type[Device]) -> tuple[bool, type[Device]]:
|
|
71
|
-
if get_origin(field) is DeviceVector:
|
|
72
|
-
return True, get_args(field)[0]
|
|
73
|
-
return False, field
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
@dataclass
|
|
77
|
-
class _PVIEntry:
|
|
78
|
-
"""
|
|
79
|
-
A dataclass to represent a single entry in the PVI table.
|
|
80
|
-
This could either be a signal or a sub-table.
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
sub_entries: dict[str, Union[dict[int, "_PVIEntry"], "_PVIEntry"]]
|
|
84
|
-
pvi_pv: str | None = None
|
|
85
|
-
device: Device | None = None
|
|
86
|
-
common_device_type: type[Device] | None = None
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def _verify_common_blocks(entry: _PVIEntry, common_device: type[Device]):
|
|
90
|
-
if not entry.sub_entries:
|
|
91
|
-
return
|
|
92
|
-
common_sub_devices = get_type_hints(common_device)
|
|
93
|
-
for sub_name, sub_device in common_sub_devices.items():
|
|
94
|
-
if sub_name.startswith("_") or sub_name == "parent":
|
|
95
|
-
continue
|
|
96
|
-
assert entry.sub_entries
|
|
97
|
-
device_t, is_optional = _strip_union(sub_device)
|
|
98
|
-
if sub_name not in entry.sub_entries and not is_optional:
|
|
99
|
-
raise RuntimeError(
|
|
100
|
-
f"sub device `{sub_name}:{type(sub_device)}` " "was not provided by pvi"
|
|
101
|
-
)
|
|
102
|
-
if isinstance(entry.sub_entries[sub_name], dict):
|
|
103
|
-
for sub_sub_entry in entry.sub_entries[sub_name].values(): # type: ignore
|
|
104
|
-
_verify_common_blocks(sub_sub_entry, sub_device) # type: ignore
|
|
105
|
-
else:
|
|
106
|
-
_verify_common_blocks(
|
|
107
|
-
entry.sub_entries[sub_name], # type: ignore
|
|
108
|
-
sub_device, # type: ignore
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
_pvi_mapping: dict[frozenset[str], Callable[..., Signal]] = {
|
|
113
|
-
frozenset({"r", "w"}): lambda dtype, read_pv, write_pv: epics_signal_rw(
|
|
114
|
-
dtype, "pva://" + read_pv, "pva://" + write_pv
|
|
115
|
-
),
|
|
116
|
-
frozenset({"rw"}): lambda dtype, read_write_pv: epics_signal_rw(
|
|
117
|
-
dtype, "pva://" + read_write_pv, write_pv="pva://" + read_write_pv
|
|
118
|
-
),
|
|
119
|
-
frozenset({"r"}): lambda dtype, read_pv: epics_signal_r(dtype, "pva://" + read_pv),
|
|
120
|
-
frozenset({"w"}): lambda dtype, write_pv: epics_signal_w(
|
|
121
|
-
dtype, "pva://" + write_pv
|
|
122
|
-
),
|
|
123
|
-
frozenset({"x"}): lambda _, write_pv: epics_signal_x("pva://" + write_pv),
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def _parse_type(
|
|
128
|
-
is_pvi_table: bool,
|
|
129
|
-
number_suffix: int | None,
|
|
130
|
-
common_device_type: type[Device] | None,
|
|
131
|
-
):
|
|
132
|
-
if common_device_type:
|
|
133
|
-
# pre-defined type
|
|
134
|
-
device_cls, _ = _strip_union(common_device_type)
|
|
135
|
-
is_device_vector, device_cls = _strip_device_vector(device_cls)
|
|
136
|
-
device_cls, device_args = _split_subscript(device_cls)
|
|
137
|
-
assert issubclass(device_cls, Device)
|
|
138
|
-
|
|
139
|
-
is_signal = issubclass(device_cls, Signal)
|
|
140
|
-
signal_dtype = device_args[0] if device_args is not None else None
|
|
141
|
-
|
|
142
|
-
elif is_pvi_table:
|
|
143
|
-
# is a block, we can make it a DeviceVector if it ends in a number
|
|
144
|
-
is_device_vector = number_suffix is not None
|
|
145
|
-
is_signal = False
|
|
146
|
-
signal_dtype = None
|
|
147
|
-
device_cls = Device
|
|
148
|
-
else:
|
|
149
|
-
# is a signal, signals aren't stored in DeviceVectors unless
|
|
150
|
-
# they're defined as such in the common_device_type
|
|
151
|
-
is_device_vector = False
|
|
152
|
-
is_signal = True
|
|
153
|
-
signal_dtype = None
|
|
154
|
-
device_cls = Signal
|
|
155
|
-
|
|
156
|
-
return is_device_vector, is_signal, signal_dtype, device_cls
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def _mock_common_blocks(device: Device, stripped_type: type | None = None):
|
|
160
|
-
device_t = stripped_type or type(device)
|
|
161
|
-
sub_devices = (
|
|
162
|
-
(field, field_type)
|
|
163
|
-
for field, field_type in get_type_hints(device_t).items()
|
|
164
|
-
if not field.startswith("_") and field != "parent"
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
for device_name, device_cls in sub_devices:
|
|
168
|
-
device_cls, _ = _strip_union(device_cls)
|
|
169
|
-
is_device_vector, device_cls = _strip_device_vector(device_cls)
|
|
170
|
-
device_cls, device_args = _split_subscript(device_cls)
|
|
171
|
-
assert issubclass(device_cls, Device)
|
|
172
|
-
|
|
173
|
-
signal_dtype = device_args[0] if device_args is not None else None
|
|
174
|
-
|
|
175
|
-
if is_device_vector:
|
|
176
|
-
if issubclass(device_cls, Signal):
|
|
177
|
-
sub_device_1 = device_cls(SoftSignalBackend(signal_dtype))
|
|
178
|
-
sub_device_2 = device_cls(SoftSignalBackend(signal_dtype))
|
|
179
|
-
sub_device = DeviceVector({1: sub_device_1, 2: sub_device_2})
|
|
180
|
-
else:
|
|
181
|
-
if hasattr(device, device_name):
|
|
182
|
-
sub_device = getattr(device, device_name)
|
|
183
|
-
else:
|
|
184
|
-
sub_device = DeviceVector(
|
|
185
|
-
{
|
|
186
|
-
1: device_cls(),
|
|
187
|
-
2: device_cls(),
|
|
188
|
-
}
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
for sub_device_in_vector in sub_device.values():
|
|
192
|
-
_mock_common_blocks(sub_device_in_vector, stripped_type=device_cls)
|
|
193
|
-
|
|
194
|
-
for value in sub_device.values():
|
|
195
|
-
value.parent = sub_device
|
|
196
|
-
else:
|
|
197
|
-
if issubclass(device_cls, Signal):
|
|
198
|
-
sub_device = device_cls(SoftSignalBackend(signal_dtype))
|
|
199
|
-
else:
|
|
200
|
-
sub_device = getattr(device, device_name, device_cls())
|
|
201
|
-
_mock_common_blocks(sub_device, stripped_type=device_cls)
|
|
202
|
-
|
|
203
|
-
setattr(device, device_name, sub_device)
|
|
204
|
-
sub_device.parent = device
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
async def _get_pvi_entries(entry: _PVIEntry, timeout=DEFAULT_TIMEOUT):
|
|
208
|
-
if not entry.pvi_pv or not entry.pvi_pv.endswith(":PVI"):
|
|
209
|
-
raise RuntimeError("Top level entry must be a pvi table")
|
|
210
|
-
|
|
211
|
-
pvi_table_signal_backend: PvaSignalBackend = PvaSignalBackend(
|
|
212
|
-
None, entry.pvi_pv, entry.pvi_pv
|
|
213
|
-
)
|
|
214
|
-
await pvi_table_signal_backend.connect(
|
|
215
|
-
timeout=timeout
|
|
216
|
-
) # create table signal backend
|
|
217
|
-
|
|
218
|
-
pva_table = (await pvi_table_signal_backend.get_value())["pvi"]
|
|
219
|
-
common_device_type_hints = (
|
|
220
|
-
get_type_hints(entry.common_device_type) if entry.common_device_type else {}
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
for sub_name, pva_entries in pva_table.items():
|
|
224
|
-
pvs = list(pva_entries.values())
|
|
225
|
-
is_pvi_table = len(pvs) == 1 and pvs[0].endswith(":PVI")
|
|
226
|
-
sub_name_split, sub_number_split = _strip_number_from_string(sub_name)
|
|
227
|
-
is_device_vector, is_signal, signal_dtype, device_type = _parse_type(
|
|
228
|
-
is_pvi_table,
|
|
229
|
-
sub_number_split,
|
|
230
|
-
common_device_type_hints.get(sub_name_split),
|
|
231
|
-
)
|
|
232
|
-
if is_signal:
|
|
233
|
-
device = _pvi_mapping[frozenset(pva_entries.keys())](signal_dtype, *pvs)
|
|
234
|
-
else:
|
|
235
|
-
device = getattr(entry.device, sub_name, device_type())
|
|
236
|
-
|
|
237
|
-
sub_entry = _PVIEntry(
|
|
238
|
-
device=device, common_device_type=device_type, sub_entries={}
|
|
239
|
-
)
|
|
240
|
-
|
|
241
|
-
if is_device_vector:
|
|
242
|
-
# If device vector then we store sub_name -> {sub_number -> sub_entry}
|
|
243
|
-
# and aggregate into `DeviceVector` in `_set_device_attributes`
|
|
244
|
-
sub_number_split = 1 if sub_number_split is None else sub_number_split
|
|
245
|
-
if sub_name_split not in entry.sub_entries:
|
|
246
|
-
entry.sub_entries[sub_name_split] = {}
|
|
247
|
-
entry.sub_entries[sub_name_split][sub_number_split] = sub_entry # type: ignore
|
|
248
|
-
else:
|
|
249
|
-
entry.sub_entries[sub_name] = sub_entry
|
|
250
|
-
|
|
251
|
-
if is_pvi_table:
|
|
252
|
-
sub_entry.pvi_pv = pvs[0]
|
|
253
|
-
await _get_pvi_entries(sub_entry)
|
|
254
|
-
|
|
255
|
-
if entry.common_device_type:
|
|
256
|
-
_verify_common_blocks(entry, entry.common_device_type)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
def _set_device_attributes(entry: _PVIEntry):
|
|
260
|
-
for sub_name, sub_entry in entry.sub_entries.items():
|
|
261
|
-
if isinstance(sub_entry, dict):
|
|
262
|
-
sub_device = DeviceVector() # type: ignore
|
|
263
|
-
for key, device_vector_sub_entry in sub_entry.items():
|
|
264
|
-
sub_device[key] = device_vector_sub_entry.device
|
|
265
|
-
if device_vector_sub_entry.pvi_pv:
|
|
266
|
-
_set_device_attributes(device_vector_sub_entry)
|
|
267
|
-
# Set the device vector entry to have the device vector as a parent
|
|
268
|
-
device_vector_sub_entry.device.parent = sub_device # type: ignore
|
|
269
|
-
else:
|
|
270
|
-
sub_device = sub_entry.device
|
|
271
|
-
assert sub_device, f"Device of {sub_entry} is None"
|
|
272
|
-
if sub_entry.pvi_pv:
|
|
273
|
-
_set_device_attributes(sub_entry)
|
|
274
|
-
|
|
275
|
-
sub_device.parent = entry.device
|
|
276
|
-
setattr(entry.device, sub_name, sub_device)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
async def fill_pvi_entries(
|
|
280
|
-
device: Device, root_pv: str, timeout=DEFAULT_TIMEOUT, mock=False
|
|
281
|
-
):
|
|
282
|
-
"""
|
|
283
|
-
Fills a ``device`` with signals from a the ``root_pvi:PVI`` table.
|
|
284
|
-
|
|
285
|
-
If the device names match with parent devices of ``device`` then types are used.
|
|
286
|
-
"""
|
|
287
|
-
if mock:
|
|
288
|
-
# set up mock signals for the common annotations
|
|
289
|
-
_mock_common_blocks(device)
|
|
290
|
-
else:
|
|
291
|
-
# check the pvi table for devices and fill the device with them
|
|
292
|
-
root_entry = _PVIEntry(
|
|
293
|
-
pvi_pv=root_pv,
|
|
294
|
-
device=device,
|
|
295
|
-
common_device_type=type(device),
|
|
296
|
-
sub_entries={},
|
|
297
|
-
)
|
|
298
|
-
await _get_pvi_entries(root_entry, timeout=timeout)
|
|
299
|
-
_set_device_attributes(root_entry)
|
|
300
|
-
|
|
301
|
-
# We call set name now the parent field has been set in all of the
|
|
302
|
-
# introspect-initialized devices. This will recursively set the names.
|
|
303
|
-
device.set_name(device.name)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
def create_children_from_annotations(
|
|
307
|
-
device: Device,
|
|
308
|
-
included_optional_fields: tuple[str, ...] = (),
|
|
309
|
-
device_vectors: dict[str, int] | None = None,
|
|
310
|
-
):
|
|
311
|
-
"""For intializing blocks at __init__ of ``device``."""
|
|
312
|
-
for name, device_type in get_type_hints(type(device)).items():
|
|
313
|
-
if name in ("_name", "parent"):
|
|
314
|
-
continue
|
|
315
|
-
device_type, is_optional = _strip_union(device_type)
|
|
316
|
-
if is_optional and name not in included_optional_fields:
|
|
317
|
-
continue
|
|
318
|
-
is_device_vector, device_type = _strip_device_vector(device_type)
|
|
319
|
-
if (
|
|
320
|
-
(is_device_vector and (not device_vectors or name not in device_vectors))
|
|
321
|
-
or ((origin := get_origin(device_type)) and issubclass(origin, Signal))
|
|
322
|
-
or (isclass(device_type) and issubclass(device_type, Signal))
|
|
323
|
-
):
|
|
324
|
-
continue
|
|
325
|
-
|
|
326
|
-
if is_device_vector:
|
|
327
|
-
n_device_vector = DeviceVector(
|
|
328
|
-
{i: device_type() for i in range(1, device_vectors[name] + 1)} # type: ignore
|
|
329
|
-
)
|
|
330
|
-
setattr(device, name, n_device_vector)
|
|
331
|
-
for sub_device in n_device_vector.values():
|
|
332
|
-
create_children_from_annotations(
|
|
333
|
-
sub_device, device_vectors=device_vectors
|
|
334
|
-
)
|
|
335
|
-
else:
|
|
336
|
-
sub_device = device_type()
|
|
337
|
-
setattr(device, name, sub_device)
|
|
338
|
-
create_children_from_annotations(sub_device, device_vectors=device_vectors)
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from ._common import LimitPair, Limits, get_supported_values
|
|
2
|
-
from ._p4p import PvaSignalBackend
|
|
3
|
-
from ._signal import (
|
|
4
|
-
epics_signal_r,
|
|
5
|
-
epics_signal_rw,
|
|
6
|
-
epics_signal_rw_rbv,
|
|
7
|
-
epics_signal_w,
|
|
8
|
-
epics_signal_x,
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
__all__ = [
|
|
12
|
-
"get_supported_values",
|
|
13
|
-
"LimitPair",
|
|
14
|
-
"Limits",
|
|
15
|
-
"PvaSignalBackend",
|
|
16
|
-
"epics_signal_r",
|
|
17
|
-
"epics_signal_rw",
|
|
18
|
-
"epics_signal_rw_rbv",
|
|
19
|
-
"epics_signal_w",
|
|
20
|
-
"epics_signal_x",
|
|
21
|
-
]
|