You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

212 lines
6.2 KiB

from typing import Any, Callable, Dict, Iterable, List, Set, SupportsIndex, Union, overload
from . import events
class ObservableDict(dict):
def __init__(self, data: Dict, on_change: Callable) -> None:
super().__init__(data)
for key, value in self.items():
super().__setitem__(key, make_observable(value, on_change))
self.on_change = lambda: events.handle_event(on_change, events.ObservableChangeEventArguments(sender=self))
def pop(self, k: Any, d: Any = None) -> Any:
item = super().pop(k, d)
self.on_change()
return item
def popitem(self) -> Any:
item = super().popitem()
self.on_change()
return item
def update(self, *args: Any, **kwargs: Any) -> None:
super().update(make_observable(dict(*args, **kwargs), self.on_change))
self.on_change()
def clear(self) -> None:
super().clear()
self.on_change()
def setdefault(self, __key: Any, __default: Any = None) -> Any:
item = super().setdefault(__key, make_observable(__default, self.on_change))
self.on_change()
return item
def __setitem__(self, __key: Any, __value: Any) -> None:
super().__setitem__(__key, make_observable(__value, self.on_change))
self.on_change()
def __delitem__(self, __key: Any) -> None:
super().__delitem__(__key)
self.on_change()
def __or__(self, other: Any) -> Any:
return super().__or__(other)
def __ior__(self, other: Any) -> Any:
super().__ior__(make_observable(dict(other), self.on_change))
self.on_change()
return self
class ObservableList(list):
def __init__(self, data: List, on_change: Callable) -> None:
super().__init__(data)
for i, item in enumerate(self):
super().__setitem__(i, make_observable(item, on_change))
self.on_change = lambda: events.handle_event(on_change, events.ObservableChangeEventArguments(sender=self))
def append(self, item: Any) -> None:
super().append(make_observable(item, self.on_change))
self.on_change()
def extend(self, iterable: Iterable) -> None:
super().extend(make_observable(list(iterable), self.on_change))
self.on_change()
def insert(self, index: SupportsIndex, obj: Any) -> None:
super().insert(index, make_observable(obj, self.on_change))
self.on_change()
def remove(self, value: Any) -> None:
super().remove(value)
self.on_change()
def pop(self, index: SupportsIndex = -1) -> Any:
item = super().pop(index)
self.on_change()
return item
def clear(self) -> None:
super().clear()
self.on_change()
def sort(self, **kwargs: Any) -> None:
super().sort(**kwargs)
self.on_change()
def reverse(self) -> None:
super().reverse()
self.on_change()
def __delitem__(self, key: Union[SupportsIndex, slice]) -> None:
super().__delitem__(key)
self.on_change()
def __setitem__(self, key: Union[SupportsIndex, slice], value: Any) -> None:
super().__setitem__(key, make_observable(value, self.on_change))
self.on_change()
def __add__(self, other: Any) -> Any:
return super().__add__(other)
def __iadd__(self, other: Any) -> Any:
super().__iadd__(make_observable(other, self.on_change))
self.on_change()
return self
class ObservableSet(set):
def __init__(self, data: set, on_change: Callable) -> None:
super().__init__(data)
for item in self:
super().add(make_observable(item, on_change))
self.on_change = lambda: events.handle_event(on_change, events.ObservableChangeEventArguments(sender=self))
def add(self, item: Any) -> None:
super().add(make_observable(item, self.on_change))
self.on_change()
def remove(self, item: Any) -> None:
super().remove(item)
self.on_change()
def discard(self, item: Any) -> None:
super().discard(item)
self.on_change()
def pop(self) -> Any:
item = super().pop()
self.on_change()
return item
def clear(self) -> None:
super().clear()
self.on_change()
def update(self, *s: Iterable[Any]) -> None:
super().update(make_observable(set(*s), self.on_change))
self.on_change()
def intersection_update(self, *s: Iterable[Any]) -> None:
super().intersection_update(*s)
self.on_change()
def difference_update(self, *s: Iterable[Any]) -> None:
super().difference_update(*s)
self.on_change()
def symmetric_difference_update(self, *s: Iterable[Any]) -> None:
super().symmetric_difference_update(*s)
self.on_change()
def __or__(self, other: Any) -> Any:
return super().__or__(other)
def __ior__(self, other: Any) -> Any:
super().__ior__(make_observable(other, self.on_change))
self.on_change()
return self
def __and__(self, other: Any) -> set:
return super().__and__(other)
def __iand__(self, other: Any) -> Any:
super().__iand__(make_observable(other, self.on_change))
self.on_change()
return self
def __sub__(self, other: Any) -> set:
return super().__sub__(other)
def __isub__(self, other: Any) -> Any:
super().__isub__(make_observable(other, self.on_change))
self.on_change()
return self
def __xor__(self, other: Any) -> set:
return super().__xor__(other)
def __ixor__(self, other: Any) -> Any:
super().__ixor__(make_observable(other, self.on_change))
self.on_change()
return self
@overload
def make_observable(data: Dict, on_change: Callable) -> ObservableDict:
...
@overload
def make_observable(data: List, on_change: Callable) -> ObservableList:
...
@overload
def make_observable(data: Set, on_change: Callable) -> ObservableSet:
...
def make_observable(data: Any, on_change: Callable) -> Any:
if isinstance(data, dict):
return ObservableDict(data, on_change)
if isinstance(data, list):
return ObservableList(data, on_change)
if isinstance(data, set):
return ObservableSet(data, on_change)
return data