Coverage for src/blob_dict/dict/valkey.py: 0%
49 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-10 06:26 -0700
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-10 06:26 -0700
1from collections.abc import Iterator
2from datetime import timedelta
3from typing import Any, cast, override
5from valkey import Valkey
7from ..blob import BytesBlob, StrBlob
8from . import BlobDictBase
11class ValkeyBlobDict(BlobDictBase):
12 def __init__(
13 self,
14 *,
15 ttl: timedelta | None = None,
16 str_blob_only: bool = False,
17 client_kwargs: dict[str, Any] | None = None,
18 ) -> None:
19 super().__init__()
21 self.__client: Valkey = Valkey(
22 **(client_kwargs or {}),
23 decode_responses=True,
24 )
26 self.__ttl_ms: int | None = int(ttl.total_seconds() * 1_000) if ttl else None
28 self.__str_blob_only: bool = str_blob_only
30 @override
31 def __len__(self) -> int:
32 return cast("int", self.__client.dbsize())
34 @override
35 def __contains__(self, key: str) -> bool:
36 return cast("int", self.__client.exists(key)) == 1
38 @override
39 def get(self, key: str, default: BytesBlob | None = None) -> BytesBlob | None:
40 response: Any = self.__client.get(key)
41 if not response:
42 return default
44 s: str = cast("str", response)
45 return (
46 StrBlob(s) if self.__str_blob_only
47 else BytesBlob.from_b64_str(s)
48 )
50 @override
51 def __iter__(self) -> Iterator[str]:
52 for key in self.__client.scan_iter(_type="STRING"):
53 yield cast("str", key)
55 @override
56 def clear(self) -> None:
57 self.__client.flushdb()
59 @override
60 def pop(self, key: str, default: BytesBlob | None = None) -> BytesBlob | None:
61 if response := self.get(key):
62 self.__client.delete(key)
63 return response
65 return default
67 @override
68 def __delitem__(self, key: str) -> None:
69 number_deleted: int = cast("int", self.__client.delete(key))
70 if number_deleted == 0:
71 raise KeyError
73 __BAD_BLOB_CLASS_ERROR_MESSAGE: str = "Must specify blob of type `StrBlob`"
75 @override
76 def __setitem__(self, key: str, blob: BytesBlob) -> None:
77 if self.__str_blob_only and not isinstance(blob, StrBlob):
78 raise TypeError(self.__BAD_BLOB_CLASS_ERROR_MESSAGE)
80 self.__client.set(
81 key,
82 (
83 cast("StrBlob", blob).as_str() if self.__str_blob_only
84 else blob.as_b64_str()
85 ),
86 px=self.__ttl_ms,
87 )