This commit is contained in:
John Lancaster
2026-02-22 21:44:06 -06:00
parent 0c3dfde336
commit 66b4c1274f
2 changed files with 19 additions and 7 deletions

View File

@@ -1,15 +1,18 @@
from __future__ import annotations
from collections.abc import MutableSequence
from dataclasses import dataclass, field
from typing import Generic, Protocol, TypeVar
from typing import TYPE_CHECKING, Generic, Protocol, TypeVar
from .types import MutableNesting
if TYPE_CHECKING:
from .mapping import HookedMapping
T = TypeVar("T")
@dataclass(frozen=True)
class ChangeEvent(Generic[T]):
root: MutableNesting[T] = field(repr=False)
root: HookedMapping[T] = field(repr=False)
path: MutableSequence[int]
item: T

View File

@@ -15,6 +15,7 @@ class HookedMapping(HookedContainer[T], MutableMapping[T, MutableNesting[T]]):
self,
existing: MutableMapping[T, MutableNesting[T]],
hook: HookFunction | None = None,
root: MutableMapping[T] | None = None,
path: MutableSequence[int] | None = None,
):
match existing:
@@ -27,15 +28,19 @@ class HookedMapping(HookedContainer[T], MutableMapping[T, MutableNesting[T]]):
# self._data = dict(it)
self._data = existing
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 HookedMapping(self.__setitem__(key, {}), hook=self.hook, path=self.new_path(key))
return self.__wrap_sub__(self.__setitem__(key, {}), path=self.new_path(key))
value = self._data[key]
match value:
case MutableMapping() as mapping:
return HookedMapping(mapping, hook=self.hook, path=self.new_path(key))
return self.__wrap_sub__(mapping, path=self.new_path(key))
case _ as item:
return item
@@ -47,7 +52,11 @@ class HookedMapping(HookedContainer[T], MutableMapping[T, MutableNesting[T]]):
suppress_hook: bool = False,
) -> MutableNesting[T] | None:
new_path = self.new_path(key)
event = e.SetItemEvent(self, new_path, value) if key in self._data else e.AddItemEvent(self, new_path, value)
event = (
e.SetItemEvent(self._root, new_path, value)
if key in self._data
else e.AddItemEvent(self._root, new_path, value)
)
match value:
case HookedMapping(_data=value):
self._data[key] = value
@@ -60,4 +69,4 @@ class HookedMapping(HookedContainer[T], MutableMapping[T, MutableNesting[T]]):
def __delitem__(self, key: T) -> None:
item = self._data.pop(key)
if self.hook:
self.hook(e.RemoveItemEvent(self, self.new_path(key), item))
self.hook(e.RemoveItemEvent(self._root, self.new_path(key), item))