statikk 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
statikk/engine.py CHANGED
@@ -8,6 +8,7 @@ from pydantic.fields import FieldInfo
8
8
  from boto3.dynamodb.conditions import ComparisonCondition, Key
9
9
  from boto3.dynamodb.types import TypeDeserializer, Decimal
10
10
 
11
+ from statikk.typing import T
11
12
  from statikk.conditions import Condition, Equals, BeginsWith
12
13
  from statikk.expressions import UpdateExpressionBuilder
13
14
  from statikk.models import (
@@ -170,10 +171,10 @@ class Table:
170
171
  def get_item(
171
172
  self,
172
173
  id: str,
173
- model_class: Type[DatabaseModel],
174
+ model_class: Type[T],
174
175
  sort_key: Optional[Any] = None,
175
176
  consistent_read: bool = False,
176
- ):
177
+ ) -> T:
177
178
  """
178
179
  Returns an item from the database by id, using the partition key of the table.
179
180
  :param id: The id of the item to retrieve.
@@ -331,11 +332,11 @@ class Table:
331
332
  def query_index(
332
333
  self,
333
334
  hash_key: Union[Condition | str],
334
- model_class: Type[DatabaseModel],
335
+ model_class: Type[T],
335
336
  range_key: Optional[Condition] = None,
336
337
  filter_condition: Optional[ComparisonCondition] = None,
337
338
  index_name: Optional[str] = None,
338
- ):
339
+ ) -> list[T]:
339
340
  """
340
341
  Queries the database using the provided hash key and range key conditions. A filter condition can also be provided
341
342
  using the filter_condition parameter. The method returns a list of items matching the query, deserialized into the
@@ -397,7 +398,7 @@ class Table:
397
398
  self,
398
399
  filter_condition: Optional[ComparisonCondition] = None,
399
400
  consistent_read: bool = False,
400
- ):
401
+ ) -> list[DatabaseModel]:
401
402
  """
402
403
  Scans the database for items matching the provided filter condition. The method returns a list of items matching
403
404
  the query, deserialized into the provided model_class parameter.
@@ -421,9 +422,7 @@ class Table:
421
422
  deserializer = TypeDeserializer()
422
423
  return {k: deserializer.deserialize(v) for k, v in item.items()}
423
424
 
424
- def batch_get_items(
425
- self, ids: List[str], model_class: Type[DatabaseModel], batch_size: int = 100
426
- ) -> List[DatabaseModel]:
425
+ def batch_get_items(self, ids: List[str], model_class: Type[T], batch_size: int = 100) -> list[T]:
427
426
  dynamodb = self._dynamodb_client()
428
427
 
429
428
  id_batches = [ids[i : i + batch_size] for i in range(0, len(ids), batch_size)]
statikk/models.py CHANGED
@@ -4,6 +4,7 @@ import typing
4
4
  import logging
5
5
  from uuid import uuid4
6
6
  from typing import Optional, List, Any, Set, Type
7
+ from statikk.typing import T
7
8
 
8
9
  from boto3.dynamodb.conditions import ComparisonCondition
9
10
  from pydantic import BaseModel, model_serializer, model_validator, Field, Extra
@@ -55,7 +56,13 @@ class IndexFieldConfig(BaseModel):
55
56
  class TrackingMixin:
56
57
  _original_hash: int = Field(exclude=True)
57
58
 
58
- def __init__(self):
59
+ @property
60
+ def should_track(self) -> bool:
61
+ if self._parent is not None:
62
+ return self._parent.should_track
63
+ return False
64
+
65
+ def init_tracking(self):
59
66
  self._original_hash = self._recursive_hash()
60
67
 
61
68
  def _recursive_hash(self) -> int:
@@ -67,6 +74,9 @@ class TrackingMixin:
67
74
  Returns:
68
75
  A hash value representing the model's non-model fields.
69
76
  """
77
+ if not self.should_track:
78
+ return 0
79
+
70
80
  values = []
