Source code for redditwarp.util.attribute_mapping_proxy

"""Mapping wrappers that allow dot access to mapping entires.

Examples:

::

    >>> d = AttributeMappingProxy({'foo': 'bar'})
    >>> d.foo
    'bar'

::

    >>> d = DictRecursiveAttributeMappingProxy({'foo': {'bar': 'baz'}})
    >>> d.foo.bar
    'baz'

::

    >>> d = DictAndListRecursiveAttributeMappingProxy({'foo': [1, 'bar', {'c': 3}]})
    >>> d.foo[2].c
    3
"""

from __future__ import annotations
from typing import Any, TypeVar, Mapping, Iterable, Iterator, IO, Sequence, overload, Union

from pprint import PrettyPrinter

V = TypeVar('V')

[docs]class AttributeMappingProxy(Mapping[str, V]): __slots__ = ('_store',) _store: Mapping[str, V] def __init__(self, mapping: Mapping[str, V]) -> None: object.__setattr__(self, '_store', mapping) def __repr__(self) -> str: return f'{self.__class__.__name__}({self._store})' def __dir__(self) -> Iterable[str]: return self.keys() def __contains__(self, item: object) -> bool: return item in self._store def __iter__(self) -> Iterator[str]: return iter(self._store) def __len__(self) -> int: return len(self._store) def __getitem__(self, key: str) -> V: return self._store[key] def __getattr__(self, name: str) -> Any: try: return self[name] except KeyError: raise AttributeError(repr(name)) from None def __abs__(self) -> Mapping[str, V]: return self._store def __getstate__(self) -> Mapping[str, V]: return self._store def __setstate__(self, state: Mapping[str, V]) -> None: object.__setattr__(self, '_store', state) @staticmethod def _pprint( printer: PrettyPrinter, obj: AttributeMappingProxy[V], stream: IO[str], indent: int, allowance: int, context: Mapping[int, Any], level: int, ) -> None: cls_name = obj.__class__.__name__ stream.write(cls_name + '(') printer._format( # type: ignore[attr-defined] dict(obj), stream, indent + len(cls_name) + 1, allowance + 1, context, level, ) stream.write(')') if isinstance(getattr(PrettyPrinter, '_dispatch', None), dict): PrettyPrinter._dispatch[__repr__] = _pprint.__func__ # type: ignore[attr-defined]
[docs]class MappingRecursiveAttributeMappingProxy(AttributeMappingProxy[V]): def __getattr__(self, name: str) -> Any: attr = super().__getattr__(name) if isinstance(attr, Mapping): return MappingRecursiveAttributeMappingProxy(attr) return attr
[docs]class DictRecursiveAttributeMappingProxy(AttributeMappingProxy[V]): def __getattr__(self, name: str) -> Any: attr = super().__getattr__(name) if isinstance(attr, dict): return DictRecursiveAttributeMappingProxy(attr) return attr
[docs]class ListProxy(Sequence[Any]): def __init__(self, data: Sequence[Any]) -> None: self._elements: Sequence[Any] = data def __repr__(self) -> str: return f'{self.__class__.__name__}({self._elements})' def __abs__(self) -> Sequence[Any]: return self._elements def __len__(self) -> int: return len(self._elements) def __contains__(self, item: object) -> bool: return item in self._elements def __iter__(self) -> Iterator[Any]: return iter(self._elements) @overload def __getitem__(self, index: int) -> Any: ... @overload def __getitem__(self, index: slice) -> Sequence[Any]: ... def __getitem__(self, index: Union[int, slice]) -> Union[Any, Sequence[Any]]: item = self._elements[index] if isinstance(item, dict): return DictAndListRecursiveAttributeMappingProxy(item) if isinstance(item, list): return self.__class__(item) return item @staticmethod def _pprint( printer: PrettyPrinter, obj: ListProxy, stream: IO[str], indent: int, allowance: int, context: Mapping[int, Any], level: int, ) -> None: cls_name = obj.__class__.__name__ stream.write(cls_name + '(') printer._format( # type: ignore[attr-defined] list(obj), stream, indent + len(cls_name) + 1, allowance + 1, context, level, ) stream.write(')') if isinstance(getattr(PrettyPrinter, '_dispatch', None), dict): PrettyPrinter._dispatch[__repr__] = _pprint.__func__ # type: ignore[attr-defined]
[docs]class DictAndListRecursiveAttributeMappingProxy(AttributeMappingProxy[V]): def __getattr__(self, name: str) -> Any: attr = super().__getattr__(name) if isinstance(attr, dict): return DictAndListRecursiveAttributeMappingProxy(attr) elif isinstance(attr, list): return ListProxy(attr) return attr