ophyd-async 0.2.0__py3-none-any.whl → 0.3a1__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 (32) hide show
  1. ophyd_async/_version.py +2 -2
  2. ophyd_async/core/__init__.py +5 -9
  3. ophyd_async/core/_providers.py +36 -5
  4. ophyd_async/core/async_status.py +3 -3
  5. ophyd_async/core/detector.py +159 -37
  6. ophyd_async/core/device.py +37 -38
  7. ophyd_async/core/device_save_loader.py +96 -23
  8. ophyd_async/core/flyer.py +32 -237
  9. ophyd_async/core/signal.py +11 -4
  10. ophyd_async/core/signal_backend.py +2 -2
  11. ophyd_async/core/sim_signal_backend.py +2 -2
  12. ophyd_async/core/utils.py +75 -29
  13. ophyd_async/epics/_backend/_aioca.py +18 -26
  14. ophyd_async/epics/_backend/_p4p.py +58 -27
  15. ophyd_async/epics/_backend/common.py +20 -0
  16. ophyd_async/epics/areadetector/controllers/ad_sim_controller.py +1 -1
  17. ophyd_async/epics/areadetector/controllers/pilatus_controller.py +1 -1
  18. ophyd_async/epics/areadetector/writers/_hdffile.py +17 -3
  19. ophyd_async/epics/areadetector/writers/hdf_writer.py +21 -15
  20. ophyd_async/epics/pvi.py +70 -0
  21. ophyd_async/epics/signal/__init__.py +0 -2
  22. ophyd_async/panda/__init__.py +5 -2
  23. ophyd_async/panda/panda.py +41 -94
  24. ophyd_async/panda/panda_controller.py +41 -0
  25. ophyd_async/panda/utils.py +15 -0
  26. {ophyd_async-0.2.0.dist-info → ophyd_async-0.3a1.dist-info}/METADATA +2 -2
  27. {ophyd_async-0.2.0.dist-info → ophyd_async-0.3a1.dist-info}/RECORD +31 -28
  28. {ophyd_async-0.2.0.dist-info → ophyd_async-0.3a1.dist-info}/WHEEL +1 -1
  29. ophyd_async/epics/signal/pvi_get.py +0 -22
  30. {ophyd_async-0.2.0.dist-info → ophyd_async-0.3a1.dist-info}/LICENSE +0 -0
  31. {ophyd_async-0.2.0.dist-info → ophyd_async-0.3a1.dist-info}/entry_points.txt +0 -0
  32. {ophyd_async-0.2.0.dist-info → ophyd_async-0.3a1.dist-info}/top_level.txt +0 -0
@@ -1,24 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
- import atexit
4
3
  import re
5
- from typing import (
6
- Callable,
7
- Dict,
8
- FrozenSet,
9
- Optional,
10
- Tuple,
11
- Type,
12
- TypedDict,
13
- cast,
14
- get_args,
15
- get_origin,
16
- get_type_hints,
17
- )
18
-
19
- from p4p.client.thread import Context
4
+ from typing import Dict, Optional, Tuple, cast, get_args, get_origin, get_type_hints
20
5
 
