diff --git a/pyproject.toml b/pyproject.toml index 2810022..39cb6a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ classifiers = [ dependencies = [ "PyTango>=10.1.1", - "accelerator-middle-layer<=0.2.2", + "accelerator-middle-layer>=0.2.2", "pydantic>=2.0" ] diff --git a/tango/pyaml/__init__.py b/tango/pyaml/__init__.py index 096e4f9..ad4a188 100644 --- a/tango/pyaml/__init__.py +++ b/tango/pyaml/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.3.2" +__version__ = "0.3.3" import logging.config import os diff --git a/tango/pyaml/multi_attribute.py b/tango/pyaml/multi_attribute.py index 25ca05c..d6e289d 100644 --- a/tango/pyaml/multi_attribute.py +++ b/tango/pyaml/multi_attribute.py @@ -1,4 +1,5 @@ import logging +from typing import Tuple, Optional import numpy as np import pyaml @@ -28,11 +29,14 @@ class ConfigModel(BaseModel): Group name. unit : str, optional Unit of the attributes. + range : tuple(min, max), optional + Range of valid values. Use null for -∞ or +∞. """ attributes: list[str] = [] name: str = "" unit: str = "" + range: Optional[Tuple[Optional[float], Optional[float]]] = None class MultiAttribute(DeviceAccessList): @@ -41,7 +45,9 @@ def __init__(self, cfg: ConfigModel = None): self._cfg = cfg if self._cfg: for attribute in self._cfg.attributes: - attr_config = AttrConfig(attribute=attribute, unit=self._cfg.unit) + attr_config = AttrConfig( + attribute=attribute, unit=self._cfg.unit, range=self._cfg.range + ) attr = Attribute(attr_config) self.append(attr) @@ -128,6 +134,20 @@ def readback(self) -> np.array: return np.array(values) + def get_range(self) -> list[float]: + attr_range: list[float] = [] + for device in self: + attr_range.extend(device.get_range()) + return attr_range + + def check_device_availability(self) -> bool: + available = False + for device in self: + available = device.check_device_availability() + if not available: + break + return available + def unit(self) -> str: if self._cfg: return self._cfg.unit diff --git a/tests/conftest.py b/tests/conftest.py index ac09f9e..e12bd02 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -74,6 +74,21 @@ def config_multi(): return MultiAttrCM(**cfg_dict) +@pytest.fixture +def config_multi_range(): + conf = """ +attributes: + - "sys/tg_test/1/float_scalar" + - "sys/tg_test/2/float_scalar" + - "sys/tg_test/3/float_scalar" + - "sys/tg_test/4/float_scalar" +unit: "A" +range: [-15, 15] +""" + cfg_dict = yaml.safe_load(conf) + return MultiAttrCM(**cfg_dict) + + @pytest.fixture def config_tango_cs(): conf = """ diff --git a/tests/test_multi_attribute.py b/tests/test_multi_attribute.py index a56a748..4185f03 100644 --- a/tests/test_multi_attribute.py +++ b/tests/test_multi_attribute.py @@ -1,6 +1,5 @@ import random - from .mocked_control_system_initialized import MockedControlSystemInitialized from .mocked_device_proxy import MockedDeviceProxy from unittest.mock import patch @@ -24,3 +23,17 @@ def test_multi_read_write(self, config_multi): assert len(vals) == len(values) for index, val in enumerate(vals): assert val == values[index] + + def test_multiattribute_range(self, config_multi_range): + with ( + patch("tango.DeviceProxy", new=MockedDeviceProxy), + patch( + "tango.pyaml.controlsystem.TangoControlSystem", + new=MockedControlSystemInitialized, + ), + ): + ma = MultiAttribute(config_multi_range) + attr_range = ma.get_range() + assert attr_range is not None + assert len(attr_range) == 8 # (4*2) + assert attr_range == [-15, 15, -15, 15, -15, 15, -15, 15]