From fd2688f6a5f7e7a0023867cdf6a641061779aee0 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 25 Nov 2024 12:44:22 -0500 Subject: [PATCH] ENH: add ability to control component names are mangled The Python name (via attributes) of a child device is `foo.bar.baz`, however for a number of historical reasons (allowed keys in mongo and for attribute access in Pandas data frames with columns named from the data keys in an event stream) ophyd-sync has replaced '.' with '_' in the names. This leads to ambiguity when looking at the (default) name to which component on which device the data came from as there may be `_` in the attribute names. Ophyd-async used '-' which does allow for round tripping. This makes it controllable on per-instance basis in ophyd-sync so that users can either make a different set of trade offs. xref https://github.com/bluesky/ophyd-async/issues/666 --- ophyd/device.py | 7 +++++-- ophyd/tests/test_device.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ophyd/device.py b/ophyd/device.py index 0d9882a52..132a364c3 100644 --- a/ophyd/device.py +++ b/ophyd/device.py @@ -253,10 +253,12 @@ def create_component(self, instance): "Instantiate the object described by this Component for a Device" kwargs = self.kwargs.copy() kwargs.update( - name=f"{instance.name}_{self.attr}", + name=f"{instance.name}{instance._child_name_seperator}{self.attr}", kind=instance._component_kinds[self.attr], attr_name=self.attr, ) + if issubclass(self.cls, Device): + kwargs.setdefault('child_name_seperator', instance._child_name_seperator) for kw, val in list(kwargs.items()): kwargs[kw] = self.maybe_add_prefix(instance, kw, val) @@ -839,10 +841,11 @@ def __init__( read_attrs=None, configuration_attrs=None, parent=None, + child_name_seperator='_', **kwargs, ): self._destroyed = False - + self._child_name_seperator = child_name_seperator # Store EpicsSignal objects (only created once they are accessed) self._signals = {} diff --git a/ophyd/tests/test_device.py b/ophyd/tests/test_device.py index 926bbab53..d0a59ca87 100644 --- a/ophyd/tests/test_device.py +++ b/ophyd/tests/test_device.py @@ -969,3 +969,31 @@ class FakeTriggerableDevice(Device): d.trigger() assert d.strigger.get() == after + + +def test_child_seperator(): + class Test(Device): + a = Component(Signal) + b = Component(Signal) + + t = Test(name="bob") + assert t.a.name == "bob_a" + + t = Test(name="bob", child_name_seperator="-") + assert t.a.name == "bob-a" + + class Test2(Device): + c = Component(Signal) + d = Component(Signal) + t = Component(Test) + s = Component(Test, child_name_seperator="?") + + t2 = Test2(name="bob", child_name_seperator="!") + + assert t2.c.name == "bob!c" + assert t2.d.name == "bob!d" + + assert t2.t.a.name == "bob!t!a" + assert t2.t.b.name == "bob!t!b" + assert t2.s.a.name == "bob!s?a" + assert t2.s.a.name == "bob!s?b"