Source code for pyicat_plus.metadata.namespace_wrapper

from functools import partial
from typing import Callable, Iterable, Optional


[docs] class NamespaceWrapper: """Namespace which delegates attribute getting and setting to a getter and setter method.""" _PROPERTY_NAMES = () def __new__( cls, property_names: Iterable[str], getter: Callable, setter: Optional[Callable] = None, property_decorator: Optional[Callable] = None, ): cls = type(cls.__name__, (cls,), {}) if property_decorator is None: property_decorator = property property_names = tuple(sorted(property_names)) cls._PROPERTY_NAMES = property_names for key in property_names: prop = property_decorator(partial(NamespaceWrapper._getter, key=key)) if setter is not None: prop = prop.setter(partial(NamespaceWrapper._setter, key=key)) setattr(cls, key, prop) return object.__new__(cls) def __init__( self, property_names: Iterable[str], getter: Callable, setter: Optional[Callable] = None, property_decorator: Optional[Callable] = None, ): self.__property_names = property_names self.__getter = getter self.__setter = setter def __str__(self) -> str: if self._PROPERTY_NAMES: return "NameSpace:\n " + "\n ".join(self._PROPERTY_NAMES) else: return "NameSpace: <empty>" def __info__(self) -> str: # For the Bliss shell return str(self) def _getter(self, key): return self.__getter(key) def _setter(self, value, key): return self.__setter(key, value)
[docs] def get_content(self) -> str: if not self.__property_names: return "Namespace is empty" res = "Namespace contains:\n" max_len = max(len(s) for s in self.__property_names) key_fmt = f".%-{max_len}s" for key in self.__property_names: val = self._getter(key) if val: res += (key_fmt % key) + f" = {val!r}\n" else: res += (key_fmt % key) + "\n" return res