Source code for fastcs.attributes.attribute

from collections.abc import Callable
from typing import Generic

from fastcs.attributes.attribute_io_ref import AttributeIORefT
from fastcs.datatypes import DataType, DType, DType_T
from fastcs.logging import bind_logger
from fastcs.tracer import Tracer

logger = bind_logger(logger_name=__name__)


[docs] class Attribute(Generic[DType_T, AttributeIORefT], Tracer): """Base FastCS attribute. Instances of this class added to a ``Controller`` will be used by the FastCS class. """ def __init__( self, datatype: DataType[DType_T], io_ref: AttributeIORefT | None = None, group: str | None = None, description: str | None = None, ) -> None: super().__init__() assert issubclass(datatype.dtype, DType), ( f"Attr type must be one of {DType}, received type {datatype.dtype}" ) self._io_ref = io_ref self._datatype: DataType[DType_T] = datatype self._group = group self.enabled = True self.description = description # A callback to use when setting the datatype to a different value, for example # changing the units on an int. self._update_datatype_callbacks: list[Callable[[DataType[DType_T]], None]] = [] # Path and name to be filled in by Controller it is bound to self._name = "" self._path = [] @property def io_ref(self) -> AttributeIORefT: if self._io_ref is None: raise RuntimeError(f"{self} has no AttributeIORef") return self._io_ref def has_io_ref(self): return self._io_ref is not None @property def datatype(self) -> DataType[DType_T]: return self._datatype @property def dtype(self) -> type[DType_T]: return self._datatype.dtype @property def group(self) -> str | None: return self._group @property def name(self) -> str: return self._name @property def path(self) -> list[str]: return self._path @property def full_name(self) -> str: return ".".join(self._path + [self._name]) def add_update_datatype_callback( self, callback: Callable[[DataType[DType_T]], None] ) -> None: self._update_datatype_callbacks.append(callback) def update_datatype(self, datatype: DataType[DType_T]) -> None: if not isinstance(self._datatype, type(datatype)): raise ValueError( f"Attribute datatype must be of type {type(self._datatype)}" ) self._datatype = datatype for callback in self._update_datatype_callbacks: callback(datatype) def set_name(self, name: str): if self._name: raise RuntimeError( f"Attribute is already registered with a controller as {self._name}" ) self._name = name def set_path(self, path: list[str]): if self._path: raise RuntimeError( f"Attribute is already registered with a controller at {self._path}" ) self._path = path def __repr__(self): name = self.__class__.__name__ full_name = self.full_name or None datatype = self._datatype.__class__.__name__ return f"{name}(name={full_name}, datatype={datatype}, io_ref={self._io_ref})"