statikk 0.1.20__py3-none-any.whl → 0.1.22__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
@@ -24,6 +24,14 @@ from aws_xray_sdk.core import patch_all
24
24
  patch_all()
25
25
 
26
26
 
27
+ DYNAMODB_CONTEXT = decimal.Context(
28
+ prec=38, # precision
29
+ rounding=decimal.ROUND_HALF_EVEN,
30
+ traps=[decimal.Overflow, decimal.Underflow, decimal.InvalidOperation],
31
+ )
32
+ decimal.setcontext(DYNAMODB_CONTEXT)
33
+
34
+
27
35
  class InvalidIndexNameError(Exception):
28
36
  pass
29
37
 
@@ -253,10 +261,7 @@ class Table:
253
261
  batch.delete_by_key(delete_params)
254
262
 
255
263
  for item in items:
256
- if item.should_delete:
257
- batch.delete(item)
258
- else:
259
- batch.put(item)
264
+ batch.put(item)
260
265
 
261
266
  model._db_snapshot_keys = new_keys
262
267
 
@@ -536,6 +541,8 @@ class Table:
536
541
 
537
542
  if actual_annotation is datetime or "datetime" in str(annotation) and value is not None:
538
543
  return datetime.fromtimestamp(int(value))
544
+ if isinstance(value, decimal.Decimal):
545
+ return float(value)
539
546
  if actual_annotation is float:
540
547
  return float(value)
541
548
  if actual_annotation is list:
@@ -550,15 +557,13 @@ class Table:
550
557
  return {self._deserialize_value(item, item_annotation) for item in value}
551
558
  if isinstance(value, dict):
552
559
  return {key: self._deserialize_value(item, annotation) for key, item in value.items() if item is not None}
553
- if isinstance(value, decimal.Decimal):
554
- return float(value)
555
560
  return value
556
561
 
557
562
  def _serialize_value(self, value: Any):
558
563
  if isinstance(value, datetime):
559
564
  return int(value.timestamp())
560
565
  if isinstance(value, float):
561
- return Decimal(value)
566
+ return DYNAMODB_CONTEXT.create_decimal_from_float(value)
562
567
  if isinstance(value, list):
563
568
  return [self._serialize_value(item) for item in value]
564
569
  if isinstance(value, set):
statikk/models.py CHANGED
@@ -171,7 +171,6 @@ class DatabaseModel(BaseModel, TrackingMixin):
171
171
  _parent: Optional[DatabaseModel] = None
172
172
  _parent_field_name: Optional[str] = None
173
173
  _model_types_in_hierarchy: dict[str, Type[DatabaseModel]] = {}
174
- _should_delete: bool = False
175
174
  _db_snapshot_keys = set()
176
175
 
177
176
  class Config:
@@ -207,20 +206,6 @@ class DatabaseModel(BaseModel, TrackingMixin):
207
206
  def is_simple_object(self) -> bool:
208
207
  return len(self._model_types_in_hierarchy) == 1
209
208
 
210
- @property
211
- def should_delete(self) -> bool:
212
- if self._is_any_parent_marked_for_deletion():
213
- return True
214
- return self._should_delete
215
-
216
- def _is_any_parent_marked_for_deletion(self) -> bool:
217
- current = self._parent
218
- while current is not None:
219
- if current._should_delete:
220
- return True
221
- current = current._parent
222
- return False
223
-
224
209
  def build_model_indexes(self) -> T:
225
210
  for node in self.dfs_traverse_hierarchy():
226
211
  self._table.build_model_indexes(node)
@@ -294,12 +279,30 @@ class DatabaseModel(BaseModel, TrackingMixin):
294
279
  return self._parent.should_write_to_database()
295
280
  return True
296
281
 
297
- def mark_for_delete(self):
298
- self._should_delete = True
299
-
300
282
  def _change_parent_to(self, new_parent: DatabaseModel, field_name: str) -> T:
301
283
  return self._table.reparent_subtree(self, new_parent, field_name)
302
284
 
