diff options
Diffstat (limited to 'tools/cru-py/cru/_list.py')
-rw-r--r-- | tools/cru-py/cru/_list.py | 104 |
1 files changed, 51 insertions, 53 deletions
diff --git a/tools/cru-py/cru/_list.py b/tools/cru-py/cru/_list.py index f1965db..45122bf 100644 --- a/tools/cru-py/cru/_list.py +++ b/tools/cru-py/cru/_list.py @@ -1,77 +1,75 @@ +from __future__ import annotations +from collections.abc import Callable +from typing import Generic, Iterable, Self, TypeAlias, TypeVar +from ._iter import CruIterable -class CruInplaceList(CruList, Generic[_V]): +_T = TypeVar("_T") - def clear(self) -> "CruInplaceList[_V]": - self.clear() - return self - def extend(self, *l: Iterable[_V]) -> "CruInplaceList[_V]": - self.extend(l) - return self +class CruListEdit(CruIterable.Wrapper[_T]): + def done(self) -> CruList[_T]: + l: CruList[_T] = self.my_attr["list"] + l.reset(self) + return l - def reset(self, *l: Iterable[_V]) -> "CruInplaceList[_V]": + +class CruList(list[_T]): + def reset(self, new_values: Iterable[_T]): + if self is new_values: + new_values = list(new_values) self.clear() - self.extend(l) + self.extend(new_values) return self - def transform(self, *f: OptionalElementTransformer) -> "CruInplaceList"[Any]: - return self.reset(super().transform(*f)) - - def transform_if( - self, f: OptionalElementTransformer, p: ElementPredicate[_V] - ) -> "CruInplaceList"[Any]: - return self.reset(super().transform_if(f, p)) + def as_iterable_wrapper(self) -> CruIterable.Wrapper[_T]: + return CruIterable.Wrapper(self) - def remove_by_indices(self, *index: int) -> "CruInplaceList"[_V]: - return self.reset(super().remove_by_indices(*index)) - - def remove_all_if(self, p: ElementPredicate[_V]) -> "CruInplaceList"[_V]: - return self.reset(super().remove_all_if(p)) - - def remove_all_value(self, *r: Any) -> "CruInplaceList"[_V]: - return self.reset(super().remove_all_value(*r)) - - def replace_all_value( - self, old_value: Any, new_value: R - ) -> "CruInplaceList"[_V | R]: - return self.reset(super().replace_all_value(old_value, new_value)) + def as_edit_iterable_wrapper(self) -> CruListEdit[_T]: + return CruListEdit(self, attr={"list": self}) @staticmethod - def make(l: CanBeList[_V]) -> "CruInplaceList"[_V]: - return CruInplaceList(ListOperations.make(l)) - + def make(maybe_list: Iterable[_T] | _T | None) -> CruList[_T]: + if maybe_list is None: + return CruList() + if isinstance(maybe_list, Iterable): + return CruList(maybe_list) + return CruList([maybe_list]) -K = TypeVar("K") +_K = TypeVar("_K") +_KeyGetter: TypeAlias = Callable[[_T], _K] -class CruUniqueKeyInplaceList(Generic[_V, K]): - KeyGetter = Callable[[_V], K] +class CruUniqueKeyList(Generic[_T, _K]): def __init__( - self, get_key: KeyGetter, *, before_add: Callable[[_V], _V] | None = None + self, + key_getter: _KeyGetter[_T, _K], + *, + before_add: Callable[[_T], _T] | None = None, ): super().__init__() - self._get_key = get_key + self._key_getter = key_getter self._before_add = before_add - self._l: CruInplaceList[_V] = CruInplaceList() + self._list: CruList[_T] = CruList() @property - def object_key_getter(self) -> KeyGetter: - return self._get_key + def key_getter(self) -> _KeyGetter[_T, _K]: + return self._key_getter @property - def internal_list(self) -> CruInplaceList[_V]: - return self._l + def internal_list(self) -> CruList[_T]: + return self._list def validate_self(self): - keys = self._l.transform(self._get_key) + keys = self._list.transform(self._key_getter) if len(keys) != len(set(keys)): raise ValueError("Duplicate keys!") - def get_or(self, k: K, fallback: Any = CRU_NOT_FOUND) -> _V | Any: - r = self._l.find_if(lambda i: k == self._get_key(i)) + # TODO: Continue here! + def get_or(self, key: K, fallback: Any = CRU_NOT_FOUND) -> _V | Any: + r = self._l.find_if(lambda i: k == self._key_getter(i)) return r if r is not CRU_NOT_FOUND else fallback def get(self, k: K) -> _V: @@ -84,10 +82,10 @@ class CruUniqueKeyInplaceList(Generic[_V, K]): return self.get_or(k, CRU_NOT_FOUND) is not CRU_NOT_FOUND def has_any_key(self, *k: K) -> bool: - return self._l.any(lambda i: self._get_key(i) in k) + return self._l.any(lambda i: self._key_getter(i) in k) def try_remove(self, k: K) -> bool: - i = self._l.find_index_if(lambda v: k == self._get_key(v)) + i = self._l.find_index_if(lambda v: k == self._key_getter(v)) if i is CRU_NOT_FOUND: return False self._l.remove_by_indices(i) @@ -98,11 +96,11 @@ class CruUniqueKeyInplaceList(Generic[_V, K]): raise KeyError(f"Key {k} not found!") def add(self, v: _V, /, replace: bool = False) -> None: - if self.has_key(self._get_key(v)): + if self.has_key(self._key_getter(v)): if replace: - self.remove(self._get_key(v)) + self.remove(self._key_getter(v)) else: - raise ValueError(f"Key {self._get_key(v)} already exists!") + raise ValueError(f"Key {self._key_getter(v)} already exists!") if self._before_add is not None: v = self._before_add(v) self._l.append(v) @@ -111,12 +109,12 @@ class CruUniqueKeyInplaceList(Generic[_V, K]): self.add(v, True) def extend(self, l: Iterable[_V], /, replace: bool = False) -> None: - if not replace and self.has_any_key([self._get_key(i) for i in l]): + if not replace and self.has_any_key([self._key_getter(i) for i in l]): raise ValueError("Keys already exists!") if self._before_add is not None: l = [self._before_add(i) for i in l] - keys = [self._get_key(i) for i in l] - self._l.remove_all_if(lambda i: self._get_key(i) in keys).extend(l) + keys = [self._key_getter(i) for i in l] + self._l.remove_all_if(lambda i: self._key_getter(i) in keys).extend(l) def clear(self) -> None: self._l.clear() |