Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add children property to a device #1138

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 20 additions & 42 deletions ophyd/v2/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ def name(self) -> str:
"""Return the name of the Device"""
return self._name

@property
def children(self) -> Generator[Tuple[str, Device], None, None]:
rosesyrett marked this conversation as resolved.
Show resolved Hide resolved
rosesyrett marked this conversation as resolved.
Show resolved Hide resolved
for attr_name, attr in self.__dict__.items():
if attr_name != "parent" and isinstance(attr, Device):
yield attr_name, attr

def set_name(self, name: str):
"""Set ``self.name=name`` and each ``self.child.name=name+"-child"``.

Expand All @@ -164,7 +170,10 @@ def set_name(self, name: str):
New name to set
"""
self._name = name
name_children(self, name)
for attr_name, child in self.children:
child_name = f"{name}-{attr_name.rstrip('_')}" if name else ""
child.set_name(child_name)
child.parent = self

async def connect(self, sim: bool = False):
"""Connect self and all child Devices.
Expand All @@ -174,7 +183,11 @@ async def connect(self, sim: bool = False):
sim:
If True then connect in simulation mode.
"""
await connect_children(self, sim)
coros = {
name: child_device.connect(sim) for name, child_device in self.children
}
if coros:
await wait_for_connection(**coros)


class NotConnected(Exception):
Expand Down Expand Up @@ -217,37 +230,6 @@ async def wait_for_connection(**coros: Awaitable[None]):
await f


async def connect_children(device: Device, sim: bool):
"""Call ``child.connect(sim)`` on all child devices in parallel.

Typically used to implement `Device.connect` like this::

async def connect(self, sim=False):
await connect_children(self, sim)
"""

coros = {
name: child_device.connect(sim)
for name, child_device in get_device_children(device)
}
if coros:
await wait_for_connection(**coros)


def name_children(device: Device, name: str):
"""Call ``child.set_name(child_name)`` on all child devices in series."""
for attr_name, child in get_device_children(device):
child_name = f"{name}-{attr_name.rstrip('_')}" if name else ""
child.set_name(child_name)
child.parent = device


def get_device_children(device: Device) -> Generator[Tuple[str, Device], None, None]:
for attr_name, attr in device.__dict__.items():
if attr_name != "parent" and isinstance(attr, Device):
yield attr_name, attr


class DeviceCollector:
"""Collector of top level Device instances to be used as a context manager

Expand Down Expand Up @@ -981,15 +963,11 @@ async def read(self) -> Dict[str, Reading]:


class DeviceVector(Dict[int, VT], Device):
def set_name(self, parent_name: str):
self._name = parent_name
for name, device in self.items():
device.set_name(f"{parent_name}-{name}")
device.parent = self

async def connect(self, sim: bool = False):
coros = {str(k): d.connect(sim) for k, d in self.items()}
await wait_for_connection(**coros)
@property
def children(self) -> Generator[Tuple[str, Device], None, None]:
for attr_name, attr in self.items():
if isinstance(attr, Device):
yield str(attr_name), attr


def get_unique(values: Dict[str, T], types: str) -> T:
Expand Down
15 changes: 12 additions & 3 deletions ophyd/v2/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
SignalRW,
SimSignalBackend,
T,
get_device_children,
set_and_wait_for_value,
set_sim_put_proceeds,
set_sim_value,
Expand Down Expand Up @@ -205,17 +204,27 @@ def __init__(self, name: str) -> None:
self.set_name(name)


def test_get_device_children():
def test_device_children():
parent = DummyDeviceGroup("parent")

names = ["child1", "child2", "dict_with_children"]
for idx, (name, child) in enumerate(get_device_children(parent)):
for idx, (name, child) in enumerate(parent.children):
assert name == names[idx]
assert (
type(child) == DummyBaseDevice
if name.startswith("child")
else type(child) == DeviceVector
)
assert child.parent == parent


def test_device_vector_children():
parent = DummyDeviceGroup("root")

device_vector_children = [
(name, child) for name, child in parent.dict_with_children.children
]
assert device_vector_children == [("123", parent.dict_with_children[123])]


async def test_children_of_device_have_set_names_and_get_connected():
Expand Down
Loading