21
6
  from ophyd_async.core import (
7
+ DEFAULT_TIMEOUT,
22
8
  Device,
23
9
  DeviceVector,
24
10
  Signal,
@@ -28,13 +14,7 @@ from ophyd_async.core import (
28
14
  SignalX,
29
15
  SimSignalBackend,
30
16
  )
31
- from ophyd_async.epics.signal import (
32
- epics_signal_r,
33
- epics_signal_rw,
34
- epics_signal_w,
35
- epics_signal_x,
36
- pvi_get,
37
- )
17
+ from ophyd_async.epics.pvi import PVIEntry, make_signal, pvi_get
38
18
  from ophyd_async.panda.table import SeqTable
39
19
 
40
20
 
@@ -50,14 +30,7 @@ class SeqBlock(Device):
50
30
 
51
31
  class PcapBlock(Device):
52
32
  active: SignalR[bool]
53
-
54
-
55
- class PVIEntry(TypedDict, total=False):
56
- d: str
57
- r: str
58
- rw: str
59
- w: str
60
- x: str
33
+ arm: SignalRW[bool]
61
34
 
62
35
 
63
36
  def _block_name_number(block_name: str) -> Tuple[str, Optional[int]]:
@@ -78,7 +51,7 @@ def _block_name_number(block_name: str) -> Tuple[str, Optional[int]]:
78
51
  return block_name, None
79
52
 
80
53
 
81
- def _remove_inconsistent_blocks(pvi_info: Dict[str, PVIEntry]) -> None:
54
+ def _remove_inconsistent_blocks(pvi_info: Optional[Dict[str, PVIEntry]]) -> None:
82
55
  """Remove blocks from pvi information.
83
56
 
84
57
  This is needed because some pandas have 'pcap' and 'pcap1' blocks, which are
@@ -86,6 +59,8 @@ def _remove_inconsistent_blocks(pvi_info: Dict[str, PVIEntry]) -> None:
86
59
  for example.
87
60
 
88
61
  """
62
+ if pvi_info is None:
63
+ return
89
64
  pvi_keys = set(pvi_info.keys())
90
65
  for k in pvi_keys:
91
66
  kn = re.sub(r"\d*$", "", k)
@@ -93,44 +68,14 @@ def _remove_inconsistent_blocks(pvi_info: Dict[str, PVIEntry]) -> None:
93
68
  del pvi_info[k]
94
69
 
95
70
 
96
- async def pvi(pv: str, ctxt: Context, timeout: float = 5.0) -> Dict[str, PVIEntry]:
97
- result = await pvi_get(pv, ctxt, timeout=timeout)
98
- _remove_inconsistent_blocks(result)
99
- return result
100
-
101
-
102
71
  class PandA(Device):
103
- _ctxt: Optional[Context] = None
104
-
105
72
  pulse: DeviceVector[PulseBlock]
106
73
  seq: DeviceVector[SeqBlock]
107
74
  pcap: PcapBlock
108
75
 
109
- def __init__(self, pv: str) -> None:
110
- self._init_prefix = pv
111
- self.pvi_mapping: Dict[FrozenSet[str], Callable[..., Signal]] = {
112
- frozenset({"r", "w"}): lambda dtype, rpv, wpv: epics_signal_rw(
113
- dtype, rpv, wpv
114
- ),
115
- frozenset({"rw"}): lambda dtype, rpv, wpv: epics_signal_rw(dtype, rpv, wpv),
116
- frozenset({"r"}): lambda dtype, rpv, wpv: epics_signal_r(dtype, rpv),
117
- frozenset({"w"}): lambda dtype, rpv, wpv: epics_signal_w(dtype, wpv),
118
- frozenset({"x"}): lambda dtype, rpv, wpv: epics_signal_x(wpv),
119
- }
120
-
121
- @property
122
- def ctxt(self) -> Context:
123
- if PandA._ctxt is None:
124
- PandA._ctxt = Context("pva", nt=False)
125
-
126
- @atexit.register
127
- def _del_ctxt():
128
- # If we don't do this we get messages like this on close:
129
- # Error in sys.excepthook:
130
- # Original exception was:
131
- PandA._ctxt = None
132
-
133
- return PandA._ctxt
76
+ def __init__(self, prefix: str, name: str = "") -> None:
77
+ super().__init__(name)
78
+ self._prefix = prefix
134
79
 
135
80
  def verify_block(self, name: str, num: Optional[int]):
136
81
  """Given a block name and number, return information about a block."""
@@ -148,7 +93,12 @@ class PandA(Device):
148
93
  return block
149
94
 
150
95
  async def _make_block(
151
- self, name: str, num: Optional[int], block_pv: str, sim: bool = False
96
+ self,
97
+ name: str,
98
+ num: Optional[int],
99
+ block_pv: str,
100
+ sim: bool = False,
101
+ timeout: float = DEFAULT_TIMEOUT,
152
102
  ):
153
103
  """Makes a block given a block name containing relevant signals.
154
104
 
@@ -158,7 +108,7 @@ class PandA(Device):
158
108
  block = self.verify_block(name, num)
159
109
 
160
110
  field_annos = get_type_hints(block, globalns=globals())
161
- block_pvi = await pvi(block_pv, self.ctxt) if not sim else None
111
+ block_pvi = await pvi_get(block_pv, timeout=timeout) if not sim else None
162
112
 
163
113
  # finds which fields this class actually has, e.g. delay, width...
164
114
  for sig_name, sig_type in field_annos.items():
@@ -167,7 +117,6 @@ class PandA(Device):
167
117
 
168
118
  # if not in sim mode,
169
119
  if block_pvi:
170
- block_pvi = cast(Dict[str, PVIEntry], block_pvi)
171
120
  # try to get this block in the pvi.
172
121
  entry: Optional[PVIEntry] = block_pvi.get(sig_name)
173
122
  if entry is None:
@@ -176,7 +125,7 @@ class PandA(Device):
176
125
  + f"an {sig_name} signal which has not been retrieved by PVI."
177
126
  )
178
127
 
179
- signal = self._make_signal(entry, args[0] if len(args) > 0 else None)
128
+ signal: Signal = make_signal(entry, args[0] if len(args) > 0 else None)
180
129
 
181
130
  else:
182
131
  backend: SignalBackend = SimSignalBackend(
@@ -191,40 +140,26 @@ class PandA(Device):
191
140
  for attr, attr_pvi in block_pvi.items():
192
141
  if not hasattr(block, attr):
193
142
  # makes any extra signals
194
- signal = self._make_signal(attr_pvi)
195
- setattr(block, attr, signal)
143
+ setattr(block, attr, make_signal(attr_pvi))
196
144
 
197
145
  return block
198
146
 
199
- async def _make_untyped_block(self, block_pv: str):
147
+ async def _make_untyped_block(
148
+ self, block_pv: str, timeout: float = DEFAULT_TIMEOUT
149
+ ):
200
150
  """Populates a block using PVI information.
201
151
 
202
152
  This block is not typed as part of the PandA interface but needs to be
203
153
  included dynamically anyway.
204
154
  """
205
155
  block = Device()
206
- block_pvi: Dict[str, PVIEntry] = await pvi(block_pv, self.ctxt)
156
+ block_pvi: Dict[str, PVIEntry] = await pvi_get(block_pv, timeout=timeout)
207
157
 
208
158
  for signal_name, signal_pvi in block_pvi.items():
209
- signal = self._make_signal(signal_pvi)
210
- setattr(block, signal_name, signal)
159
+ setattr(block, signal_name, make_signal(signal_pvi))
211
160
 
212
161
  return block
213
162
 
214
- def _make_signal(self, signal_pvi: PVIEntry, dtype: Optional[Type] = None):
215
- """Make a signal.
216
-
217
- This assumes datatype is None so it can be used to create dynamic signals.
218
- """
219
- operations = frozenset(signal_pvi.keys())
220
- pvs = [signal_pvi[i] for i in operations] # type: ignore
221
- signal_factory = self.pvi_mapping[operations]
222
-
223
- write_pv = pvs[0]
224
- read_pv = write_pv if len(pvs) == 1 else pvs[1]
225
-
226
- return signal_factory(dtype, "pva://" + read_pv, "pva://" + write_pv)
227
-
228
163
  # TODO redo to set_panda_block? confusing name
229
164
  def set_attribute(self, name: str, num: Optional[int], block: Device):
230
165
  """Set a block on the panda.
@@ -241,7 +176,9 @@ class PandA(Device):
241
176
  else:
242
177
  setattr(self, name, block)
243
178
 
244
- async def connect(self, sim=False) -> None:
179
+ async def connect(
180
+ self, sim: bool = False, timeout: float = DEFAULT_TIMEOUT
181
+ ) -> None:
245
182
  """Initialises all blocks and connects them.
246
183
 
247
184
  First, checks for pvi information. If it exists, make all blocks from this.
@@ -250,7 +187,11 @@ class PandA(Device):
250
187
  If there's no pvi information, that's because we're in sim mode. In that case,
251
188
  makes all required blocks.
252
189
  """
253
- pvi_info = await pvi(self._init_prefix + ":PVI", self.ctxt) if not sim else None
190
+ pvi_info = (
191
+ await pvi_get(self._prefix + "PVI", timeout=timeout) if not sim else None
192
+ )
193
+ _remove_inconsistent_blocks(pvi_info)
194
+
254
195
  hints = {
255
196
  attr_name: attr_type
256
197
  for attr_name, attr_type in get_type_hints(self, globalns=globals()).items()
@@ -264,9 +205,13 @@ class PandA(Device):
264
205
  name, num = _block_name_number(block_name)
265
206
 
266
207
  if name in hints:
267
- block = await self._make_block(name, num, block_pvi["d"])
208
+ block = await self._make_block(
209
+ name, num, block_pvi["d"], timeout=timeout
210
+ )
268
211
  else:
269
- block = await self._make_untyped_block(block_pvi["d"])
212
+ block = await self._make_untyped_block(
213
+ block_pvi["d"], timeout=timeout
214
+ )
270
215
 
271
216
  self.set_attribute(name, num, block)
272
217
 
@@ -287,7 +232,9 @@ class PandA(Device):
287
232
  ], f"Expected PandA to only contain blocks, got {entry}"
288
233
  else:
289
234
  num = 1 if get_origin(hints[block_name]) == DeviceVector else None
290
- block = await self._make_block(block_name, num, "sim://", sim=sim)
235
+ block = await self._make_block(
236
+ block_name, num, "sim://", sim=sim, timeout=timeout
237
+ )
291
238
  self.set_attribute(block_name, num, block)
292
239
 
293
240
  self.set_name(self.name)
@@ -0,0 +1,41 @@
1
+ import asyncio
2
+ from typing import Optional
3
+
4
+ from ophyd_async.core import (
5
+ AsyncStatus,
6
+ DetectorControl,
7
+ DetectorTrigger,
8
+ wait_for_value,
9
+ )
10
+
11
+ from .panda import PcapBlock
12
+
13
+
14
+ class PandaPcapController(DetectorControl):
15
+ def __init__(
16
+ self,
17
+ pcap: PcapBlock,
18
+ ) -> None:
19
+ self.pcap = pcap
20
+
21
+ def get_deadtime(self, exposure: float) -> float:
22
+ return 0.000000008
23
+
24
+ async def arm(
25
+ self,
26
+ num: int,
27
+ trigger: DetectorTrigger = DetectorTrigger.constant_gate,
28
+ exposure: Optional[float] = None,
29
+ ) -> AsyncStatus:
30
+ assert trigger in (
31
+ DetectorTrigger.constant_gate,
32
+ trigger == DetectorTrigger.variable_gate,
33
+ ), "Only constant_gate and variable_gate triggering is supported on the PandA"
34
+ await asyncio.gather(self.pcap.arm.set(True))
35
+ await wait_for_value(self.pcap.active, True, timeout=1)
36
+ return AsyncStatus(wait_for_value(self.pcap.active, False, timeout=None))
37
+
38
+ async def disarm(self):
39
+ await asyncio.gather(self.pcap.arm.set(False))
40
+ await wait_for_value(self.pcap.active, False, timeout=1)
41
+ return AsyncStatus(wait_for_value(self.pcap.active, False, timeout=None))
@@ -0,0 +1,15 @@
1
+ from typing import Any, Dict, Sequence
2
+
3
+
4
+ def phase_sorter(panda_signal_values: Dict[str, Any]) -> Sequence[Dict[str, Any]]:
5
+ # Panda has two load phases. If the signal name ends in the string "UNITS",
6
+ # it needs to be loaded first so put in first phase
7
+ phase_1, phase_2 = {}, {}
8
+
9
+ for key, value in panda_signal_values.items():
10
+ if key.endswith("units"):
11
+ phase_1[key] = value
12
+ else:
13
+ phase_2[key] = value
14
+
15
+ return [phase_1, phase_2]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ophyd-async
3
- Version: 0.2.0
3
+ Version: 0.3a1
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
@@ -45,7 +45,7 @@ Requires-Dist: networkx >=2.0
45
45
  Requires-Dist: numpy
46
46
  Requires-Dist: packaging
47
47
  Requires-Dist: pint
48
- Requires-Dist: bluesky
48
+ Requires-Dist: bluesky >=1.13.0a3
49
49
  Requires-Dist: event-model
50
50
  Requires-Dist: p4p
51
51
  Requires-Dist: pyyaml
@@ -1,35 +1,37 @@
1
1
  ophyd_async/__init__.py,sha256=WJoRU7gO-hRzyf7a-C952zF6-7zwPjP7qZ1Qu5GTUC8,124
2
2
  ophyd_async/__main__.py,sha256=G-Zcv_G9zK7Nhx6o5L5w-wyhMxdl_WgyMELu8IMFqAE,328
3
- ophyd_async/_version.py,sha256=H-qsvrxCpdhaQzyddR-yajEqI71hPxLa4KxzpP3uS1g,411
4
- ophyd_async/core/__init__.py,sha256=Us5DMr4ys-P4_zKWs6rN-J8QipWpOjAsmF5Cu0BY9k8,2188
5
- ophyd_async/core/_providers.py,sha256=sgEv6MabSKlrFwB8TEoTU7qKiQ6D1YsO33q2E3oKK_M,940
6
- ophyd_async/core/async_status.py,sha256=j3sE2zCvfg0GZWVY1NCEhdkdrqGhwtoDqwX_SVnFhbA,2765
7
- ophyd_async/core/detector.py,sha256=seeokcIRBj-maUuODUOKxesXRJjZLuEhOh6BzDmdIQI,6375
8
- ophyd_async/core/device.py,sha256=4PCvf7MU91CiWvJf0ERWEWE5wu7XPNrUND1ScxzMOXY,5958
9
- ophyd_async/core/device_save_loader.py,sha256=oAxWleSSOUD5TrnZWjOOmsVEfk2dE0cOvdwLTkEifvQ,6935
10
- ophyd_async/core/flyer.py,sha256=n3lqcvfXJiZooXXJocvaN6Wzi3wsqIPKzG4jD5veO7o,9970
11
- ophyd_async/core/signal.py,sha256=2szVlaxdZwc5z8gtnH8Yaol1jQIMrNMwhNWlvdZtwwI,11589
12
- ophyd_async/core/signal_backend.py,sha256=brD1MTug_AkNj3hDkhz6CxG5ygE1LF4AS9YVWCMFI0M,1312
13
- ophyd_async/core/sim_signal_backend.py,sha256=XZ2NCgoLnVPJyqwhRRhuUjY4TRXrVl6zH-5UAVLJGvY,5539
3
+ ophyd_async/_version.py,sha256=nSi77MfFtahju9XLwmhCTVsEygz__it8HHOvmBHSgKI,408
4
+ ophyd_async/core/__init__.py,sha256=Vy0m53wHwRSQ8FVeqzyZ5c6qdWIkkLA4vmEwbdk7iqc,2121
5
+ ophyd_async/core/_providers.py,sha256=HJbXQGocNxGDr5fv13zOkONXN1JqCfqJ3P0pR_sIy1Y,2137
6
+ ophyd_async/core/async_status.py,sha256=-sfIf7VhwAP25kSVwKZjAIYOTROpfnh2jgkDw5_afSU,2801
7
+ ophyd_async/core/detector.py,sha256=-KttT_gPniRB5xalfh5xj2aH5nLV6KoDVLlXaM-d0rw,9989
8
+ ophyd_async/core/device.py,sha256=Ai5FRThlDeXnzKwTuVlmD8RFzlF_cq88Y6xcEiHOTho,5545
9
+ ophyd_async/core/device_save_loader.py,sha256=RXA3dPUPihAR2ZGDStlGiA-TAsr_xqL0snsCjMsMnfA,9138
10
+ ophyd_async/core/flyer.py,sha256=PBfxH9XMYqhFzNFqR2H6U_FxY2L5Un5mUD_3GMDZvdo,2780
11
+ ophyd_async/core/signal.py,sha256=PgoUzcmMaQczoBSlHDA4AmRKoDwoDH9uNmF_5DgJa6k,11800
12
+ ophyd_async/core/signal_backend.py,sha256=hwrDrwJK9rzOW4fsN_T2RFdCHhYwSFkR325i5L0lHE8,1363
13
+ ophyd_async/core/sim_signal_backend.py,sha256=h7if2Oqr4jNOLfQoD_sqJOZd3uyTNHpfn1oJ4apug84,5590
14
14
  ophyd_async/core/standard_readable.py,sha256=9cBetIYttAho-7wOB3T1YgSJy0iWEFTAdn9jZkrGvLA,2560
15
- ophyd_async/core/utils.py,sha256=uxmKSbLsRizna482Zsl2q14H_jiM3JksqHCFkp_QYIM,3193
15
+ ophyd_async/core/utils.py,sha256=10cGVTR73oa_05ZVfdNzdTlr3-s1VHxvgtT1PD5LJ8Q,4585
16
16
  ophyd_async/epics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ ophyd_async/epics/pvi.py,sha256=BGhAXLyY2Z2e3ujyJ2ObnW19hogGvTZbHZY6Iq_nQeU,2331
17
18
  ophyd_async/epics/_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- ophyd_async/epics/_backend/_aioca.py,sha256=izEUbxHKRLalsbcfybmMKUHw7NvDOvST4lqzIRxlOwg,9033
19
- ophyd_async/epics/_backend/_p4p.py,sha256=vrCjX2W6mkghZfyCFI_i5VLhG3380nyW1-HiupzRjKQ,11001
19
+ ophyd_async/epics/_backend/_aioca.py,sha256=0PmpDNohm52461plfrxirLJsyhZXgYIDJv12Y6zfQ0A,8731
20
+ ophyd_async/epics/_backend/_p4p.py,sha256=aikjxQUgBRqNmMNMzOx3-N0rPdn-D1E8P5vQwvmYIgM,11970
21
+ ophyd_async/epics/_backend/common.py,sha256=3zxGLNcBtss6WUGAwfAjxWnUF4YbFbYvpOUmoFJaG5Y,753
20
22
  ophyd_async/epics/areadetector/__init__.py,sha256=oEOzL7gEVVSULeT2WkFrva8lUKeX0zmQD0tmwFz6L24,325
21
23
  ophyd_async/epics/areadetector/single_trigger_det.py,sha256=q5mG-OUVagIjvXLb28lsrGj4eUSoH2pNW2rT4rQR8fA,1206
22
24
  ophyd_async/epics/areadetector/utils.py,sha256=dez54oElIkGMnhSM9qghToUB1opSqjdWTV2vhHCgRMA,3133
23
25
  ophyd_async/epics/areadetector/controllers/__init__.py,sha256=UG2-M5d2ykp2T8isQJCbAsGZF1aH0BtC_OPlzzPTjnA,149
24
- ophyd_async/epics/areadetector/controllers/ad_sim_controller.py,sha256=Q5GT7nzXWL3MxJ25b6rab_qft-XQtwGEfrGG9dNKJcA,1591
25
- ophyd_async/epics/areadetector/controllers/pilatus_controller.py,sha256=n9Gkq2RtPnTzdoqpKArvod92Nu1Jo7XHJBGUkZr-N2s,1556
26
+ ophyd_async/epics/areadetector/controllers/ad_sim_controller.py,sha256=mthZ6WxajMEgUKptq3bnkIctbLhjzTagV66i1auB8cg,1587
27
+ ophyd_async/epics/areadetector/controllers/pilatus_controller.py,sha256=TSWry-eWfDl4LqafMH75aVqYTrsdmSEbBzCLDUcR2aY,1552
26
28
  ophyd_async/epics/areadetector/drivers/__init__.py,sha256=AOpIEYfoBhG9Nc4-SId99v4PpyEh4_RBXfNaqiXlwUI,315
27
29
  ophyd_async/epics/areadetector/drivers/ad_base.py,sha256=ikfyNcZwJa5ah52DckjrBzkMMT_eDY1smM4XWfb6A6E,3689
28
30
  ophyd_async/epics/areadetector/drivers/pilatus_driver.py,sha256=cn5WNz913UOnOttw2bssjV2Bo3p9SuJma3ckRyCdvw8,442
29
31
  ophyd_async/epics/areadetector/writers/__init__.py,sha256=tpPcrYd1hs8WS7C0gmCnR2EBwjE5RzCljI7WwZ2V_LM,191
30
32
  ophyd_async/epics/areadetector/writers/_hdfdataset.py,sha256=E0C9VgsPyY35h7k0mvcIhjsIVNavApLxizqNWlM388w,167
31
- ophyd_async/epics/areadetector/writers/_hdffile.py,sha256=bFVDlVIMXANtE146DCm4uVbnYaibQM8Qzoa32XcwMJg,1373
32
- ophyd_async/epics/areadetector/writers/hdf_writer.py,sha256=_JAU6CSOigxi7SW6Wbu1jX7__8U-03HkjaPLF5VfHfQ,4666
33
+ ophyd_async/epics/areadetector/writers/_hdffile.py,sha256=Zh7nWzK9-q0ASCi88tLAFUuWRL_rbz8XTNzKXwRmi88,1797
34
+ ophyd_async/epics/areadetector/writers/hdf_writer.py,sha256=lJHP1CzpXYH82GcgEA-D4qI27Uj1_W8pAVgexFSXmgk,5011
33
35
  ophyd_async/epics/areadetector/writers/nd_file_hdf.py,sha256=rutCstILCGGwhP5pH_2lWM2QUcZ88-uxx5dTZIJUMWQ,1562
34
36
  ophyd_async/epics/areadetector/writers/nd_plugin.py,sha256=l0yBBEazviyFsWJv_4_sfGn_YM_Iyd0_SlMdAmUlXDU,871
35
37
  ophyd_async/epics/demo/__init__.py,sha256=DbVO4ufJWjQnZteilW8SBs5A8DN-Xajn0YibM0q8UkE,5500
@@ -38,16 +40,17 @@ ophyd_async/epics/demo/mover.db,sha256=RFz0rxZue689Wh1sWTZwWeFMUrH04ttPq2u5xJH_F
38
40
  ophyd_async/epics/demo/sensor.db,sha256=AVtiydrdtwAz2EFurO2Ult9SSRtre3r0akOBbL98LT0,554
39
41
  ophyd_async/epics/motion/__init__.py,sha256=tnmVRIwKa9PdN_xonJdAUD04UpEceh-hoD7XI62yDB0,46
40
42
  ophyd_async/epics/motion/motor.py,sha256=lQcA3PSPxA6XOnk8y5VuJGnKTq2VjkcO6ldCrssGr3M,3392
41
- ophyd_async/epics/signal/__init__.py,sha256=M1dz74L_SM5Qf3GRuQVKn-1Pvs-CEOCkoxyg1J-etHM,232
43
+ ophyd_async/epics/signal/__init__.py,sha256=wb93RTqvSbGKVFQj8OHykbVLGLmwKHU72oi5xYu2UaY,188
42
44
  ophyd_async/epics/signal/_epics_transport.py,sha256=DEIL0iYUAWssysVEgWGu1fHSM1l-ATV2kjUgPtDN9LY,858
43
- ophyd_async/epics/signal/pvi_get.py,sha256=YTNQ9nXi1v8Rig54goc4_nFTxoH_wmF3yl75FzkdXy4,479
44
45
  ophyd_async/epics/signal/signal.py,sha256=7GnGa4CgFgTwyHeh4wYOJ2GEWwdXsC6vHD3z9LsaHaM,2543
45
- ophyd_async/panda/__init__.py,sha256=1fyb-sP56K5zDmhKrn97YzMe7hL7LscHGgogqkGEobU,420
46
- ophyd_async/panda/panda.py,sha256=ThNzYarMlmyLqrUsDo-vjd-IxYLxnqKDIwvcBKWzED0,9901
46
+ ophyd_async/panda/__init__.py,sha256=rVM7PdHnON5h0Hcpz_49N5bVfcNmSH5V6ApdaGcBSno,533
47
+ ophyd_async/panda/panda.py,sha256=f_bEYUn7HwMCfVsZxPJ43e4Mo9FQrluHh7_vOHErwYE,8335
48
+ ophyd_async/panda/panda_controller.py,sha256=CK9TTXAGXne31C3HZfBo_grk9pIM1y9Lyo0lms37dLY,1236
47
49
  ophyd_async/panda/table.py,sha256=dLoRP4zYNOkD_s0Vkp2wVYAwkjVG8nNdf8-FaXOTfPo,5655
48
- ophyd_async-0.2.0.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
49
- ophyd_async-0.2.0.dist-info/METADATA,sha256=hF1Gj4qjAmUc2eeaX3RA8awW41LYrkSieBJ5y36pqsI,7197
50
- ophyd_async-0.2.0.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
51
- ophyd_async-0.2.0.dist-info/entry_points.txt,sha256=O0YNJTEufO0w9BozXi-JurTy2U1_o0ypeCgJLQ727Jk,58
52
- ophyd_async-0.2.0.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
53
- ophyd_async-0.2.0.dist-info/RECORD,,
50
+ ophyd_async/panda/utils.py,sha256=VHW5kPVISyEkmse_qQcyisBkkEwMO6GG2Ago-CH1AFA,487
51
+ ophyd_async-0.3a1.dist-info/LICENSE,sha256=pU5shZcsvWgz701EbT7yjFZ8rMvZcWgRH54CRt8ld_c,1517
52
+ ophyd_async-0.3a1.dist-info/METADATA,sha256=Ypyn4I7_5JESeLA3lNZUyld4MB3vNrWGw_bpTnYvq0g,7208
53
+ ophyd_async-0.3a1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
54
+ ophyd_async-0.3a1.dist-info/entry_points.txt,sha256=O0YNJTEufO0w9BozXi-JurTy2U1_o0ypeCgJLQ727Jk,58
55
+ ophyd_async-0.3a1.dist-info/top_level.txt,sha256=-hjorMsv5Rmjo3qrgqhjpal1N6kW5vMxZO3lD4iEaXs,12
56
+ ophyd_async-0.3a1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.3)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,22 +0,0 @@
1
- from typing import Dict, TypedDict
2
-
3
- from p4p.client.asyncio import Context
4
-
5
-
6
- class PVIEntry(TypedDict, total=False):
7
- d: str
8
- r: str
9
- rw: str
10
- w: str
11
- x: str
12
-
13
-
14
- async def pvi_get(pv: str, ctxt: Context, timeout: float = 5.0) -> Dict[str, PVIEntry]:
15
- pv_info = ctxt.get(pv, timeout=timeout).get("pvi").todict()
16
-
17
- result = {}
18
-
19
- for attr_name, attr_info in pv_info.items():
20
- result[attr_name] = PVIEntry(**attr_info) # type: ignore
21
-
22
- return result