Source code for ekfsm.core.utils

from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from anytree import AnyNode

from ekfsm.devices import CLASS_MAP
from ekfsm.exceptions import ConfigError

if TYPE_CHECKING:
    from .components import HwModule
    from ekfsm.devices.generic import Device


[docs] class BoardDictImporter: def __init__(self, nodecls=AnyNode): self.nodecls = nodecls
[docs] def import_(self, logger: logging.Logger, data, parent=None, abort: bool = False): """Import tree from `data`.""" return self.__import(logger, data, parent=parent, abort=abort)
def __import(self, logger: logging.Logger, data, parent=None, abort: bool = False): from .components import HwModule device_type = data.get("device_type") nodecls = CLASS_MAP.get(device_type) if nodecls is None: raise ConfigError(f"Unknown device type: {device_type}") children = data.pop("children", []) if parent is not None and isinstance(parent, HwModule): # ??? pass node = nodecls(parent=parent, **data) if children is not None: for child in children: try: logger.debug(f"Importing sub device {child}") self.__import(logger, child, parent=node, abort=abort) except Exception as e: if abort: logger.error( f"Failed to import sub device {child}: {e}. aborting" ) raise e else: logger.error( f"Failed to import sub device {child}: {e}. continue anyway" ) return node
[docs] def deserialize_hardware_tree( logger: logging.Logger, data: dict, parent: "HwModule" ) -> tuple[str, str, str, list["Device"]]: importer = BoardDictImporter() abort = parent.abort # better use schema extension for this id = data.pop("id", None) if id is None: raise ConfigError("Board configuration must contain `id`") name = data.pop("name", None) if name is None: raise ConfigError("Board configuration must contain `name`") slot_type = data.pop("slot_type") if slot_type is None: raise ConfigError("Board configuration must contain `board_type`") children = data.pop("children", None) devices = [] if children: for child in children: try: logger.debug(f"Importing top level device {child}") node = importer.import_(logger, child, parent=parent, abort=abort) devices.append(node) except Exception as e: if abort: logger.error( f"Failed to import top level device {child}: {e}. aborting" ) raise e else: logger.error( f"Failed to import top level device {child}: {e}. continue anyway" ) return id, name, slot_type, devices