Skip to content
This repository was archived by the owner on Oct 11, 2023. It is now read-only.

Commit 1f1abce

Browse files
coretlolliesilvester
authored andcommitted
Changes to work with a real PandA
- Block names can have numbers and underscores in - Type hints seem to work better on the class, not instance - Added demo - Added type hints function which doesn't look through parent classes
1 parent 72b3517 commit 1f1abce

File tree

4 files changed

+59
-7
lines changed

4 files changed

+59
-7
lines changed

docs/examples/panda_demo.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from bluesky import RunEngine
2+
3+
# these three lines just let you use await statements
4+
# #in ipython terminal with the Run Engine event loop.
5+
from IPython import get_ipython
6+
from ophyd.v2.core import DeviceCollector
7+
8+
from ophyd_epics_devices.panda import PandA
9+
10+
get_ipython().run_line_magic("autoawait", "call_in_bluesky_event_loop")
11+
RE = RunEngine()
12+
13+
with DeviceCollector():
14+
my_panda = PandA("TS-PANDA")

src/ophyd_epics_devices/panda.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import atexit
24
import re
35
from enum import Enum
@@ -34,6 +36,8 @@
3436
)
3537
from p4p.client.thread import Context
3638

39+
from ophyd_epics_devices.utils import get_type_hints_no_inheritance
40+
3741

3842
class PulseBlock(Device):
3943
delay: SignalRW[float]
@@ -93,7 +97,7 @@ class PVIEntry(TypedDict, total=False):
9397

9498

9599
def block_name_number(block_name: str) -> Tuple[str, int]:
96-
m = re.match("^([a-z]+)([0-9]*)$", block_name)
100+
m = re.match("^([0-9_a-z]+)([0-9]*)$", block_name)
97101
assert m, f"Expected '<block_name><block_num>', got '{block_name}'"
98102
name, num = m.groups()
99103
return name, int(num or 1)
@@ -144,7 +148,7 @@ def _del_ctxt():
144148

145149
def verify_block(self, name: str, num: int):
146150
"""Given a block name and number, return information about a block."""
147-
anno = get_type_hints(self).get(name)
151+
anno = get_type_hints(type(self)).get(name)
148152

149153
block: Device = Device()
150154

@@ -164,8 +168,7 @@ async def _make_block(self, name: str, num: int, block_pv: str, sim: bool = Fals
164168
sim mode then does a pvi call, and identifies this signal from the pvi call.
165169
"""
166170
block = self.verify_block(name, num)
167-
168-
field_annos = get_type_hints(block)
171+
field_annos = get_type_hints_no_inheritance(type(block))
169172
block_pvi = await pvi_get(block_pv, self.ctxt) if not sim else None
170173

171174
# finds which fields this class actually has, e.g. delay, width...
@@ -231,7 +234,7 @@ def _make_signal(self, signal_pvi: PVIEntry, dtype: Optional[Type] = None):
231234
return signal_factory(dtype, "pva://" + read_pv, "pva://" + write_pv)
232235

233236
def set_attribute(self, name, num, block):
234-
anno = get_type_hints(self).get(name)
237+
anno = get_type_hints(type(self)).get(name)
235238

236239
# get_origin to see if it's a device vector.
237240
if (anno == DeviceVector[PulseBlock]) or (anno == DeviceVector[SeqBlock]):
@@ -251,10 +254,11 @@ async def connect(self, sim=False) -> None:
251254
pvi = await pvi_get(self._init_prefix + ":PVI", self.ctxt) if not sim else None
252255
hints = {
253256
attr_name: attr_type
254-
for attr_name, attr_type in get_type_hints(self).items()
257+
for attr_name, attr_type in get_type_hints_no_inheritance(
258+
type(self)
259+
).items()
255260
if not attr_name.startswith("_")
256261
}
257-
258262
# create all the blocks pvi says it should have,
259263
if pvi:
260264
for block_name, block_pvi in pvi.items():

src/ophyd_epics_devices/utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from typing import get_type_hints
2+
3+
4+
# Use with types, not instances
5+
def get_type_hints_no_inheritance(cls):
6+
cls_hints = get_type_hints(cls)
7+
8+
for base_cls in cls.__bases__:
9+
base_hints = get_type_hints(base_cls)
10+
for base_hint_names in base_hints.keys():
11+
if base_hint_names in cls_hints:
12+
del cls_hints[base_hint_names]
13+
return cls_hints

tests/test_utils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from typing import get_type_hints
2+
3+
from ophyd_epics_devices.utils import get_type_hints_no_inheritance
4+
5+
6+
def test_get_type_hints_no_inheritance():
7+
class BaseClass:
8+
base_integer: int
9+
base_string: str
10+
11+
class SubClass(BaseClass):
12+
integer: int
13+
string: str
14+
15+
assert get_type_hints(SubClass) == {
16+
"base_integer": int,
17+
"base_string": str,
18+
"integer": int,
19+
"string": str,
20+
}
21+
assert get_type_hints_no_inheritance(SubClass) == {"integer": int, "string": str}

0 commit comments

Comments
 (0)