Coverage for src/blob_dict/dict/multi_replica.py: 0%
64 statements
« prev ^ index » next coverage.py v7.8.1, created at 2025-05-29 23:07 -0700
« prev ^ index » next coverage.py v7.8.1, created at 2025-05-29 23:07 -0700
1from collections.abc import Iterator
2from typing import Any, Literal, override
4from ..blob import BytesBlob
5from . import BlobDictBase
8class MultiReplicaBlobDict(BlobDictBase):
9 def __init__(
10 self,
11 replica_dicts: dict[str, BlobDictBase],
12 ) -> None:
13 super().__init__()
15 self.__replica_dicts: dict[str, BlobDictBase] = replica_dicts
16 self.__primary_dict: BlobDictBase = next(iter(replica_dicts.values()))
18 @override
19 def __len__(self) -> int:
20 return len(self.__primary_dict)
22 def len(
23 self,
24 *,
25 replica_name: str | None = None,
26 ) -> int:
27 return len(
28 self.__replica_dicts[replica_name] if replica_name
29 else self.__primary_dict,
30 )
32 @override
33 def __contains__(self, key: Any) -> bool:
34 return self.contains(str(key))
36 def contains(
37 self,
38 key: str,
39 *,
40 replica_names: set[str] | None = None,
41 ) -> bool:
42 return any(
43 key in self.__replica_dicts[replica_name]
44 for replica_name in (
45 self.__replica_dicts.keys() if replica_names is None
46 else replica_names
47 )
48 )
50 @override
51 def get[T: Any](
52 self,
53 key: str,
54 /,
55 default: BytesBlob | T = None,
56 *,
57 replica_names: set[str] | None = None,
58 ) -> BytesBlob | T:
59 for replica_name in (
60 self.__replica_dicts.keys() if replica_names is None
61 else replica_names
62 ):
63 replica_dict: BlobDictBase = self.__replica_dicts[replica_name]
64 blob: BytesBlob | None
65 if blob := replica_dict.get(key):
66 return blob
68 return default
70 @override
71 def __getitem__(self, key: str, /) -> BytesBlob:
72 blob: BytesBlob | None = self.get(key)
73 if blob is None:
74 raise KeyError
76 return blob
78 @override
79 def __iter__(self) -> Iterator[str]:
80 yield from (
81 key for key in self.__primary_dict
82 )
84 def iter(
85 self,
86 *,
87 replica_name: str | None = None,
88 ) -> Iterator[str]:
89 yield from (
90 key for key in (
91 self.__replica_dicts[replica_name] if replica_name
92 else self.__primary_dict
93 )
94 )
96 @override
97 def clear(
98 self,
99 *,
100 replica_names: set[str] | None = None,
101 ) -> None:
102 for replica_name in (
103 self.__replica_dicts.keys() if replica_names is None
104 else replica_names
105 ):
106 replica_dict: BlobDictBase = self.__replica_dicts[replica_name]
107 replica_dict.clear()
109 @override
110 def pop[T: Any](
111 self,
112 key: str,
113 /,
114 default: BytesBlob | T | Literal["__DEFAULT"] = "__DEFAULT",
115 *,
116 replica_names: set[str] | None = None,
117 ) -> BytesBlob | T:
118 final_blob: BytesBlob | None = None
119 for replica_name in (
120 self.__replica_dicts.keys() if replica_names is None
121 else replica_names
122 ):
123 replica_dict: BlobDictBase = self.__replica_dicts[replica_name]
124 if (blob := replica_dict.pop(key, None)) and not final_blob:
125 final_blob = blob
127 if final_blob:
128 return final_blob
130 if default == "__DEFAULT":
131 raise KeyError
133 return default
135 @override
136 def __delitem__(self, key: str, /) -> None:
137 if key not in self:
138 raise KeyError
140 self.pop(key)
142 @override
143 def __setitem__(
144 self,
145 key: str,
146 blob: BytesBlob,
147 /,
148 *,
149 replica_names: set[str] | None = None,
150 ) -> None:
151 for replica_name in (
152 self.__replica_dicts.keys() if replica_names is None
153 else replica_names
154 ):
155 replica_dict: BlobDictBase = self.__replica_dicts[replica_name]
156 replica_dict[key] = blob