class Dict(Clearable, Generic[DictItem]):
- 'Customized dict replacement.'
+ 'Reduced dict only allowing one item type, communicated in ._item_cls.'
def __init__(self, **kwargs) -> None:
self._dict: dict[str, DictItem] = {}
super().__init__(**kwargs)
- def __getattribute__(self, key: str):
- if key in {'items', 'keys', 'values'}:
- return getattr(self._dict, key)
- return super().__getattribute__(key)
-
- def __getitem__(self, key: str) -> DictItem:
- return self._dict[key]
-
- def clear(self) -> None:
- self._dict.clear()
-
@property
def _item_cls(self):
orig_cls = (self.__orig_class__ if hasattr(self, '__orig_class__')
else self.__orig_bases__[0])
return orig_cls.__args__[0]
+ # NB: Some of below wrappers around ._dict method calls were previously
+ # replaced by .__getattribute__ simply returning getattr(self._dict, key).
+ # This however confused subclasses super() (which doesn't check instance's
+ # .__getattribute__ but looks at class method definitions), and wouldn't
+ # satisfy abstractmethod slots such as for Clearable.clear.
+
def __setitem__(self, key: str, val: DictItem) -> None:
assert isinstance(val, self._item_cls), (type(val), self._item_cls)
self._dict[key] = val
+ def __getitem__(self, key: str) -> DictItem:
+ return self._dict[key]
+
def __delitem__(self, key: str) -> None:
del self._dict[key]
+ def clear(self) -> None:
+ 'Wrapper around dict.clear().'
+ self._dict.clear()
+
+ def items(self) -> tuple[tuple[str, DictItem], ...]:
+ 'Wrapper around dict.values().'
+ return tuple(((key, val) for key, val in self._dict.items()))
+
+ def keys(self) -> tuple[str, ...]:
+ 'Wrapper around dict.keys().'
+ return tuple((key for key in self._dict))
+
+ def values(self) -> tuple[DictItem, ...]:
+ 'Wrapper around dict.values().'
+ return tuple((val for val in self._dict.values()))
+
class Completable(ABC):
'Data whose collection can be declared complete/incomplete.'