from collections.abc import MutableMapping, MutableSequence, Sequence from copy import copy from typing import TypeVar from .common import HookedContainer from .sequence import HookedList T = TypeVar("T") class HookedMapping(HookedContainer[T], MutableMapping[T, T | MutableSequence[T] | MutableMapping]): _data: MutableMapping[T, T | MutableSequence[T] | MutableMapping] def __init__( self, hook, existing: MutableMapping[T, T | MutableSequence[T] | MutableMapping], path: Sequence[int] | None = None, ): self.hook = hook self._data = existing self._path = list(path) if path is not None else [] def __getitem__(self, key: T) -> T | MutableSequence[T] | MutableMapping: value = self._data[key] match value: case MutableMapping() as mapping: new_path = copy(self._path) new_path.append(key) return HookedMapping(self.hook, existing=mapping, path=new_path) case MutableSequence() as seq: new_path = copy(self._path) new_path.append(key) return HookedList(self.hook, existing=seq, path=new_path) case _ as item: return item def __setitem__(self, key: T, value: T | MutableSequence[T] | MutableMapping) -> None: self._data[key] = value if self.hook: from . import events as e self.hook(e.SetItemEvent(index=key, item=value)) def __delitem__(self, key: T) -> None: item = self._data[key] del self._data[key] if self.hook: from . import events as e self.hook(e.RemoveItemEvent(index=key, item=item))