type annotations, NotFoundError

This commit is contained in:
Yusur 2025-07-24 11:44:24 +02:00
parent 002dbb0579
commit 589d4b3b13
3 changed files with 21 additions and 11 deletions

View file

@ -4,7 +4,8 @@
+ `sqlalchemy`: add `unbound_fk()`, `bound_fk()` + `sqlalchemy`: add `unbound_fk()`, `bound_fk()`
+ Add `timed_cache()`, `TimedDict()` + Add `timed_cache()`, `TimedDict()`
+ Move obsolete stuff to `obsolete` package + Move obsolete stuff to `obsolete` package (includes configparse 0.3 as of now)
+ Add more exceptions: `NotFoundError()`
## 0.4.0 ## 0.4.0

View file

@ -18,12 +18,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
from __future__ import annotations from __future__ import annotations
import time import time
from typing import TypeVar from typing import Iterator, TypeVar
_KT = TypeVar('_KT') _KT = TypeVar('_KT')
_VT = TypeVar('_VT')
class TimedDict(dict): class TimedDict(dict[_KT, _VT]):
"""
Dictionary where keys expire after the defined time to live, expressed in seconds.
"""
_expires: dict[_KT, int] _expires: dict[_KT, int]
_ttl: int _ttl: int
@ -32,7 +36,7 @@ class TimedDict(dict):
self._ttl = ttl self._ttl = ttl
self._expires = dict() self._expires = dict()
def check_ex(self, key): def check_ex(self, key: _KT):
if super().__contains__(key): if super().__contains__(key):
ex = self._expires[key] ex = self._expires[key]
now = int(time.time()) now = int(time.time())
@ -42,28 +46,28 @@ class TimedDict(dict):
elif key in self._expires: elif key in self._expires:
del self._expires[key] del self._expires[key]
def __getitem__(self, key: _KT, /): def __getitem__(self, key: _KT, /) -> _VT:
self.check_ex(key) self.check_ex(key)
return super().__getitem__(key) return super().__getitem__(key)
def get(self, key, default=None, /): def get(self, key: _KT, default: _VT | None = None, /) -> _VT | None:
self.check_ex(key) self.check_ex(key)
return super().get(key) return super().get(key)
def __setitem__(self, key: _KT, value, /) -> None: def __setitem__(self, key: _KT, value: _VT, /) -> None:
self._expires = int(time.time() + self._ttl) self._expires = int(time.time() + self._ttl)
super().__setitem__(key, value) super().__setitem__(key, value)
def setdefault(self, key, default, /): def setdefault(self, key: _KT, default: _VT, /) -> _VT:
self.check_ex(key) self.check_ex(key)
self._expires = int(time.time() + self._ttl) self._expires = int(time.time() + self._ttl)
return super().setdefault(key, default) return super().setdefault(key, default)
def __delitem__(self, key, /): def __delitem__(self, key: _KT, /) -> None:
del self._expires[key] del self._expires[key]
super().__delitem__(key) super().__delitem__(key)
def __iter__(self): def __iter__(self) -> Iterator[_KT]:
for k in super(): for k in super():
self.check_ex(k) self.check_ex(k)
return super().__iter__() return super().__iter__()

View file

@ -41,6 +41,11 @@ class InconsistencyError(RuntimeError):
This program is in a state which it's not supposed to be in. This program is in a state which it's not supposed to be in.
""" """
class NotFoundError(LookupError):
"""
The requested item was not found.
"""
__all__ = ( __all__ = (
'MissingConfigError', 'MissingConfigWarning', 'LexError', 'InconsistencyError' 'MissingConfigError', 'MissingConfigWarning', 'LexError', 'InconsistencyError', 'NotFoundError'
) )