diff --git a/pottery/__init__.py b/pottery/__init__.py index b7e94834..c64ae901 100644 --- a/pottery/__init__.py +++ b/pottery/__init__.py @@ -32,7 +32,7 @@ __title__: Final[str] = 'pottery' -__version__: Final[str] = '2.3.6' +__version__: Final[str] = '2.3.7' __description__: Final[str] = __doc__.split(sep='\n\n', maxsplit=1)[0] __url__: Final[str] = 'https://github.com/brainix/pottery' __author__: Final[str] = 'Rajiv Bakulesh Shah' diff --git a/pottery/bloom.py b/pottery/bloom.py index b95a1ed5..7b7ad7a1 100644 --- a/pottery/bloom.py +++ b/pottery/bloom.py @@ -34,8 +34,8 @@ from typing_extensions import final from .annotations import F +from .annotations import JSONTypes from .base import Container -from .base import JSONTypes # TODO: When we drop support for Python 3.7, stop using @_store_on_self(). Use diff --git a/pottery/cache.py b/pottery/cache.py index 7e42f560..f9f31e2b 100644 --- a/pottery/cache.py +++ b/pottery/cache.py @@ -29,8 +29,11 @@ from typing import Collection from typing import Hashable from typing import Iterable +from typing import Mapping from typing import NamedTuple +from typing import Tuple from typing import TypeVar +from typing import Union from typing import cast from redis import Redis @@ -39,15 +42,20 @@ # from typing import Final from typing_extensions import Final -from .base import JSONTypes +from .annotations import JSONTypes from .base import _default_redis from .base import logger from .base import random_key -from .dict import InitArg -from .dict import InitIter from .dict import RedisDict +F = TypeVar('F', bound=Callable[..., JSONTypes]) + +UpdateMap = Mapping[JSONTypes, Union[JSONTypes, object]] +UpdateItem = Tuple[JSONTypes, Union[JSONTypes, object]] +UpdateIter = Iterable[UpdateItem] +UpdateArg = Union[UpdateMap, UpdateIter] + _DEFAULT_TIMEOUT: Final[int] = 60 # seconds @@ -68,9 +76,6 @@ def _arg_hash(*args: Hashable, **kwargs: Hashable) -> int: return hash((args, kwargs_items)) -F = TypeVar('F', bound=Callable[..., JSONTypes]) - - def redis_cache(*, # NoQA: C901 redis: Redis | None = None, key: str | None = None, @@ -248,13 +253,14 @@ def __init__(self, ) for dict_key, encoded_value in zip(dict_keys, encoded_values): if encoded_value is None: - value = self._SENTINEL self._misses.add(dict_key) + value = self._SENTINEL else: value = self._cache._decode(encoded_value) item = (dict_key, value) items.append(item) - return super().__init__(items) + super().__init__() + self.__update(items) def misses(self) -> Collection[JSONTypes]: return frozenset(self._misses) @@ -265,7 +271,7 @@ def __setitem__(self, value: JSONTypes | object, ) -> None: 'Set self[dict_key] to value.' - if value is not self._SENTINEL: + if value is not self._SENTINEL: # pragma: no cover self._cache[dict_key] = value self._misses.discard(dict_key) return super().__setitem__(dict_key, value) @@ -318,24 +324,29 @@ def __retry(self, callable: Callable[[], Any], *, try_num: int = 0) -> Any: raise @_set_expiration - def update(self, arg: InitArg = tuple(), **kwargs: JSONTypes) -> None: # type: ignore + def update(self, # type: ignore + arg: UpdateArg = tuple(), + **kwargs: JSONTypes | object, + ) -> None: '''D.update([E, ]**F) -> None. Update D from dict/iterable E and F. If E is present and has an .items() method, then does: for k in E: D[k] = E[k] If E is present and lacks an .items() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k] The base class, OrderedDict, has an .update() method that works just - fine. The trouble is that it executes multiple calls to .__setitem__() - therefore multiple round trips to Redis. This overridden .update() - makes a single bulk call to Redis. + fine. The trouble is that it executes multiple calls to + self.__setitem__() therefore multiple round trips to Redis. This + overridden .update() makes a single bulk call to Redis. ''' to_cache = {} if isinstance(arg, collections.abc.Mapping): arg = arg.items() - items = itertools.chain(cast(InitIter, arg), kwargs.items()) + items = itertools.chain(arg, kwargs.items()) for dict_key, value in items: if value is not self._SENTINEL: to_cache[dict_key] = value - self._misses.discard(dict_key) + self._misses.discard(cast(JSONTypes, dict_key)) super().__setitem__(dict_key, value) self._cache.update(to_cache) + + __update = update diff --git a/pottery/counter.py b/pottery/counter.py index 70bc6d80..72324dcc 100644 --- a/pottery/counter.py +++ b/pottery/counter.py @@ -36,7 +36,7 @@ from redis.client import Pipeline from typing_extensions import Counter -from .base import JSONTypes +from .annotations import JSONTypes from .dict import RedisDict diff --git a/pottery/deque.py b/pottery/deque.py index 5cf052f7..6df1160d 100644 --- a/pottery/deque.py +++ b/pottery/deque.py @@ -29,7 +29,7 @@ from redis import Redis from redis.client import Pipeline -from .base import JSONTypes +from .annotations import JSONTypes from .exceptions import InefficientAccessWarning from .list import RedisList diff --git a/pottery/dict.py b/pottery/dict.py index 0833523e..508b44c7 100644 --- a/pottery/dict.py +++ b/pottery/dict.py @@ -35,9 +35,9 @@ from redis import Redis from redis.client import Pipeline +from .annotations import JSONTypes from .base import Container from .base import Iterable_ -from .base import JSONTypes from .exceptions import InefficientAccessWarning from .exceptions import KeyExistsError diff --git a/pottery/hyper.py b/pottery/hyper.py index 59a51d21..c28ee6f9 100644 --- a/pottery/hyper.py +++ b/pottery/hyper.py @@ -31,9 +31,9 @@ from redis import Redis +from .annotations import JSONTypes from .annotations import RedisValues from .base import Container -from .base import JSONTypes from .base import random_key diff --git a/pottery/list.py b/pottery/list.py index b834094a..1267d137 100644 --- a/pottery/list.py +++ b/pottery/list.py @@ -42,8 +42,8 @@ from typing_extensions import final from .annotations import F +from .annotations import JSONTypes from .base import Container -from .base import JSONTypes from .exceptions import InefficientAccessWarning from .exceptions import KeyExistsError diff --git a/pottery/queue.py b/pottery/queue.py index 57be8fbf..48adb93e 100644 --- a/pottery/queue.py +++ b/pottery/queue.py @@ -29,8 +29,8 @@ from redis import WatchError +from .annotations import JSONTypes from .base import Container -from .base import JSONTypes from .exceptions import QueueEmptyError from .timer import ContextTimer diff --git a/pottery/set.py b/pottery/set.py index bd712c44..ce897a12 100644 --- a/pottery/set.py +++ b/pottery/set.py @@ -35,9 +35,9 @@ from redis.client import Pipeline from typing_extensions import Literal +from .annotations import JSONTypes from .base import Container from .base import Iterable_ -from .base import JSONTypes from .exceptions import InefficientAccessWarning from .exceptions import KeyExistsError