Compare commits

...

2 Commits

Author SHA1 Message Date
John Lancaster
89f533d9bf pruning 2026-02-21 19:01:03 -06:00
John Lancaster
2405d670fb broke apart 2026-02-21 19:00:10 -06:00
4 changed files with 93 additions and 64 deletions

View File

@@ -0,0 +1,33 @@
from collections.abc import Callable, MutableSequence
from typing import Generic, TypeVar
from . import events as e
T = TypeVar("T")
class HookedContainer(Generic[T]):
_path: MutableSequence[int]
hook: Callable[[e.ChangeEvent[T]], None] | None
def __repr__(self):
return f"{self.__class__.__name__}({self._data!r})"
def __len__(self):
return len(self._data)
def __iter__(self):
return iter(self._data)
def __contains__(self, value):
return value in self._data
def __setitem__(self, s, value):
self._data[s] = value
if self.hook:
self.hook(e.SetItemEvent(index=s, item=value))
def __delitem__(self, s):
del self._data[s]
if self.hook:
self.hook(e.RemoveItemEvent(index=s, item=self._data[s]))

View File

@@ -0,0 +1,24 @@
from dataclasses import dataclass
from typing import Generic, TypeVar
T = TypeVar("T")
@dataclass(frozen=True)
class ChangeEvent(Generic[T]):
index: int
@dataclass(frozen=True)
class AddItemEvent(ChangeEvent[T]):
item: T
@dataclass(frozen=True)
class SetItemEvent(ChangeEvent[T]):
item: T
@dataclass(frozen=True)
class RemoveItemEvent(ChangeEvent[T]):
item: T

View File

@@ -0,0 +1,20 @@
from collections.abc import Callable, MutableMapping, MutableSequence, Sequence
from typing import Generic, TypeVar
from . import events as e
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
def __init__(self, hook, existing: MutableMapping[T], 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

View File

@@ -1,85 +1,37 @@
from collections.abc import Callable, Iterable, MutableSequence, Sequence
from dataclasses import dataclass
from enum import Enum, auto
from typing import Generic, TypeVar
from collections.abc import Iterable, MutableSequence, Sequence
from copy import copy
from typing import TypeVar
from . import events as e
from .common import HookedContainer
T = TypeVar("T")
class ListChange(Enum):
ADD_ITEM = auto()
REMOVE_ITEM = auto()
SET_ITEM = auto()
@dataclass(frozen=True)
class ChangeEvent(Generic[T]):
index: int
@dataclass(frozen=True)
class AddItemEvent(ChangeEvent[T]):
item: T
@dataclass(frozen=True)
class SetItemEvent(ChangeEvent[T]):
item: T
@dataclass(frozen=True)
class RemoveItemEvent(ChangeEvent[T]):
item: T
class HookedList(Generic[T], MutableSequence[T]):
class HookedList(HookedContainer[T], MutableSequence[T]):
_data: MutableSequence[T]
_path: MutableSequence[int]
hook: Callable[[ChangeEvent[T]], None] | None
def __init__(self, iterable: Iterable[T], path: Sequence[int] | None = None, *, hook=None):
match iterable:
def __init__(self, hook, existing: Iterable[T], path: Sequence[int] | None = None):
self.hook = hook
match existing:
case MutableSequence() as seq:
self._data = seq
case Iterable() as it:
case _ as it:
self._data = list(it)
self._path = list(path) if path is not None else []
self.hook = hook
def __repr__(self):
return f"{self.__class__.__name__}({self._data!r})"
def __iter__(self):
return iter(self._data)
def __contains__(self, value):
return value in self._data
def __len__(self):
return len(self._data)
def __getitem__(self, s):
# print("Getting item:", s)
match self._data[s]:
case HookedList() as hs:
hs.hook = self.hook
return hs
case MutableSequence() as seq:
return HookedList(seq, hook=self.hook)
new_path = copy(self._path)
new_path.append(s)
# print(new_path)
return HookedList(self.hook, existing=seq, path=new_path)
case _ as item:
return item
def __setitem__(self, s, value):
self._data[s] = value
if self.hook:
self.hook(SetItemEvent(index=s, item=value))
def __delitem__(self, s):
del self._data[s]
if self.hook:
self.hook(RemoveItemEvent(index=s, item=self._data[s]))
def insert(self, index, value):
self._data.insert(index, value)
if self.hook:
self.hook(AddItemEvent(index=index, item=value))
self.hook(e.AddItemEvent(index=index, item=value))