Source code for ifgen.svd.string

"""
A module implementing interfaces for string-data elements.
"""

# built-in
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any, Iterable, Optional, Type, TypeVar
from xml.etree import ElementTree

# third-party
from ruamel.yaml.scalarstring import LiteralScalarString
from vcorelib.logging import LoggerType


[docs] @dataclass class StringKeyVal: """Name of key and whether or not it's required.""" key: str required: bool = True
T = TypeVar("T", bound="StringKeyValueMixin")
[docs] class StringKeyValueMixin(ABC): """A mixin for SVD data model classes.""" raw_data: dict[str, str]
[docs] @classmethod def create(cls: Type[T], elem: ElementTree.Element, *args, **kwargs) -> T: """Create a device instance from an element.""" inst = cls(*args, **kwargs) inst.raw(elem) return inst
[docs] @classmethod @abstractmethod def string_keys(cls) -> Iterable[StringKeyVal]: """Get string keys for this instance type."""
[docs] def handle_description( self, data: dict[str, Any] = None, prefix: str = None ) -> dict[str, Any]: """Handle a possible description entry.""" if data is None: data = {} description = self.raw_data.get("description") if description: data["description"] = LiteralScalarString( (prefix if prefix else "") + description ).replace("\\n", "") return data
[docs] def raw(self, elem: ElementTree.Element) -> dict[str, str]: """Get raw data for this instance based on string keys.""" result = getattr(self, "raw_data", None) if result is None: self.raw_data = self.get_values(elem) result = self.raw_data assert result is not None return result
[docs] def log( self, elem: ElementTree.Element, logger: Optional[LoggerType] ) -> None: """Log information from this instance's raw data.""" if logger is not None: for key, value in self.raw(elem).items(): for line in value.splitlines(): line = line.strip().replace("\\n", "") if line: logger.info("%s: %s", key, line)
[docs] @classmethod def get_values(cls, elem: ElementTree.Element) -> dict[str, str]: """Get string values for this instance.""" return get_string_values(elem, cls.string_keys())
[docs] def get_string_values( elem: ElementTree.Element, keys: Iterable[StringKeyVal] ) -> dict[str, str]: """Get string values from an element's children.""" result = {} for item in keys: key = item.key required = item.required new_elem = elem.find(key) assert ( new_elem is not None or not required ), f"'{key}' required but not found!" if new_elem is not None: result[key] = new_elem.text or "" return result