Source code for ifgen.svd.model.derived

"""
A module implementing a class mixin for SVD element types with a derivedFrom
attribute.
"""

# built-in
from typing import Iterable, Iterator, Optional, TypeVar
from xml.etree import ElementTree

# third-party
from vcorelib.logging import LoggerType

# internal
from ifgen.svd.string import StringKeyValueMixin

T = TypeVar("T", bound="DerivedMixin")
DEFAULT_ALTERNATE = "alternateRegister"


[docs] class DerivedMixin(StringKeyValueMixin): """A class mixin for instances with a derived attribute.""" @property def derived_elem(self: T) -> T: """Get the derived element.""" result = getattr(self, "derived_from", None) if result is None: result = self return result @property def name(self) -> str: """Get the name of this peripheral.""" return self.raw_data["name"] @property def derived(self) -> bool: """Whether or not this peripheral is derived from another.""" return getattr(self, "derived_from", None) is not None @property def alternates(self: T) -> list[T]: """Get alternates of this instance.""" if not hasattr(self, "_alternates"): self._alternates: list[T] = [] return self._alternates
[docs] def is_alternate(self, key: str = DEFAULT_ALTERNATE) -> bool: """Determine if this instance is an alternate of another.""" return isinstance(self.alternate(key=key), str)
[docs] def alternate(self, key: str = DEFAULT_ALTERNATE) -> Optional[str]: """Get a possible alternate for this instance.""" return self.raw_data.get(key)
[docs] def log( self, elem: ElementTree.Element, logger: Optional[LoggerType] ) -> None: """Log information from this instance's raw data.""" super().log(elem, logger) if logger is not None and self.derived: logger.info( "'%s' derived from '%s'.", self.name, self.derived_elem.name, )
[docs] def derived_from_stack( elements: Iterable[ElementTree.Element], ) -> Iterator[ElementTree.Element]: """Organize elements that are derived after ones that aren't.""" elem_stack = [] for elem in elements: # Handle derived peripherals last. derived = elem.attrib.get("derivedFrom") if derived is not None: elem_stack.append(elem) else: elem_stack.insert(0, elem) while elem_stack: yield elem_stack.pop(0)