Skip to content

Commit 18bf082

Browse files
authored
Merge branch 'main' into claude/issue-135-20251027-0057
2 parents 6a9455f + fd19290 commit 18bf082

File tree

8 files changed

+40
-14
lines changed

8 files changed

+40
-14
lines changed

key-value/key-value-aio/src/key_value/aio/stores/dynamodb/store.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ async def _put_managed_entry(
203203
}
204204

205205
# Add TTL if present
206-
if managed_entry.ttl is not None and managed_entry.created_at:
206+
if managed_entry.ttl is not None and managed_entry.created_at is not None:
207207
# DynamoDB TTL expects a Unix timestamp
208208
ttl_timestamp = int(managed_entry.created_at.timestamp() + managed_entry.ttl)
209209
item["ttl"] = {"N": str(ttl_timestamp)}

key-value/key-value-aio/src/key_value/aio/stores/memory/store.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,27 @@ async def _setup_collection(self, *, collection: str) -> None:
219219
collection_cache = MemoryCollection(max_entries=self.max_entries_per_collection)
220220
self._cache[collection] = collection_cache
221221

222+
def _get_collection_or_raise(self, collection: str) -> MemoryCollection:
223+
"""Get a collection or raise KeyError if not setup.
224+
225+
Args:
226+
collection: The collection name.
227+
228+
Returns:
229+
The MemoryCollection instance.
230+
231+
Raises:
232+
KeyError: If the collection has not been setup via setup_collection().
233+
"""
234+
collection_cache: MemoryCollection | None = self._cache.get(collection)
235+
if collection_cache is None:
236+
msg = f"Collection '{collection}' has not been setup. Call setup_collection() first."
237+
raise KeyError(msg)
238+
return collection_cache
239+
222240
@override
223241
async def _get_managed_entry(self, *, key: str, collection: str) -> ManagedEntry | None:
224-
collection_cache: MemoryCollection = self._cache[collection]
225-
242+
collection_cache = self._get_collection_or_raise(collection)
226243
return collection_cache.get(key=key)
227244

228245
@override
@@ -233,20 +250,17 @@ async def _put_managed_entry(
233250
collection: str,
234251
managed_entry: ManagedEntry,
235252
) -> None:
236-
collection_cache: MemoryCollection = self._cache[collection]
237-
253+
collection_cache = self._get_collection_or_raise(collection)
238254
collection_cache.put(key=key, value=managed_entry)
239255

240256
@override
241257
async def _delete_managed_entry(self, *, key: str, collection: str) -> bool:
242-
collection_cache: MemoryCollection = self._cache[collection]
243-
258+
collection_cache = self._get_collection_or_raise(collection)
244259
return collection_cache.delete(key=key)
245260

246261
@override
247262
async def _get_collection_keys(self, *, collection: str, limit: int | None = None) -> list[str]:
248-
collection_cache: MemoryCollection = self._cache[collection]
249-
263+
collection_cache = self._get_collection_or_raise(collection)
250264
return collection_cache.keys(limit=limit)
251265

252266
@override

key-value/key-value-aio/src/key_value/aio/wrappers/default_value/wrapper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ def __init__(
4040
self._default_value_json = dump_to_json(obj=dict(default_value))
4141
self._default_ttl = None if default_ttl is None else float(default_ttl)
4242

43+
super().__init__()
44+
4345
def _new_default_value(self) -> dict[str, Any]:
4446
return load_from_json(json_str=self._default_value_json)
4547

key-value/key-value-aio/src/key_value/aio/wrappers/encryption/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def _encrypt_value(self, value: dict[str, Any]) -> dict[str, Any]:
6969
json_str: str = json.dumps(value, separators=(",", ":"))
7070

7171
json_bytes: bytes = json_str.encode(encoding="utf-8")
72-
except (json.JSONDecodeError, TypeError) as e:
72+
except TypeError as e:
7373
msg: str = f"Failed to serialize object to JSON: {e}"
7474
raise SerializationError(msg) from e
7575

key-value/key-value-aio/src/key_value/aio/wrappers/limit_size/wrapper.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,5 @@ async def put_many(
101101
filtered_keys.append(k)
102102
filtered_values.append(v)
103103

104-
await self.key_value.put_many(keys=filtered_keys, values=filtered_values, collection=collection, ttl=ttl)
104+
if filtered_keys:
105+
await self.key_value.put_many(keys=filtered_keys, values=filtered_values, collection=collection, ttl=ttl)

key-value/key-value-aio/src/key_value/aio/wrappers/routing/wrapper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ def __init__(
4848
self._routing_function = routing_function
4949
self._default_store = default_store
5050

51+
super().__init__()
52+
5153
def _get_store(self, collection: str | None) -> AsyncKeyValue:
5254
"""Get the appropriate store for the given collection.
5355

key-value/key-value-aio/src/key_value/aio/wrappers/statistics/wrapper.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ def statistics(self) -> KVStoreStatistics:
145145
async def get(self, key: str, *, collection: str | None = None) -> dict[str, Any] | None:
146146
collection = collection or DEFAULT_COLLECTION_NAME
147147

148-
if value := await self.key_value.get(collection=collection, key=key):
148+
value = await self.key_value.get(collection=collection, key=key)
149+
150+
if value is not None:
149151
self.statistics.get_collection(collection=collection).get.increment_hit()
150152
return value
151153

@@ -159,7 +161,7 @@ async def ttl(self, key: str, *, collection: str | None = None) -> tuple[dict[st
159161

160162
value, ttl = await self.key_value.ttl(collection=collection, key=key)
161163

162-
if value:
164+
if value is not None:
163165
self.statistics.get_collection(collection=collection).ttl.increment_hit()
164166
return value, ttl
165167

key-value/key-value-aio/src/key_value/aio/wrappers/ttl_clamp/wrapper.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99

1010

1111
class TTLClampWrapper(BaseWrapper):
12-
"""Wrapper that enforces a maximum TTL for puts into the store."""
12+
"""Wrapper that enforces a maximum TTL for puts into the store.
13+
14+
This wrapper only modifies write operations (put, put_many). All read operations
15+
(get, get_many, ttl, ttl_many, delete, delete_many) pass through unchanged to
16+
the underlying store.
17+
"""
1318

1419
def __init__(
1520
self, key_value: AsyncKeyValue, min_ttl: SupportsFloat, max_ttl: SupportsFloat, missing_ttl: SupportsFloat | None = None

0 commit comments

Comments
 (0)