diff --git a/src/hooked_containers/mapping.py b/src/hooked_containers/mapping.py index 08dbfda..ebd3507 100644 --- a/src/hooked_containers/mapping.py +++ b/src/hooked_containers/mapping.py @@ -1,20 +1,51 @@ -from collections.abc import Callable, MutableMapping, MutableSequence, Sequence -from typing import Generic, TypeVar +from collections.abc import MutableMapping, MutableSequence, Sequence +from copy import copy +from typing import TypeVar -from . import events as e +from .common import HookedContainer +from .sequence import HookedList T = TypeVar("T") -class HookedMapping(Generic[T], MutableMapping[T, T | MutableSequence[T], MutableMapping[T]]): - _data: MutableSequence[T] - _path: MutableSequence[int] - hook: Callable[[e.ChangeEvent[T]], None] | None +class HookedMapping(HookedContainer[T], MutableMapping[T, T | MutableSequence[T] | MutableMapping]): + _data: MutableMapping[T, T | MutableSequence[T] | MutableMapping] - def __init__(self, hook, existing: MutableMapping[T], path: Sequence[int] | None = None): + 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 __setitem__(self, key): - return + 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))