ophyd-async 0.7.0a1__py3-none-any.whl → 0.8.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.
- ophyd_async/_version.py +2 -2
- ophyd_async/core/__init__.py +23 -8
- ophyd_async/core/_detector.py +5 -10
- ophyd_async/core/_device.py +145 -67
- ophyd_async/core/_device_filler.py +191 -0
- ophyd_async/core/_device_save_loader.py +6 -7
- ophyd_async/core/_mock_signal_backend.py +32 -40
- ophyd_async/core/_mock_signal_utils.py +22 -16
- ophyd_async/core/_protocol.py +28 -8
- ophyd_async/core/_readable.py +5 -5
- ophyd_async/core/_signal.py +140 -152
- ophyd_async/core/_signal_backend.py +131 -64
- ophyd_async/core/_soft_signal_backend.py +125 -194
- ophyd_async/core/_status.py +22 -6
- ophyd_async/core/_table.py +97 -100
- ophyd_async/core/_utils.py +71 -18
- ophyd_async/epics/adaravis/_aravis_controller.py +2 -2
- ophyd_async/epics/adaravis/_aravis_io.py +7 -5
- ophyd_async/epics/adcore/_core_io.py +4 -6
- ophyd_async/epics/adcore/_hdf_writer.py +2 -2
- 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 +3 -4
- ophyd_async/epics/adpilatus/_pilatus_controller.py +2 -2
- ophyd_async/epics/adpilatus/_pilatus_io.py +2 -3
- 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 +7 -8
- ophyd_async/epics/demo/_sensor.py +8 -4
- ophyd_async/epics/eiger/_eiger.py +1 -2
- ophyd_async/epics/eiger/_eiger_controller.py +1 -1
- ophyd_async/epics/eiger/_eiger_io.py +2 -4
- ophyd_async/epics/eiger/_odin_io.py +4 -4
- ophyd_async/epics/pvi/__init__.py +2 -2
- ophyd_async/epics/pvi/_pvi.py +56 -321
- ophyd_async/epics/signal/__init__.py +3 -4
- ophyd_async/epics/signal/_aioca.py +184 -236
- ophyd_async/epics/signal/_common.py +35 -49
- ophyd_async/epics/signal/_p4p.py +254 -387
- ophyd_async/epics/signal/_signal.py +63 -21
- ophyd_async/fastcs/core.py +9 -0
- ophyd_async/fastcs/panda/__init__.py +4 -4
- ophyd_async/fastcs/panda/_block.py +23 -11
- ophyd_async/fastcs/panda/_control.py +3 -5
- ophyd_async/fastcs/panda/_hdf_panda.py +5 -19
- ophyd_async/fastcs/panda/_table.py +29 -51
- ophyd_async/fastcs/panda/_trigger.py +8 -8
- ophyd_async/fastcs/panda/_writer.py +4 -7
- ophyd_async/plan_stubs/_ensure_connected.py +3 -1
- 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/tango/__init__.py +2 -4
- ophyd_async/tango/base_devices/_base_device.py +76 -143
- ophyd_async/tango/demo/_counter.py +2 -2
- ophyd_async/tango/demo/_mover.py +2 -2
- ophyd_async/tango/signal/__init__.py +2 -4
- ophyd_async/tango/signal/_signal.py +29 -50
- ophyd_async/tango/signal/_tango_transport.py +38 -40
- {ophyd_async-0.7.0a1.dist-info → ophyd_async-0.8.0a2.dist-info}/METADATA +8 -12
- ophyd_async-0.8.0a2.dist-info/RECORD +110 -0
- {ophyd_async-0.7.0a1.dist-info → ophyd_async-0.8.0a2.dist-info}/WHEEL +1 -1
- ophyd_async/epics/signal/_epics_transport.py +0 -34
- ophyd_async-0.7.0a1.dist-info/RECORD +0 -108
- {ophyd_async-0.7.0a1.dist-info → ophyd_async-0.8.0a2.dist-info}/LICENSE +0 -0
- {ophyd_async-0.7.0a1.dist-info → ophyd_async-0.8.0a2.dist-info}/entry_points.txt +0 -0
- {ophyd_async-0.7.0a1.dist-info → ophyd_async-0.8.0a2.dist-info}/top_level.txt +0 -0
|
@@ -1,21 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
4
|
-
|
|
5
|
-
get_args,
|
|
6
|
-
get_origin,
|
|
7
|
-
get_type_hints,
|
|
8
|
-
)
|
|
3
|
+
from typing import TypeVar
|
|
4
|
+
from unittest.mock import Mock
|
|
9
5
|
|
|
10
|
-
from ophyd_async.core import
|
|
11
|
-
DEFAULT_TIMEOUT,
|
|
12
|
-
Device,
|
|
13
|
-
Signal,
|
|
14
|
-
)
|
|
6
|
+
from ophyd_async.core import Device, DeviceConnector, DeviceFiller
|
|
15
7
|
from ophyd_async.tango.signal import (
|
|
16
8
|
TangoSignalBackend,
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
infer_python_type,
|
|
10
|
+
infer_signal_type,
|
|
19
11
|
)
|
|
20
12
|
from tango import DeviceProxy as DeviceProxy
|
|
21
13
|
from tango.asyncio import DeviceProxy as AsyncDeviceProxy
|
|
@@ -50,64 +42,14 @@ class TangoDevice(Device):
|
|
|
50
42
|
device_proxy: DeviceProxy | None = None,
|
|
51
43
|
name: str = "",
|
|
52
44
|
) -> None:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
raise ValueError("TRL must be a string.")
|
|
62
|
-
self.trl = trl
|
|
63
|
-
|
|
64
|
-
async def connect(
|
|
65
|
-
self,
|
|
66
|
-
mock: bool = False,
|
|
67
|
-
timeout: float = DEFAULT_TIMEOUT,
|
|
68
|
-
force_reconnect: bool = False,
|
|
69
|
-
):
|
|
70
|
-
if self.trl and self.proxy is None:
|
|
71
|
-
self.proxy = await AsyncDeviceProxy(self.trl)
|
|
72
|
-
elif self.proxy and not self.trl:
|
|
73
|
-
self.trl = self.proxy.name()
|
|
74
|
-
|
|
75
|
-
# Set the trl of the signal backends
|
|
76
|
-
for child in self.children():
|
|
77
|
-
if isinstance(child[1], Signal):
|
|
78
|
-
if isinstance(child[1]._backend, TangoSignalBackend): # noqa: SLF001
|
|
79
|
-
resource_name = child[0].lstrip("_")
|
|
80
|
-
read_trl = f"{self.trl}/{resource_name}"
|
|
81
|
-
child[1]._backend.set_trl(read_trl, read_trl) # noqa: SLF001
|
|
82
|
-
|
|
83
|
-
if self.proxy is not None:
|
|
84
|
-
self.register_signals()
|
|
85
|
-
await _fill_proxy_entries(self)
|
|
86
|
-
|
|
87
|
-
# set_name should be called again to propagate the new signal names
|
|
88
|
-
self.set_name(self.name)
|
|
89
|
-
|
|
90
|
-
# Set the polling configuration
|
|
91
|
-
if self._polling[0]:
|
|
92
|
-
for child in self.children():
|
|
93
|
-
child_type = type(child[1])
|
|
94
|
-
if issubclass(child_type, Signal):
|
|
95
|
-
if isinstance(child[1]._backend, TangoSignalBackend): # noqa: SLF001 # type: ignore
|
|
96
|
-
child[1]._backend.set_polling(*self._polling) # noqa: SLF001 # type: ignore
|
|
97
|
-
child[1]._backend.allow_events(False) # noqa: SLF001 # type: ignore
|
|
98
|
-
if self._signal_polling:
|
|
99
|
-
for signal_name, polling in self._signal_polling.items():
|
|
100
|
-
if hasattr(self, signal_name):
|
|
101
|
-
attr = getattr(self, signal_name)
|
|
102
|
-
if isinstance(attr._backend, TangoSignalBackend): # noqa: SLF001
|
|
103
|
-
attr._backend.set_polling(*polling) # noqa: SLF001
|
|
104
|
-
attr._backend.allow_events(False) # noqa: SLF001
|
|
105
|
-
|
|
106
|
-
await super().connect(mock=mock, timeout=timeout)
|
|
107
|
-
|
|
108
|
-
# Users can override this method to register new signals
|
|
109
|
-
def register_signals(self):
|
|
110
|
-
pass
|
|
45
|
+
connector = TangoDeviceConnector(
|
|
46
|
+
trl=trl,
|
|
47
|
+
device_proxy=device_proxy,
|
|
48
|
+
polling=self._polling,
|
|
49
|
+
signal_polling=self._signal_polling,
|
|
50
|
+
)
|
|
51
|
+
connector.create_children_from_annotations(self)
|
|
52
|
+
super().__init__(name=name, connector=connector)
|
|
111
53
|
|
|
112
54
|
|
|
113
55
|
def tango_polling(
|
|
@@ -150,76 +92,67 @@ def tango_polling(
|
|
|
150
92
|
return decorator
|
|
151
93
|
|
|
152
94
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
95
|
+
class TangoDeviceConnector(DeviceConnector):
|
|
96
|
+
def __init__(
|
|
97
|
+
self,
|
|
98
|
+
trl: str | None,
|
|
99
|
+
device_proxy: DeviceProxy | None,
|
|
100
|
+
polling: tuple[bool, float, float | None, float | None],
|
|
101
|
+
signal_polling: dict[str, tuple[bool, float, float, float]],
|
|
102
|
+
) -> None:
|
|
103
|
+
self.trl = trl
|
|
104
|
+
self.proxy = device_proxy
|
|
105
|
+
self._polling = polling
|
|
106
|
+
self._signal_polling = signal_polling
|
|
107
|
+
|
|
108
|
+
def create_children_from_annotations(self, device: Device):
|
|
109
|
+
self._filler = DeviceFiller(
|
|
110
|
+
device=device,
|
|
111
|
+
signal_backend_factory=TangoSignalBackend,
|
|
112
|
+
device_connector_factory=lambda: TangoDeviceConnector(
|
|
113
|
+
None, None, (False, 0.1, None, None), {}
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
async def connect(
|
|
118
|
+
self, device: Device, mock: bool | Mock, timeout: float, force_reconnect: bool
|
|
119
|
+
) -> None:
|
|
120
|
+
if mock:
|
|
121
|
+
# Make 2 entries for each DeviceVector
|
|
122
|
+
self._filler.make_soft_device_vector_entries(2)
|
|
123
|
+
else:
|
|
124
|
+
if self.trl and self.proxy is None:
|
|
125
|
+
self.proxy = await AsyncDeviceProxy(self.trl)
|
|
126
|
+
elif self.proxy and not self.trl:
|
|
127
|
+
self.trl = self.proxy.name()
|
|
128
|
+
else:
|
|
129
|
+
raise TypeError("Neither proxy nor trl supplied")
|
|
130
|
+
|
|
131
|
+
children = sorted(
|
|
132
|
+
set()
|
|
133
|
+
.union(self.proxy.get_attribute_list())
|
|
134
|
+
.union(self.proxy.get_command_list())
|
|
135
|
+
)
|
|
136
|
+
for name in children:
|
|
137
|
+
# TODO: strip attribute name
|
|
138
|
+
full_trl = f"{self.trl}/{name}"
|
|
139
|
+
signal_type = await infer_signal_type(full_trl, self.proxy)
|
|
140
|
+
if signal_type:
|
|
141
|
+
backend = self._filler.make_child_signal(name, signal_type)
|
|
142
|
+
backend.datatype = await infer_python_type(full_trl, self.proxy)
|
|
143
|
+
backend.set_trl(full_trl)
|
|
144
|
+
if polling := self._signal_polling.get(name, ()):
|
|
145
|
+
backend.set_polling(*polling)
|
|
146
|
+
backend.allow_events(False)
|
|
147
|
+
elif self._polling[0]:
|
|
148
|
+
backend.set_polling(*self._polling)
|
|
149
|
+
backend.allow_events(False)
|
|
150
|
+
# Check that all the requested children have been created
|
|
151
|
+
if unfilled := self._filler.unfilled():
|
|
152
|
+
raise RuntimeError(
|
|
153
|
+
f"{device.name}: cannot provision {unfilled} from "
|
|
154
|
+
f"{self.trl}: {children}"
|
|
200
155
|
)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
print(
|
|
205
|
-
f"Skipping {name}. Commands with different in and out dtypes"
|
|
206
|
-
f" are not supported."
|
|
207
|
-
)
|
|
208
|
-
continue
|
|
209
|
-
raise e
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
# def _strip_union(field: T | T) -> tuple[T, bool]:
|
|
213
|
-
# if get_origin(field) is Union:
|
|
214
|
-
# args = get_args(field)
|
|
215
|
-
# is_optional = type(None) in args
|
|
216
|
-
# for arg in args:
|
|
217
|
-
# if arg is not type(None):
|
|
218
|
-
# return arg, is_optional
|
|
219
|
-
# return field, False
|
|
220
|
-
#
|
|
221
|
-
#
|
|
222
|
-
# def _strip_device_vector(field: type[Device]) -> tuple[bool, type[Device]]:
|
|
223
|
-
# if get_origin(field) is DeviceVector:
|
|
224
|
-
# return True, get_args(field)[0]
|
|
225
|
-
# return False, field
|
|
156
|
+
# Set the name of the device to name all children
|
|
157
|
+
device.set_name(device.name)
|
|
158
|
+
return await super().connect(device, mock, timeout, force_reconnect)
|
|
@@ -19,7 +19,7 @@ class TangoCounter(TangoReadable):
|
|
|
19
19
|
counts: SignalR[int]
|
|
20
20
|
sample_time: SignalRW[float]
|
|
21
21
|
start: SignalX
|
|
22
|
-
|
|
22
|
+
reset_: SignalX
|
|
23
23
|
|
|
24
24
|
def __init__(self, trl: str | None = "", name=""):
|
|
25
25
|
super().__init__(trl, name=name)
|
|
@@ -34,4 +34,4 @@ class TangoCounter(TangoReadable):
|
|
|
34
34
|
|
|
35
35
|
@AsyncStatus.wrap
|
|
36
36
|
async def reset(self) -> None:
|
|
37
|
-
await self.
|
|
37
|
+
await self.reset_.trigger(wait=True, timeout=DEFAULT_TIMEOUT)
|
ophyd_async/tango/demo/_mover.py
CHANGED
|
@@ -29,7 +29,7 @@ class TangoMover(TangoReadable, Movable, Stoppable):
|
|
|
29
29
|
position: SignalRW[float]
|
|
30
30
|
velocity: SignalRW[float]
|
|
31
31
|
state: SignalR[DevState]
|
|
32
|
-
|
|
32
|
+
stop_: SignalX
|
|
33
33
|
|
|
34
34
|
def __init__(self, trl: str | None = "", name=""):
|
|
35
35
|
super().__init__(trl, name=name)
|
|
@@ -74,4 +74,4 @@ class TangoMover(TangoReadable, Movable, Stoppable):
|
|
|
74
74
|
|
|
75
75
|
def stop(self, success: bool = True) -> AsyncStatus:
|
|
76
76
|
self._set_success = success
|
|
77
|
-
return self.
|
|
77
|
+
return self.stop_.trigger()
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from ._signal import (
|
|
2
|
-
__tango_signal_auto,
|
|
3
2
|
infer_python_type,
|
|
4
|
-
|
|
3
|
+
infer_signal_type,
|
|
5
4
|
make_backend,
|
|
6
5
|
tango_signal_r,
|
|
7
6
|
tango_signal_rw,
|
|
@@ -29,11 +28,10 @@ __all__ = (
|
|
|
29
28
|
"get_trl_descriptor",
|
|
30
29
|
"get_tango_trl",
|
|
31
30
|
"infer_python_type",
|
|
32
|
-
"
|
|
31
|
+
"infer_signal_type",
|
|
33
32
|
"make_backend",
|
|
34
33
|
"tango_signal_r",
|
|
35
34
|
"tango_signal_rw",
|
|
36
35
|
"tango_signal_w",
|
|
37
36
|
"tango_signal_x",
|
|
38
|
-
"__tango_signal_auto",
|
|
39
37
|
)
|
|
@@ -2,21 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import logging
|
|
5
6
|
from enum import Enum, IntEnum
|
|
6
7
|
|
|
7
8
|
import numpy.typing as npt
|
|
8
9
|
|
|
9
|
-
from ophyd_async.core import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
from ophyd_async.core import (
|
|
11
|
+
DEFAULT_TIMEOUT,
|
|
12
|
+
Signal,
|
|
13
|
+
SignalDatatypeT,
|
|
14
|
+
SignalR,
|
|
15
|
+
SignalRW,
|
|
16
|
+
SignalW,
|
|
17
|
+
SignalX,
|
|
13
18
|
)
|
|
14
19
|
from tango import AttrDataFormat, AttrWriteType, CmdArgType, DeviceProxy, DevState
|
|
15
20
|
from tango.asyncio import DeviceProxy as AsyncDeviceProxy
|
|
16
21
|
|
|
22
|
+
from ._tango_transport import TangoSignalBackend, get_python_type
|
|
23
|
+
|
|
17
24
|
|
|
18
25
|
def make_backend(
|
|
19
|
-
datatype: type[
|
|
26
|
+
datatype: type[SignalDatatypeT] | None,
|
|
20
27
|
read_trl: str = "",
|
|
21
28
|
write_trl: str = "",
|
|
22
29
|
device_proxy: DeviceProxy | None = None,
|
|
@@ -25,13 +32,13 @@ def make_backend(
|
|
|
25
32
|
|
|
26
33
|
|
|
27
34
|
def tango_signal_rw(
|
|
28
|
-
datatype: type[
|
|
35
|
+
datatype: type[SignalDatatypeT],
|
|
29
36
|
read_trl: str,
|
|
30
37
|
write_trl: str = "",
|
|
31
38
|
device_proxy: DeviceProxy | None = None,
|
|
32
39
|
timeout: float = DEFAULT_TIMEOUT,
|
|
33
40
|
name: str = "",
|
|
34
|
-
) -> SignalRW[
|
|
41
|
+
) -> SignalRW[SignalDatatypeT]:
|
|
35
42
|
"""Create a `SignalRW` backed by 1 or 2 Tango Attribute/Command
|
|
36
43
|
|
|
37
44
|
Parameters
|
|
@@ -54,12 +61,12 @@ def tango_signal_rw(
|
|
|
54
61
|
|
|
55
62
|
|
|
56
63
|
def tango_signal_r(
|
|
57
|
-
datatype: type[
|
|
64
|
+
datatype: type[SignalDatatypeT],
|
|
58
65
|
read_trl: str,
|
|
59
66
|
device_proxy: DeviceProxy | None = None,
|
|
60
67
|
timeout: float = DEFAULT_TIMEOUT,
|
|
61
68
|
name: str = "",
|
|
62
|
-
) -> SignalR[
|
|
69
|
+
) -> SignalR[SignalDatatypeT]:
|
|
63
70
|
"""Create a `SignalR` backed by 1 Tango Attribute/Command
|
|
64
71
|
|
|
65
72
|
Parameters
|
|
@@ -80,12 +87,12 @@ def tango_signal_r(
|
|
|
80
87
|
|
|
81
88
|
|
|
82
89
|
def tango_signal_w(
|
|
83
|
-
datatype: type[
|
|
90
|
+
datatype: type[SignalDatatypeT],
|
|
84
91
|
write_trl: str,
|
|
85
92
|
device_proxy: DeviceProxy | None = None,
|
|
86
93
|
timeout: float = DEFAULT_TIMEOUT,
|
|
87
94
|
name: str = "",
|
|
88
|
-
) -> SignalW[
|
|
95
|
+
) -> SignalW[SignalDatatypeT]:
|
|
89
96
|
"""Create a `SignalW` backed by 1 Tango Attribute/Command
|
|
90
97
|
|
|
91
98
|
Parameters
|
|
@@ -128,39 +135,10 @@ def tango_signal_x(
|
|
|
128
135
|
return SignalX(backend, timeout=timeout, name=name)
|
|
129
136
|
|
|
130
137
|
|
|
131
|
-
async def __tango_signal_auto(
|
|
132
|
-
datatype: type[T] | None = None,
|
|
133
|
-
*,
|
|
134
|
-
trl: str,
|
|
135
|
-
device_proxy: DeviceProxy | None,
|
|
136
|
-
timeout: float = DEFAULT_TIMEOUT,
|
|
137
|
-
name: str = "",
|
|
138
|
-
) -> SignalW | SignalX | SignalR | SignalRW | None:
|
|
139
|
-
try:
|
|
140
|
-
signal_character = await infer_signal_character(trl, device_proxy)
|
|
141
|
-
except RuntimeError as e:
|
|
142
|
-
if "Commands with different in and out dtypes" in str(e):
|
|
143
|
-
return None
|
|
144
|
-
else:
|
|
145
|
-
raise e
|
|
146
|
-
|
|
147
|
-
if datatype is None:
|
|
148
|
-
datatype = await infer_python_type(trl, device_proxy)
|
|
149
|
-
|
|
150
|
-
backend = make_backend(datatype, trl, trl, device_proxy)
|
|
151
|
-
if signal_character == "RW":
|
|
152
|
-
return SignalRW(backend=backend, timeout=timeout, name=name)
|
|
153
|
-
if signal_character == "R":
|
|
154
|
-
return SignalR(backend=backend, timeout=timeout, name=name)
|
|
155
|
-
if signal_character == "W":
|
|
156
|
-
return SignalW(backend=backend, timeout=timeout, name=name)
|
|
157
|
-
if signal_character == "X":
|
|
158
|
-
return SignalX(backend=backend, timeout=timeout, name=name)
|
|
159
|
-
|
|
160
|
-
|
|
161
138
|
async def infer_python_type(
|
|
162
139
|
trl: str = "", proxy: DeviceProxy | None = None
|
|
163
140
|
) -> object | npt.NDArray | type[DevState] | IntEnum:
|
|
141
|
+
# TODO: work out if this is still needed
|
|
164
142
|
device_trl, tr_name = trl.rsplit("/", 1)
|
|
165
143
|
if proxy is None:
|
|
166
144
|
dev_proxy = await AsyncDeviceProxy(device_trl)
|
|
@@ -187,7 +165,9 @@ async def infer_python_type(
|
|
|
187
165
|
return npt.NDArray[py_type] if isarray else py_type
|
|
188
166
|
|
|
189
167
|
|
|
190
|
-
async def
|
|
168
|
+
async def infer_signal_type(
|
|
169
|
+
trl, proxy: DeviceProxy | None = None
|
|
170
|
+
) -> type[Signal] | None:
|
|
191
171
|
device_trl, tr_name = trl.rsplit("/", 1)
|
|
192
172
|
if proxy is None:
|
|
193
173
|
dev_proxy = await AsyncDeviceProxy(device_trl)
|
|
@@ -204,20 +184,19 @@ async def infer_signal_character(trl, proxy: DeviceProxy | None = None) -> str:
|
|
|
204
184
|
if tr_name in dev_proxy.get_attribute_list():
|
|
205
185
|
config = await dev_proxy.get_attribute_config(tr_name)
|
|
206
186
|
if config.writable in [AttrWriteType.READ_WRITE, AttrWriteType.READ_WITH_WRITE]:
|
|
207
|
-
return
|
|
187
|
+
return SignalRW
|
|
208
188
|
elif config.writable == AttrWriteType.READ:
|
|
209
|
-
return
|
|
189
|
+
return SignalR
|
|
210
190
|
else:
|
|
211
|
-
return
|
|
191
|
+
return SignalW
|
|
212
192
|
|
|
213
193
|
if tr_name in dev_proxy.get_command_list():
|
|
214
194
|
config = await dev_proxy.get_command_config(tr_name)
|
|
215
195
|
if config.in_type == CmdArgType.DevVoid:
|
|
216
|
-
return
|
|
196
|
+
return SignalX
|
|
217
197
|
elif config.in_type != config.out_type:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
)
|
|
198
|
+
logging.debug("Commands with different in and out dtypes are not supported")
|
|
199
|
+
return None
|
|
221
200
|
else:
|
|
222
|
-
return
|
|
201
|
+
return SignalRW
|
|
223
202
|
raise RuntimeError(f"Unable to infer signal character for {trl}")
|