71
81
  for field_name in self.model_fields:
72
82
  if not hasattr(self, field_name):
@@ -126,7 +136,10 @@ class TrackingMixin:
126
136
 
127
137
  @property
128
138
  def was_modified(self) -> bool:
129
- return self._recursive_hash() != self._original_hash
139
+ if self.should_track:
140
+ return self._recursive_hash() != self._original_hash
141
+
142
+ return True
130
143
 
131
144
 
132
145
  class DatabaseModel(BaseModel, TrackingMixin, extra=Extra.allow):
@@ -160,12 +173,12 @@ class DatabaseModel(BaseModel, TrackingMixin, extra=Extra.allow):
160
173
 
161
174
  @classmethod
162
175
  def query(
163
- cls,
176
+ cls: Type[T],
164
177
  hash_key: Condition,
165
178
  range_key: Optional[Condition] = None,
166
179
  filter_condition: Optional[ComparisonCondition] = None,
167
180
  index_name: Optional[str] = None,
168
- ):
181
+ ) -> T:
169
182
  return cls._table.query_index(
170
183
  hash_key=hash_key,
171
184
  model_class=cls,
@@ -176,12 +189,12 @@ class DatabaseModel(BaseModel, TrackingMixin, extra=Extra.allow):
176
189
 
177
190
  @classmethod
178
191
  def query_hierarchy(
179
- cls,
192
+ cls: Type[T],
180
193
  hash_key: Union[Condition | str],
181
194
  range_key: Optional[Condition] = None,
182
195
  filter_condition: Optional[ComparisonCondition] = None,
183
196
  index_name: Optional[str] = None,
184
- ) -> DatabaseModel:
197
+ ) -> T:
185
198
  return cls._table.query_hierarchy(
186
199
  hash_key=hash_key,
187
200
  model_class=cls,
@@ -215,11 +228,11 @@ class DatabaseModel(BaseModel, TrackingMixin, extra=Extra.allow):
215
228
  )
216
229
 
217
230
  @classmethod
218
- def get(cls, id: str, sort_key: Optional[str] = None, consistent_read: bool = False):
231
+ def get(cls: Type[T], id: str, sort_key: Optional[str] = None, consistent_read: bool = False) -> T:
219
232
  return cls._table.get_item(id=id, model_class=cls, sort_key=sort_key, consistent_read=consistent_read)
220
233
 
221
234
  @classmethod
222
- def batch_get(cls, ids: List[str], batch_size: int = 100):
235
+ def batch_get(cls: Type[T], ids: List[str], batch_size: int = 100) -> list[T]:
223
236
  return cls._table.batch_get_items(ids=ids, model_class=cls, batch_size=batch_size)
224
237
 
225
238
  def should_write_to_database(self) -> bool:
@@ -232,7 +245,7 @@ class DatabaseModel(BaseModel, TrackingMixin, extra=Extra.allow):
232
245
  cls,
233
246
  filter_condition: Optional[ComparisonCondition] = None,
234
247
  consistent_read: bool = False,
235
- ):
248
+ ) -> list[DatabaseModel]:
236
249
  return cls._table.scan(filter_condition=filter_condition)
237
250
 
238
251
  @model_serializer(mode="wrap")
@@ -245,10 +258,10 @@ class DatabaseModel(BaseModel, TrackingMixin, extra=Extra.allow):
245
258
 
246
259
  @model_validator(mode="after")
247
260
  def initialize_tracking(self):
248
- self._original_hash = self._recursive_hash()
249
261
  self._model_types_in_hierarchy[self.type()] = type(self)
250
262
  if not self.is_nested():
251
263
  self._set_parent_references(self)
264
+ self.init_tracking()
252
265
 
253
266
  return self
254
267
 
@@ -343,6 +356,7 @@ class DatabaseModel(BaseModel, TrackingMixin, extra=Extra.allow):
343
356
  field._parent = parent
344
357
  root._model_types_in_hierarchy[field.type()] = type(field)
