diff --git a/src/ibex_bluesky_core/devices/dae/__init__.py b/src/ibex_bluesky_core/devices/dae/__init__.py index 7ee57d2..dfc971a 100644 --- a/src/ibex_bluesky_core/devices/dae/__init__.py +++ b/src/ibex_bluesky_core/devices/dae/__init__.py @@ -10,7 +10,8 @@ def convert_xml_to_names_and_values(xml) -> Dict[str, str]: elements = get_all_elements_in_xml_with_child_called_name(xml) for element in elements: name, value = _get_names_and_values(element) - names_and_values[name] = value + if name is not None: + names_and_values[name] = value return names_and_values @@ -20,15 +21,15 @@ def get_all_elements_in_xml_with_child_called_name(xml): return elements -def _get_names_and_values(element) -> Tuple[str, str]: +def _get_names_and_values(element) -> tuple[Any, Any] | tuple[None, None]: name = element.find("Name") - if name is not None and hasattr(name, "text"): + if name is not None and name.text is not None: name = name.text - value = element.find("Val") - if value is not None and hasattr(value, "text"): - value = value.text - # TODO hmmmm, should we get choices here and store them somewhere? not sure. - return name, value + value = element.find("Val") + if value is not None and value.text is not None: + value = value.text + return name, value + return None, None def set_value_in_dae_xml(elements: List[ET.ElementTree], name: str, value: Any): diff --git a/tests/devices/test_dae.py b/tests/devices/test_dae.py index 71819ee..18060d3 100644 --- a/tests/devices/test_dae.py +++ b/tests/devices/test_dae.py @@ -1,9 +1,14 @@ # pyright: reportMissingParameterType=false +from enum import Enum +from xml.etree import ElementTree as ET import pytest from ibex_bluesky_core.devices.dae.dae import Dae, RunstateEnum from ophyd_async.core import get_mock_put +from src.ibex_bluesky_core.devices.dae import set_value_in_dae_xml, convert_xml_to_names_and_values +from src.ibex_bluesky_core.devices.dae.dae_controls import BeginRunExBits + @pytest.fixture async def dae() -> Dae: @@ -50,3 +55,125 @@ async def test_trigger_calls_triggers_begin_and_end(dae: Dae): get_mock_put(dae.controls.begin_run).assert_called_once() get_mock_put(dae.controls.end_run).assert_called_once() + +async def test_begin_run_sets_begin_run_ex(dae: Dae): + get_mock_put(dae.controls.begin_run_ex.begin_run_ex).assert_not_called() + await dae.controls.begin_run_ex.set(BeginRunExBits.NONE) + get_mock_put(dae.controls.begin_run_ex.begin_run_ex).assert_called_once() + +async def test_begin_run_ex_with_options_sets_begin_run_ex_correctly(dae: Dae): + get_mock_put(dae.controls.begin_run_ex.begin_run_ex).assert_not_called() + await dae.controls.begin_run_ex.set(BeginRunExBits.NONE+BeginRunExBits.BEGINIFPAUSED+BeginRunExBits.BEGINIFDELAYED) + get_mock_put(dae.controls.begin_run_ex.begin_run_ex).assert_called_once() + assert get_mock_put(dae.controls.begin_run_ex.begin_run_ex).call_args.args == (3,) + + +INITIAL_XML = """ + + + {name} + {initial_val} + + + """ + + +def test_set_value_in_xml_sets_a_value(): + name = "test" + initial_val = "123" + + root = ET.fromstring(INITIAL_XML.format(name=name, initial_val=initial_val)) + value_to_set = "234" + set_value_in_dae_xml(root.findall(".//child"), name, value_to_set) + + assert root[0][1].text == value_to_set + + +def test_set_value_with_enum_in_xml_sets_a_value(): + name = "test" + initial_val = "456" + + class SomeEnum(Enum): + TEST = "789" + + root = ET.fromstring(INITIAL_XML.format(name=name, initial_val=initial_val)) + value_to_set = SomeEnum.TEST + set_value_in_dae_xml(root.findall(".//child"), name, value_to_set) + + assert root[0][1].text == value_to_set.value + + +def test_set_value_with_none_in_xml_doesnt_set_a_value(): + name = "test" + initial_val = "456" + + root = ET.fromstring(INITIAL_XML.format(name=name, initial_val=initial_val)) + set_value_in_dae_xml(root.findall(".//child"), name, None) + + assert root[0][1].text == initial_val + + +def test_set_value_with_no_valid_children_in_xml_doesnt_set_a_value(): + name = "test" + initial_val = "456" + + root = ET.fromstring(INITIAL_XML.format(name=name, initial_val=initial_val)) + set_value_in_dae_xml(root.findall(".//child"), name + "thisisnowinvalid", "789") + + assert root[0][1].text == initial_val + + +def test_get_names_and_values_from_xml(): + name = "test" + initial_val = "456" + test_xml = f""" + + + Cluster + 2 + + + {name} + {initial_val} + + + """ + root = ET.fromstring(test_xml) + ret = convert_xml_to_names_and_values(root) + assert ret[name] == initial_val + + +def test_get_names_and_values_without_name_does_not_get_parsed(): + test_xml = f""" + + + Cluster + 2 + + + + + + + """ + root = ET.fromstring(test_xml) + ret = convert_xml_to_names_and_values(root) + assert not ret + + +def test_get_names_and_values_without_value_does_not_get_parsed(): + test_xml = f""" + + + Cluster + 2 + + + test + + + + """ + root = ET.fromstring(test_xml) + ret = convert_xml_to_names_and_values(root) + assert not ret diff --git a/tests/devices/test_init.py b/tests/devices/test_init.py index e640391..affcfda 100644 --- a/tests/devices/test_init.py +++ b/tests/devices/test_init.py @@ -2,7 +2,12 @@ import pytest -from ibex_bluesky_core.devices import compress_and_hex, dehex_and_decompress, get_pv_prefix, isis_epics_signal_rw +from ibex_bluesky_core.devices import ( + compress_and_hex, + dehex_and_decompress, + get_pv_prefix, + isis_epics_signal_rw, +) def test_can_dehex_and_decompress():