Source code for malcolm.core.info

import inspect
from typing import Dict, List, Mapping, Optional, Sequence, Type, TypeVar

from malcolm.compat import OrderedDict

from .errors import BadValueError

PartInfo = Mapping[str, Optional[Sequence]]

T = TypeVar("T", bound="Info")


[docs]class Info: """Base class that should be inherited from when a part needs to return something from a hooked function""" def __repr__(self): spec = inspect.getfullargspec(self.__init__) args = ", ".join(repr(getattr(self, x)) for x in spec.args[1:]) return f"{self.__class__.__name__}({args})"
[docs] @classmethod def filter_parts(cls: Type[T], part_info: PartInfo) -> Dict[str, List[T]]: """Filter the part_info dict looking for instances of our class Args: part_info (dict): {part_name: [Info] or None} as returned from Controller.run_hook() Returns: dict: {part_name: [info]} where info is a subclass of cls """ filtered = OrderedDict() for part_name, info_list in part_info.items(): if info_list is None or isinstance(info_list, Exception): continue info_list = [i for i in info_list if isinstance(i, cls)] if info_list: filtered[part_name] = info_list return filtered
[docs] @classmethod def filter_values(cls: Type[T], part_info: PartInfo) -> List[T]: """Filter the part_info dict list looking for instances of our class Args: part_info (dict): {part_name: [Info] or None} as returned from Controller.run_hook() Returns: list: [info] where info is a subclass of cls """ filtered: List[T] = [] info_list: Sequence assert hasattr(cls, "filter_parts"), "Class has no filter parts method" for info_list in cls.filter_parts(part_info).values(): filtered += info_list return filtered
[docs] @classmethod def filter_single_value( cls: Type[T], part_info: PartInfo, error_msg: str = None ) -> T: """Filter the part_info dict list looking for a single instance of our class Args: part_info (dict): {part_name: [Info] or None} as returned from Controller.run_hook() error_msg (str): Optional specific error message to show if there isn't a single value Returns: info subclass of cls """ assert hasattr(cls, "filter_values"), "Class has no filter values method" filtered: List[T] = cls.filter_values(part_info) if len(filtered) != 1: if error_msg is None: error_msg = ( f"Expected a single {cls.__name__}, got {len(filtered)} of them" ) raise BadValueError(error_msg) return filtered[0]