345
358
  field._set_parent_references(root)
359
+ field.init_tracking()
346
360
 
347
361
  def _set_parent_references(self, root: DatabaseModel):
348
362
  for field_name, field_value in self:
statikk/typing.py ADDED
@@ -0,0 +1,3 @@
1
+ from typing import TypeVar
2
+
3
+ T = TypeVar("T", bound="DatabaseModel")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: statikk
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: statikk is a single table application (STA) library for DynamoDb.
5
5
  Home-page: https://github.com/terinia/statikk
6
6
  Author: Balint Biro
@@ -0,0 +1,12 @@
1
+ statikk/__init__.py,sha256=pH5i4Fj1tbXLqLtTVIdoojiplZssQn0nnud8-HXodRE,577
2
+ statikk/conditions.py,sha256=63FYMR-UUaE-ZJEb_8CU721CQTwhajq39-BbokmKeMA,2166
3
+ statikk/engine.py,sha256=hMA6V_aneWpJlCa4mogu6rE3-T7qwFuRGAkK-0nREj8,30884
4
+ statikk/expressions.py,sha256=mF6Hmj3Kmj6KKXTymeTHSepVA7rhiSINpFgSAPeBTRY,12210
5
+ statikk/fields.py,sha256=LkMP5NnX7WS0HSLxI3Q-dMOrfaJ0SD7SayZxJU5Acgg,86
6
+ statikk/models.py,sha256=GgEhoHhStykOtfPEgO5GdGITVEX0Kj26UnpVN8fDp3o,13301
7
+ statikk/typing.py,sha256=qfpegORcdODuILK3gvuD4SdcZA1a7Myn0yvscOLPHOM,68
8
+ statikk-0.1.3.dist-info/LICENSE.txt,sha256=uSH_2Hpb2Bigy5_HhBliN2fZbBU64G3ERM5zzhKPUEE,1078
9
+ statikk-0.1.3.dist-info/METADATA,sha256=5X1jmvD-a2OXeQwQeZo6AFUeqiAxDrNo1zBKL9Zs-KA,3160
10
+ statikk-0.1.3.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
11
+ statikk-0.1.3.dist-info/top_level.txt,sha256=etKmBbjzIlLpSefXoiOfhWGEgvqUEALaFwCjFDBD9YI,8
12
+ statikk-0.1.3.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- statikk/__init__.py,sha256=pH5i4Fj1tbXLqLtTVIdoojiplZssQn0nnud8-HXodRE,577
2
- statikk/conditions.py,sha256=63FYMR-UUaE-ZJEb_8CU721CQTwhajq39-BbokmKeMA,2166
3
- statikk/engine.py,sha256=ny15q1yLEJYTszxCaHxqdm7GRC3xsCZBtjPfNGHn0Dk,30878
4
- statikk/expressions.py,sha256=mF6Hmj3Kmj6KKXTymeTHSepVA7rhiSINpFgSAPeBTRY,12210
5
- statikk/fields.py,sha256=LkMP5NnX7WS0HSLxI3Q-dMOrfaJ0SD7SayZxJU5Acgg,86
6
- statikk/models.py,sha256=6ssCECKFCHZwN_-LA-epHhqtVNJK0pt6PlIVj9UxKUI,12928
7
- statikk-0.1.1.dist-info/LICENSE.txt,sha256=uSH_2Hpb2Bigy5_HhBliN2fZbBU64G3ERM5zzhKPUEE,1078
8
- statikk-0.1.1.dist-info/METADATA,sha256=bfSuQ9QD8mDp_9CdmlgApWp0h-rlAhCsgO-ChPETOkQ,3160
9
- statikk-0.1.1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
10
- statikk-0.1.1.dist-info/top_level.txt,sha256=etKmBbjzIlLpSefXoiOfhWGEgvqUEALaFwCjFDBD9YI,8
11
- statikk-0.1.1.dist-info/RECORD,,