1919_INVALID_DATABASE_ROWS = "Expected a list of database rows with string keys"
2020
2121
22+ def _is_object_mapping (value : object ) -> TypeGuard [Mapping [object , object ]]:
23+ return isinstance (value , Mapping )
24+
25+
26+ def _is_object_sequence (
27+ value : object ,
28+ ) -> TypeGuard [list [object ] | tuple [object , ...]]:
29+ return isinstance (value , (list , tuple ))
30+
31+
2232def _is_database_row (value : object ) -> TypeGuard [dict [str , object ]]:
2333 if not isinstance (value , dict ):
2434 return False
@@ -54,12 +64,10 @@ def _snapshot_row(values: Mapping[str, JSONValue]) -> dict[str, JSONValue]:
5464
5565
5666def _snapshot_filter_value (value : object ) -> object :
57- if isinstance (value , Mapping ):
58- mapping = cast ("Mapping[object, object]" , value )
59- return {key : _snapshot_filter_value (item ) for key , item in mapping .items ()}
60- if isinstance (value , (list , tuple )):
61- sequence = cast ("list[object] | tuple[object, ...]" , value )
62- return [_snapshot_filter_value (item ) for item in sequence ]
67+ if _is_object_mapping (value ):
68+ return {key : _snapshot_filter_value (item ) for key , item in value .items ()}
69+ if _is_object_sequence (value ):
70+ return [_snapshot_filter_value (item ) for item in value ]
6371 return value
6472
6573
@@ -86,10 +94,8 @@ class _OrderClause(TypedDict):
8694class FilterBuilder :
8795 """Shared immutable filters for database operations."""
8896
89- _filters : tuple [_FilterCondition , ...] = ()
90-
91- def _with_filters (self , filters : tuple [_FilterCondition , ...]) -> Self :
92- del filters
97+ def _append_filter (self , condition : _FilterCondition ) -> Self :
98+ del condition
9399 raise NotImplementedError
94100
95101 def eq (self , column : str , value : object ) -> Self :
@@ -208,7 +214,7 @@ def _filter(self, column: str, operator: str, value: object) -> Self:
208214 "operator" : operator ,
209215 "value" : _snapshot_filter_value (value ),
210216 }
211- return self ._with_filters (( * self . _filters , condition ) )
217+ return self ._append_filter ( condition )
212218
213219
214220@dataclass (frozen = True , slots = True )
@@ -319,8 +325,8 @@ def offset(self, count: int) -> QueryBuilder:
319325 return replace (self , _offset = count )
320326
321327 @override
322- def _with_filters (self , filters : tuple [ _FilterCondition , ...] ) -> QueryBuilder :
323- return replace (self , _filters = filters )
328+ def _append_filter (self , condition : _FilterCondition ) -> QueryBuilder :
329+ return replace (self , _filters = ( * self . _filters , condition ) )
324330
325331 def _request_body (self ) -> dict [str , object ]:
326332 body : dict [str , object ] = {"table" : self ._table }
@@ -402,8 +408,8 @@ class UpdateBuilder(FilterBuilder):
402408 _filters : tuple [_FilterCondition , ...] = ()
403409
404410 @override
405- def _with_filters (self , filters : tuple [ _FilterCondition , ...] ) -> UpdateBuilder :
406- return replace (self , _filters = filters )
411+ def _append_filter (self , condition : _FilterCondition ) -> UpdateBuilder :
412+ return replace (self , _filters = ( * self . _filters , condition ) )
407413
408414 def execute (self ) -> list [dict [str , object ]]:
409415 """Update matching rows and return them.
@@ -440,8 +446,8 @@ class DeleteBuilder(FilterBuilder):
440446 _filters : tuple [_FilterCondition , ...] = ()
441447
442448 @override
443- def _with_filters (self , filters : tuple [ _FilterCondition , ...] ) -> DeleteBuilder :
444- return replace (self , _filters = filters )
449+ def _append_filter (self , condition : _FilterCondition ) -> DeleteBuilder :
450+ return replace (self , _filters = ( * self . _filters , condition ) )
445451
446452 def execute (self ) -> list [dict [str , object ]]:
447453 """Delete matching rows and return them.
0 commit comments