66 lines
2.2 KiB
Python
66 lines
2.2 KiB
Python
from collections.abc import MutableMapping
|
|
from collections.abc import MutableSequence
|
|
|
|
from . import events as e
|
|
from .container import HookedContainer
|
|
from .container import MutableNesting
|
|
from .events import HookFunction
|
|
from .mixins import MutableMappingMixin
|
|
|
|
|
|
class HookedMapping[T](MutableMappingMixin[T, MutableNesting[T]], HookedContainer[T]):
|
|
_data: MutableMapping[T, MutableNesting[T]]
|
|
|
|
def __init__(
|
|
self,
|
|
existing: MutableMapping[T, MutableNesting[T]],
|
|
hook: HookFunction | None = None,
|
|
root: MutableMapping[T] | None = None,
|
|
path: MutableSequence[int] | None = None,
|
|
):
|
|
match existing:
|
|
case HookedMapping(_data=seq):
|
|
self._data = seq
|
|
case MutableMapping() as seq:
|
|
self._data = seq
|
|
case _:
|
|
raise TypeError(f"Expected a mapping, got {type(existing)}")
|
|
# self._data = dict(it)
|
|
self.hook = hook
|
|
self._root = root if root is not None else self
|
|
self._path = list(path) if path is not None else []
|
|
|
|
def __wrap_sub__(self, other, **kwargs):
|
|
return HookedMapping(other, hook=self.hook, root=self._root, **kwargs)
|
|
|
|
def __getitem__(self, key: T) -> MutableNesting[T]:
|
|
if key not in self._data:
|
|
return self.__wrap_sub__(self.__setitem__(key, {}), path=self.new_path(key))
|
|
value = self._data[key]
|
|
match value:
|
|
case MutableMapping() as mapping:
|
|
return self.__wrap_sub__(mapping, path=self.new_path(key))
|
|
case _ as item:
|
|
return item
|
|
|
|
def __setitem__(
|
|
self,
|
|
key: T,
|
|
value: MutableNesting[T],
|
|
*,
|
|
suppress_hook: bool = False,
|
|
) -> MutableNesting[T] | None:
|
|
match value:
|
|
case HookedMapping(_data=data):
|
|
event_type = e.SetItemEvent if key in self._data else e.AddItemEvent
|
|
self._data[key] = data
|
|
if not suppress_hook:
|
|
self._notify(event_type, key, value)
|
|
return data
|
|
case _:
|
|
if suppress_hook:
|
|
self._data[key] = value
|
|
else:
|
|
super().__setitem__(key, value)
|
|
return value
|