285
+ def remove_child_node(self, child_node: DatabaseModel):
286
+ """
287
+ Remove a child node from this model, optionally specifying which field to search.
288
+
289
+ Args:
290
+ child_node: The database model instance to remove
291
+ field_name: Optional field name to limit the search scope
292
+ """
293
+ field_name = child_node._parent_field_name
294
+ field_info = self.model_fields[field_name]
295
+ field_value = getattr(self, field_name)
296
+ is_optional, inner_type = inspect_optional_field(self.__class__, field_name)
297
+ field_type = inner_type if is_optional else field_info.annotation
298
+
299
+ if hasattr(field_type, "__origin__") and field_type.__origin__ == list:
300
+ if isinstance(field_value, list):
301
+ field_value.remove(next(filter(lambda item: item.id == child_node.id, field_value), None))
302
+
303
+ elif isinstance(field_value, DatabaseModel) and field_value.id == child_node.id:
304
+ setattr(self, field_name, None)
305
+
303
306
  def _remove_from_parent(self, parent: DatabaseModel, field_name: str):
304
307
  is_optional, inner_type = inspect_optional_field(parent.__class__, field_name)
305
308
  field_type = inner_type if is_optional else parent.model_fields[field_name].annotation
@@ -307,12 +310,7 @@ class DatabaseModel(BaseModel, TrackingMixin):
307
310
  if hasattr(field_type, "__origin__") and field_type.__origin__ == list:
308
311
  if not isinstance(field, list):
309
312
  setattr(parent, field_name, [])
310
- field.remove(next(filter(lambda item: item.id == self.id, getattr(parent, field_name)), None))
311
-
312
- elif hasattr(field_type, "__origin__") and field_type.__origin__ == set:
313
- if not isinstance(field, set):
314
- setattr(parent, field_name, set())
315
- field.remove(next(filter(lambda item: item.id == self.id, getattr(parent, field_name)), None))
313
+ field.remove(next(filter(lambda item: item.id == self.id, field), None))
316
314
 
317
315
  elif issubclass(field_type, DatabaseModel):
318
316
  current_value = getattr(parent, field_name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: statikk
3
- Version: 0.1.20
3
+ Version: 0.1.22
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
@@ -1,12 +1,12 @@
1
1
  statikk/__init__.py,sha256=pH5i4Fj1tbXLqLtTVIdoojiplZssQn0nnud8-HXodRE,577
2
2
  statikk/conditions.py,sha256=63FYMR-UUaE-ZJEb_8CU721CQTwhajq39-BbokmKeMA,2166
3
- statikk/engine.py,sha256=bcUJfI9G1Nwe86NIrCwkB_Ni_fxdc_KBqa1ny2wJBzE,31998
3
+ statikk/engine.py,sha256=oYSxiD6lw0aoK6StoqJvdb6lWwTJEra4H3UfnnE7yK8,32145
4
4
  statikk/expressions.py,sha256=boAeGxZj2cDsXxoiX3IIEzfX9voSMQngi4-rE_jYeuE,12233
5
5
  statikk/fields.py,sha256=uLGD3xEnz2nqQY6EwG8Dd7pnRMMVP4PU2Z2I-uGNaTA,150
6
- statikk/models.py,sha256=1qnj2VmJivo4vJtI2UnlK85d9imuh_IiIp3UC1K7Y3I,17207
6
+ statikk/models.py,sha256=IaB6USTvrzEQa3LewgFQ4772eaWkWFF_fyzIVQLzp8U,17385
7
7
  statikk/typing.py,sha256=laOlOpWOm9_sOj4hhdZnGTUZRiq8760_B9I9B3wBhz8,750
8
- statikk-0.1.20.dist-info/licenses/LICENSE.txt,sha256=uSH_2Hpb2Bigy5_HhBliN2fZbBU64G3ERM5zzhKPUEE,1078
9
- statikk-0.1.20.dist-info/METADATA,sha256=GOv6D1HUYYGNbs-5UgWLS7C1wahrMZ7L39r4Gzni9T4,3183
10
- statikk-0.1.20.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
11
- statikk-0.1.20.dist-info/top_level.txt,sha256=etKmBbjzIlLpSefXoiOfhWGEgvqUEALaFwCjFDBD9YI,8
12
- statikk-0.1.20.dist-info/RECORD,,
8
+ statikk-0.1.22.dist-info/licenses/LICENSE.txt,sha256=uSH_2Hpb2Bigy5_HhBliN2fZbBU64G3ERM5zzhKPUEE,1078
9
+ statikk-0.1.22.dist-info/METADATA,sha256=3jIg6WKVrVjPnNx6Vb6tpU03EMavyeYrGHxuzp8MlnM,3183
10
+ statikk-0.1.22.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
11
+ statikk-0.1.22.dist-info/top_level.txt,sha256=etKmBbjzIlLpSefXoiOfhWGEgvqUEALaFwCjFDBD9YI,8
12
+ statikk-0.1.22.dist-info/RECORD,,