diff --git a/csaxs_bec/devices/aerotech/README.md b/csaxs_bec/devices/aerotech/README.md index b64cceb1..3f772436 100644 --- a/csaxs_bec/devices/aerotech/README.md +++ b/csaxs_bec/devices/aerotech/README.md @@ -179,7 +179,7 @@ the wiring at connect. ```python dev.pandatrig.configure_line(n_pulses=100, exp_time=0.01, readout_time=0.002, shutter_delay=0.005) dev.pandatrig.arm() # arm(one_shot=True): only the next edge -dev.pandatrig.software_trigger() # or the PSO edges on TTLIN3, one per line +dev.pandatrig.soft_line_trigger() # or the PSO edges on TTLIN3, one per line dev.pandatrig.wait_lines_done(n_lines=1, timeout=5) dev.pandatrig.line_status() # triggers, lines, pulses, dropped since arm() ``` diff --git a/csaxs_bec/devices/panda_box/panda_line_trigger.py b/csaxs_bec/devices/panda_box/panda_line_trigger.py index 6d9660a0..5cf85a09 100644 --- a/csaxs_bec/devices/panda_box/panda_line_trigger.py +++ b/csaxs_bec/devices/panda_box/panda_line_trigger.py @@ -120,7 +120,7 @@ class PandaLineTrigger(Device): "configure_line", "arm", "disarm", - "software_trigger", + "soft_line_trigger", "line_status", "wait_lines_done", "get_readout_time", @@ -366,7 +366,7 @@ class PandaLineTrigger(Device): self.panda.set(f"{self.ARM_GATE}.FORCE_RST", "") self.panda.set(self.SOFT_TRIGGER_BIT, "0") - def software_trigger(self) -> None: + def soft_line_trigger(self) -> None: """Line trigger edge from software (accepted like a TTLIN3 edge).""" self.panda.set(self.SOFT_TRIGGER_BIT, "1") self.panda.set(self.SOFT_TRIGGER_BIT, "0") diff --git a/tests/tests_devices/test_panda_line_trigger.py b/tests/tests_devices/test_panda_line_trigger.py index 9febf180..65edee41 100644 --- a/tests/tests_devices/test_panda_line_trigger.py +++ b/tests/tests_devices/test_panda_line_trigger.py @@ -98,7 +98,7 @@ def test_never_toggles_pulse_enable_after_setup(trigger): trigger.configure_line(5, exp_time=0.01) trigger.panda.writes.clear() trigger.arm() - trigger.software_trigger() + trigger.soft_line_trigger() trigger.wait_lines_done(1, timeout=1) trigger.disarm() trigger.stop() @@ -109,7 +109,7 @@ def test_stays_armed_for_many_lines(trigger): trigger.configure_line(5, exp_time=0.01) trigger.arm() for _ in range(4): - trigger.software_trigger() + trigger.soft_line_trigger() status = trigger.wait_lines_done(4, timeout=1) assert (status["lines"], status["pulses"], status["armed"]) == (4, 20, True) @@ -117,9 +117,9 @@ def test_stays_armed_for_many_lines(trigger): def test_one_shot_accepts_one_edge(trigger): trigger.configure_line(5, exp_time=0.01) trigger.arm(one_shot=True) - trigger.software_trigger() + trigger.soft_line_trigger() assert trigger.wait_lines_done(1, timeout=1)["armed"] is False - trigger.software_trigger() + trigger.soft_line_trigger() status = trigger.wait_lines_done(1, timeout=1) assert status["triggers"] == 2 and status["lines"] == 1 @@ -127,9 +127,9 @@ def test_one_shot_accepts_one_edge(trigger): def test_edge_during_line_is_ignored(trigger): trigger.configure_line(5, exp_time=0.01) trigger.arm() - trigger.software_trigger() + trigger.soft_line_trigger() trigger.panda.busy = True - trigger.software_trigger() + trigger.soft_line_trigger() trigger.panda.busy = False status = trigger.wait_lines_done(1, timeout=1) assert status["triggers"] == 2 and status["lines"] == 1 and status["pulses"] == 5 @@ -151,7 +151,7 @@ def test_wait_lines_done_reports_too_many_lines(trigger): trigger.configure_line(5, exp_time=0.01) trigger.arm() for _ in range(3): - trigger.software_trigger() + trigger.soft_line_trigger() with pytest.raises(PandaLineTriggerError, match="expected 2 line"): trigger.wait_lines_done(2, timeout=0.1, poll=0.01) @@ -195,7 +195,7 @@ def test_disarm_closes_the_gate(trigger): trigger.configure_line(5, exp_time=0.01) trigger.arm() trigger.disarm() - trigger.software_trigger() + trigger.soft_line_trigger() status = trigger.line_status() assert (status["armed"], status["lines"], status["pulses"]) == (False, 0, 0) @@ -255,3 +255,22 @@ def test_unchanged_fields_are_not_written(trigger): again.configure_line(5, 0.01, 0.002) values = [w for w in again.panda.writes if not w.split("=", 1)[1] == ""] assert values == [] + + +@pytest.mark.parametrize( + "device_cls", + [ + "csaxs_bec.devices.panda_box.panda_line_trigger.PandaLineTrigger", + "csaxs_bec.devices.aerotech.a3200.A3200Motor", + "csaxs_bec.devices.aerotech.a3200.A3200PositionCapture", + ], +) +def test_user_access_names_not_protected_by_bec(device_cls): + # the device server refuses to load a device whose USER_ACCESS shadows a DeviceBase name + import importlib + + from bec_server.device_server.devices.device_serializer import get_protected_class_methods + + module, name = device_cls.rsplit(".", 1) + cls = getattr(importlib.import_module(module), name) + assert not set(cls.USER_ACCESS) & set(get_protected_class_methods())