Source code for tensorial.gcnn.utils

import collections.abc
import logging

from ._tree import path_from_str, path_to_str

__all__ = "UpdateDict", "path_from_str", "path_to_str"

_LOGGER = logging.getLogger(__name__)


[docs] class UpdateDict(collections.abc.MutableMapping): """This class can be used to make updates to a dictionary without modifying the passed dictionary. Once all the updates are made, a new dictionary that is the result of the modifications can be retrieved using the `_asdict()` method. """ DELETED = tuple() # Just a token we use to indicate a deleted value def __init__(self, updating: dict): super().__init__() self._updating = updating self._overrides = {} def __getitem__(self, item): try: value = self._overrides[item] except KeyError: pass else: if value is self.DELETED: raise KeyError(item) return value value = self._updating.__getitem__(item) if type(value) is dict: # pylint: disable=unidiomatic-typecheck value = UpdateDict(value) self._overrides[item] = value return value def __setitem__(self, key, value): self._overrides[key] = value def __delitem__(self, key): self._overrides[key] = self.DELETED def __iter__(self): for key in self._updating.__iter__(): try: value = self._overrides[key] except KeyError: yield key else: if value is not self.DELETED: yield key def __len__(self): return len(self._updating) - len( list(filter(lambda val: val is self.DELETED, self._overrides.values())) ) def _asdict(self) -> dict: self_dict = dict(self._updating) for key, value in self._overrides.items(): if value is self.DELETED: del self_dict[key] elif isinstance(value, UpdateDict): self_dict[key] = value._asdict() else: self_dict[key] = value return self_dict