boto3-assist 0.5.2__tar.gz → 0.6.0__tar.gz

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.
Files changed (116) hide show
  1. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/PKG-INFO +1 -1
  2. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/pyproject.toml +1 -1
  3. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_model_base.py +19 -108
  4. boto3_assist-0.6.0/src/boto3_assist/models/serializable_model.py +9 -0
  5. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/serialization_utility.py +148 -6
  6. boto3_assist-0.6.0/src/boto3_assist/version.py +1 -0
  7. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/models/serializable_model_test.py +14 -0
  8. boto3_assist-0.5.2/src/boto3_assist/models/serializable_model.py +0 -34
  9. boto3_assist-0.5.2/src/boto3_assist/version.py +0 -1
  10. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.env.docker +0 -0
  11. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.env.docker.001 +0 -0
  12. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.env.docker.nosql.workbench +0 -0
  13. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.env.unittest +0 -0
  14. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.gitignore +0 -0
  15. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.vscode/launch.json +0 -0
  16. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.vscode/settings.json +0 -0
  17. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/.vscode/tasks.json +0 -0
  18. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/LICENSE-EXPLAINED.txt +0 -0
  19. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/LICENSE.txt +0 -0
  20. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/README.md +0 -0
  21. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/aws_regions_with_status.csv +0 -0
  22. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/aws_regions_with_status.json +0 -0
  23. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/devops/build.py +0 -0
  24. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/devops/readme.md +0 -0
  25. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/__init__.py +0 -0
  26. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/cloudwatch/log_report.py +0 -0
  27. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/models/order_item_model.py +0 -0
  28. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/models/order_model.py +0 -0
  29. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/models/product_model.py +0 -0
  30. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/models/user_model.py +0 -0
  31. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/models/user_post_model.py +0 -0
  32. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/order_example/main.py +0 -0
  33. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/order_example/products.json +0 -0
  34. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/order_item_service.py +0 -0
  35. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/order_service.py +0 -0
  36. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/product_service.py +0 -0
  37. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/table_service.py +0 -0
  38. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/user_post_service.py +0 -0
  39. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/user_service.py +0 -0
  40. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/user_service_client_example.py +0 -0
  41. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/services/user_service_resource_example.py +0 -0
  42. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/dynamodb/user_post_example/main.py +0 -0
  43. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/examples/ec2/regions_report.py +0 -0
  44. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/module-headers.txt +0 -0
  45. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/mypy.ini +0 -0
  46. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/requirements-dev.txt +0 -0
  47. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/requirements.txt +0 -0
  48. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/run-checks.sh +0 -0
  49. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/__init__.py +0 -0
  50. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/aws_lambda/event_info.py +0 -0
  51. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/boto3session.py +0 -0
  52. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cloudwatch/cloudwatch_connection.py +0 -0
  53. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cloudwatch/cloudwatch_connection_tracker.py +0 -0
  54. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cloudwatch/cloudwatch_log_connection.py +0 -0
  55. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cloudwatch/cloudwatch_logs.py +0 -0
  56. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cloudwatch/cloudwatch_query.py +0 -0
  57. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cognito/cognito_authorizer.py +0 -0
  58. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cognito/cognito_connection.py +0 -0
  59. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cognito/cognito_utility.py +0 -0
  60. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cognito/jwks_cache.py +0 -0
  61. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/cognito/user.py +0 -0
  62. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/connection.py +0 -0
  63. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/connection_tracker.py +0 -0
  64. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb.py +0 -0
  65. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_connection.py +0 -0
  66. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_helpers.py +0 -0
  67. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_importer.py +0 -0
  68. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_index.py +0 -0
  69. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_iservice.py +0 -0
  70. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_key.py +0 -0
  71. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_model_base_interfaces.py +0 -0
  72. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_reindexer.py +0 -0
  73. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.py +0 -0
  74. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.txt +0 -0
  75. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/readme.md +0 -0
  76. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/dynamodb/troubleshooting.md +0 -0
  77. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/ec2/ec2_connection.py +0 -0
  78. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/environment_services/__init__.py +0 -0
  79. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/environment_services/environment_loader.py +0 -0
  80. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/environment_services/environment_variables.py +0 -0
  81. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/errors/custom_exceptions.py +0 -0
  82. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/http_status_codes.py +0 -0
  83. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/s3/s3.py +0 -0
  84. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/s3/s3_connection.py +0 -0
  85. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/datetime_utility.py +0 -0
  86. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/dictionaroy_utility.py +0 -0
  87. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/file_operations.py +0 -0
  88. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/http_utility.py +0 -0
  89. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/logging_utility.py +0 -0
  90. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/numbers_utility.py +0 -0
  91. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/src/boto3_assist/utilities/string_utility.py +0 -0
  92. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/__init__.py +0 -0
  93. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/__top/__init__.py +0 -0
  94. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/__init__.py +0 -0
  95. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/dynamodb_model_base_test.py +0 -0
  96. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/dynamodb_model_projections_test.py +0 -0
  97. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/dynamodb_model_serializtion_test.py +0 -0
  98. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/dynamodb_moto_sorting_test.py +0 -0
  99. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/dynamodb_reindex_test.py +0 -0
  100. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/models/cms/base.py +0 -0
  101. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/models/cms/content_block.py +0 -0
  102. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/models/cms/page.py +0 -0
  103. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/models/cms/template.py +0 -0
  104. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/models/simple_model.py +0 -0
  105. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/models/user_model.py +0 -0
  106. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/dynamodb/models/user_required_fields_model.py +0 -0
  107. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/examples_test/__init__.py +0 -0
  108. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/examples_test/user_service_test.py +0 -0
  109. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/lambda/__init__.py +0 -0
  110. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/lambda/event_info_test.py +0 -0
  111. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/models/__init__.py +0 -0
  112. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/s3/__init__.py +0 -0
  113. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/s3/files/test.txt +0 -0
  114. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/s3/s3_file_upload_test.py +0 -0
  115. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/utilities/__init__.py +0 -0
  116. {boto3_assist-0.5.2 → boto3_assist-0.6.0}/tests/utilities/serialization_utility_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boto3_assist
3
- Version: 0.5.2
3
+ Version: 0.6.0
4
4
  Summary: Additional boto3 wrappers to make your life a little easier
5
5
  Author-email: Eric Wilson <boto3-assist@geekcafe.com>
6
6
  License-File: LICENSE-EXPLAINED.txt
@@ -7,7 +7,7 @@ packages = ["src/boto3_assist"]
7
7
 
8
8
  [project]
9
9
  name = "boto3_assist"
10
- version = "0.5.2"
10
+ version = "0.6.0"
11
11
 
12
12
  authors = [
13
13
  { name="Eric Wilson", email="boto3-assist@geekcafe.com" }
@@ -6,9 +6,10 @@ MIT License. See Project Root for the license information.
6
6
 
7
7
  from __future__ import annotations
8
8
  import datetime as dt
9
- import decimal
10
- import inspect
11
- import uuid
9
+
10
+ # import decimal
11
+ # import inspect
12
+ # import uuid
12
13
  from typing import TypeVar, List, Dict, Any
13
14
  from boto3.dynamodb.types import TypeSerializer
14
15
  from boto3_assist.utilities.serialization_utility import Serialization
@@ -19,6 +20,7 @@ from boto3_assist.dynamodb.dynamodb_index import (
19
20
  )
20
21
  from boto3_assist.dynamodb.dynamodb_reserved_words import DynamoDBReservedWords
21
22
  from boto3_assist.utilities.datetime_utility import DatetimeUtility
23
+ from boto3_assist.models.serializable_model import SerializableModel
22
24
 
23
25
 
24
26
  def exclude_from_serialization(method):
@@ -37,7 +39,7 @@ def exclude_indexes_from_serialization(method):
37
39
  return method
38
40
 
39
41
 
40
- class DynamoDBModelBase:
42
+ class DynamoDBModelBase(SerializableModel):
41
43
  """DyanmoDb Model Base"""
42
44
 
43
45
  T = TypeVar("T", bound="DynamoDBModelBase")
@@ -270,7 +272,9 @@ class DynamoDBSerializer:
270
272
  return mapped
271
273
 
272
274
  @staticmethod
273
- def to_client_dictionary(instance: DynamoDBModelBase, include_indexes: bool = True):
275
+ def to_client_dictionary(
276
+ instance: DynamoDBModelBase, include_indexes: bool = True
277
+ ) -> Dict[str, Any]:
274
278
  """
275
279
  Convert a Python class instance to a dictionary suitable for DynamoDB client.
276
280
 
@@ -281,16 +285,19 @@ class DynamoDBSerializer:
281
285
  - dict: A dictionary representation of the class instance suitable for DynamoDB client.
282
286
  """
283
287
  serializer = TypeSerializer()
284
- return DynamoDBSerializer._serialize(
285
- instance, serializer.serialize, include_indexes=include_indexes
286
- )
288
+ d = Serialization.to_dict(instance, serializer.serialize)
289
+
290
+ if include_indexes:
291
+ d = DynamoDBSerializer._add_indexes(instance=instance, instance_dict=d)
292
+
293
+ return d
287
294
 
288
295
  @staticmethod
289
296
  def to_resource_dictionary(
290
297
  instance: DynamoDBModelBase,
291
298
  include_indexes: bool = True,
292
299
  include_none: bool = False,
293
- ):
300
+ ) -> Dict[str, Any]:
294
301
  """
295
302
  Convert a Python class instance to a dictionary suitable for DynamoDB resource.
296
303
 
@@ -300,112 +307,16 @@ class DynamoDBSerializer:
300
307
  Returns:
301
308
  - dict: A dictionary representation of the class instance suitable for DynamoDB resource.
302
309
  """
303
- return DynamoDBSerializer._serialize(
310
+ d = Serialization.to_dict(
304
311
  instance,
305
312
  lambda x: x,
306
- include_indexes=include_indexes,
307
313
  include_none=include_none,
308
314
  )
309
315
 
310
- @staticmethod
311
- def _serialize(
312
- instance: DynamoDBModelBase,
313
- serialize_fn,
314
- include_indexes: bool = True,
315
- include_none: bool = True,
316
- ):
317
- def is_primitive(value):
318
- """Check if the value is a primitive data type."""
319
- return isinstance(value, (str, int, bool, type(None)))
320
-
321
- def serialize_value(value):
322
- """Serialize the value using the provided function."""
323
-
324
- if isinstance(value, DynamoDBModelBase):
325
- return serialize_fn(
326
- value.to_resource_dictionary(
327
- include_indexes=False, include_none=include_none
328
- )
329
- )
330
- if isinstance(value, dt.datetime):
331
- return serialize_fn(value.isoformat())
332
- elif isinstance(value, float):
333
- v = serialize_fn(decimal.Decimal(str(value)))
334
- return v
335
- elif isinstance(value, decimal.Decimal):
336
- return serialize_fn(value)
337
- elif isinstance(value, uuid.UUID):
338
- return serialize_fn(str(value))
339
- elif isinstance(value, (bytes, bytearray)):
340
- return serialize_fn(value.hex())
341
- elif is_primitive(value):
342
- return serialize_fn(value)
343
- elif isinstance(value, list):
344
- return serialize_fn([serialize_value(v) for v in value])
345
- elif isinstance(value, dict):
346
- return serialize_fn({k: serialize_value(v) for k, v in value.items()})
347
- else:
348
- return serialize_fn(
349
- DynamoDBSerializer._serialize(
350
- value,
351
- serialize_fn,
352
- include_indexes=include_indexes,
353
- include_none=include_none,
354
- )
355
- )
356
-
357
- instance_dict = DynamoDBSerializer._add_properties(
358
- instance, serialize_value, include_none=include_none
359
- )
360
-
361
316
  if include_indexes:
362
- instance_dict = DynamoDBSerializer._add_indexes(instance, instance_dict)
363
- return instance_dict
317
+ d = DynamoDBSerializer._add_indexes(instance=instance, instance_dict=d)
364
318
 
365
- @staticmethod
366
- def _add_properties(
367
- instance: DynamoDBModelBase,
368
- serialize_value,
369
- include_none: bool = True,
370
- ) -> dict:
371
- instance_dict = {}
372
-
373
- # Add instance variables
374
- for attr, value in instance.__dict__.items():
375
- if str(attr) == "T":
376
- continue
377
- # don't get the private properties
378
- if not str(attr).startswith("_"):
379
- if value is not None or include_none:
380
- instance_dict[attr] = serialize_value(value)
381
-
382
- # Add properties
383
- for name, _ in inspect.getmembers(
384
- instance.__class__, predicate=inspect.isdatadescriptor
385
- ):
386
- prop = None
387
- try:
388
- prop = getattr(instance.__class__, name)
389
- except AttributeError:
390
- continue
391
- if isinstance(prop, property):
392
- # Exclude properties marked with the exclude_from_serialization decorator
393
- # Check if the property should be excluded
394
- exclude = getattr(prop.fget, "exclude_from_serialization", False)
395
- if exclude:
396
- continue
397
-
398
- # Skip TypeVar T or instances of DynamoDBModelBase
399
- if str(name) == "T":
400
- continue
401
-
402
- # don't get the private properties
403
- if not str(name).startswith("_"):
404
- value = getattr(instance, name)
405
- if value is not None or include_none:
406
- instance_dict[name] = serialize_value(value)
407
-
408
- return instance_dict
319
+ return d
409
320
 
410
321
  @staticmethod
411
322
  def _add_indexes(instance: DynamoDBModelBase, instance_dict: dict) -> dict:
@@ -0,0 +1,9 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
7
+ from __future__ import annotations
8
+ from typing import TypeVar, Dict, Any
9
+ from boto3_assist.utilities.serialization_utility import SerializableModel
@@ -2,17 +2,58 @@
2
2
 
3
3
  from datetime import datetime
4
4
  from decimal import Decimal
5
- from typing import Dict, List, TypeVar
5
+ from typing import Dict, List, TypeVar, Any
6
6
  import json
7
7
  import jsons
8
+ import datetime as dt
9
+ import decimal
10
+ import inspect
11
+ import uuid
8
12
  from aws_lambda_powertools import Logger
9
13
 
14
+
10
15
  T = TypeVar("T")
11
16
 
12
17
 
13
18
  logger = Logger()
14
19
 
15
20
 
21
+ class SerializableModel:
22
+ """Library to Serialize object to a DynamoDB Format"""
23
+
24
+ T = TypeVar("T", bound="SerializableModel")
25
+
26
+ def __init__(self):
27
+ pass
28
+
29
+ def map(
30
+ self: T,
31
+ source: Dict[str, Any] | "SerializableModel" | None,
32
+ coerce: bool = True,
33
+ ) -> T:
34
+ """
35
+ Map the source dictionary to the target object.
36
+
37
+ Args:
38
+ - source: The dictionary to map from.
39
+ - target: The object to map to.
40
+ """
41
+ mapped = Serialization.map(source=source, target=self, coerce=coerce)
42
+ if mapped is None:
43
+ raise ValueError("Unable to map source to target")
44
+
45
+ return mapped
46
+
47
+ def to_dictionary(self) -> Dict[str, Any]:
48
+ """
49
+ Convert the object to a dictionary.
50
+ """
51
+ # return Serialization.convert_object_to_dict(self)
52
+ return Serialization.to_dict(
53
+ instance=self, serialize_fn=lambda x: x, include_none=True
54
+ )
55
+
56
+
16
57
  class JsonEncoder(json.JSONEncoder):
17
58
  """
18
59
  This class is used to serialize python generics which implement a __json_encode__ method
@@ -52,7 +93,7 @@ class JsonEncoder(json.JSONEncoder):
52
93
 
53
94
  class Serialization:
54
95
  """
55
- Serliaztion Class
96
+ Serialization Class
56
97
  """
57
98
 
58
99
  @staticmethod
@@ -60,11 +101,12 @@ class Serialization:
60
101
  """
61
102
  Dumps an object to dictionary structure
62
103
  """
63
- dump = jsons.dump(model, strip_privates=True)
64
- if isinstance(dump, dict) or isinstance(dump, List):
65
- return dump
66
104
 
67
- raise ValueError("Unable to convert object to dictionary")
105
+ dump = Serialization.to_dict(
106
+ instance=model, serialize_fn=lambda x: x, include_none=True
107
+ )
108
+
109
+ return dump
68
110
 
69
111
  @staticmethod
70
112
  def map(source: object, target: T, coerce: bool = True) -> T | None:
@@ -185,3 +227,103 @@ class Serialization:
185
227
  "This procedure will update the property from False to True while serializing, "
186
228
  "then back to False once serialization is complete. "
187
229
  ) from e
230
+
231
+ @staticmethod
232
+ def to_dict(
233
+ instance: SerializableModel,
234
+ serialize_fn,
235
+ include_none: bool = True,
236
+ ) -> Dict[str, Any]:
237
+ """To Dict / Dictionary"""
238
+
239
+ def is_primitive(value):
240
+ """Check if the value is a primitive data type."""
241
+ return isinstance(value, (str, int, bool, type(None)))
242
+
243
+ def serialize_value(value):
244
+ """Serialize the value using the provided function."""
245
+
246
+ if isinstance(value, SerializableModel):
247
+ return serialize_fn(
248
+ Serialization.to_dict(
249
+ instance=value,
250
+ serialize_fn=lambda x: x,
251
+ include_none=include_none,
252
+ )
253
+ )
254
+ if isinstance(value, dt.datetime):
255
+ return serialize_fn(value.isoformat())
256
+ elif isinstance(value, float):
257
+ v = serialize_fn(decimal.Decimal(str(value)))
258
+ return v
259
+ elif isinstance(value, decimal.Decimal):
260
+ return serialize_fn(value)
261
+ elif isinstance(value, uuid.UUID):
262
+ return serialize_fn(str(value))
263
+ elif isinstance(value, (bytes, bytearray)):
264
+ return serialize_fn(value.hex())
265
+ elif is_primitive(value):
266
+ return serialize_fn(value)
267
+ elif isinstance(value, list):
268
+ return serialize_fn([serialize_value(v) for v in value])
269
+ elif isinstance(value, dict):
270
+ return serialize_fn({k: serialize_value(v) for k, v in value.items()})
271
+ else:
272
+ return serialize_fn(
273
+ Serialization.to_dict(
274
+ value,
275
+ serialize_fn,
276
+ include_none=include_none,
277
+ )
278
+ )
279
+
280
+ instance_dict = Serialization._add_properties(
281
+ instance, serialize_value, include_none=include_none
282
+ )
283
+
284
+ return instance_dict
285
+
286
+ @staticmethod
287
+ def _add_properties(
288
+ instance: SerializableModel,
289
+ serialize_value,
290
+ include_none: bool = True,
291
+ ) -> dict:
292
+ instance_dict = {}
293
+
294
+ # Add instance variables
295
+ for attr, value in instance.__dict__.items():
296
+ if str(attr) == "T":
297
+ continue
298
+ # don't get the private properties
299
+ if not str(attr).startswith("_"):
300
+ if value is not None or include_none:
301
+ instance_dict[attr] = serialize_value(value)
302
+
303
+ # Add properties
304
+ for name, _ in inspect.getmembers(
305
+ instance.__class__, predicate=inspect.isdatadescriptor
306
+ ):
307
+ prop = None
308
+ try:
309
+ prop = getattr(instance.__class__, name)
310
+ except AttributeError:
311
+ continue
312
+ if isinstance(prop, property):
313
+ # Exclude properties marked with the exclude_from_serialization decorator
314
+ # Check if the property should be excluded
315
+ exclude = getattr(prop.fget, "exclude_from_serialization", False)
316
+ if exclude:
317
+ continue
318
+
319
+ # Skip TypeVar T or instances of DynamoDBModelBase
320
+ if str(name) == "T":
321
+ continue
322
+
323
+ # don't get the private properties
324
+ if not str(name).startswith("_"):
325
+ value = getattr(instance, name)
326
+ if value is not None or include_none:
327
+ instance_dict[name] = serialize_value(value)
328
+
329
+ return instance_dict
@@ -0,0 +1 @@
1
+ __version__ = '0.6.0'
@@ -119,6 +119,20 @@ class TestSerializableModel(unittest.TestCase):
119
119
  self.assertEqual(result.age, 25)
120
120
  self.assertEqual(result.active, True)
121
121
 
122
+ def test_to_dictionary(self):
123
+ """
124
+ Test converting an object instance to a dictionary.
125
+ """
126
+ model = ExampleModel(name="Bob", age=35, active=False)
127
+
128
+ result = model.to_dictionary()
129
+
130
+ self.assertIsInstance(result, dict)
131
+ self.assertEqual(len(result), 3)
132
+ self.assertEqual(result.get("name"), "Bob")
133
+ self.assertEqual(result.get("age"), 35)
134
+ self.assertEqual(result.get("active"), False)
135
+
122
136
 
123
137
  if __name__ == "__main__":
124
138
  unittest.main()
@@ -1,34 +0,0 @@
1
- """
2
- Geek Cafe, LLC
3
- Maintainers: Eric Wilson
4
- MIT License. See Project Root for the license information.
5
- """
6
-
7
- from __future__ import annotations
8
- from typing import TypeVar, Dict, Any
9
- from boto3_assist.utilities.serialization_utility import Serialization
10
-
11
-
12
- class SerializableModel:
13
- """Library to Serialize object to a DynamoDB Format"""
14
-
15
- T = TypeVar("T", bound="SerializableModel")
16
-
17
- def __init__(self):
18
- pass
19
-
20
- def map(
21
- self: T, source: Dict[str, Any] | SerializableModel | None, coerce: bool = True
22
- ) -> T:
23
- """
24
- Map the source dictionary to the target object.
25
-
26
- Args:
27
- - source: The dictionary to map from.
28
- - target: The object to map to.
29
- """
30
- mapped = Serialization.map(source=source, target=self, coerce=coerce)
31
- if mapped is None:
32
- raise ValueError("Unable to map source to target")
33
-
34
- return mapped
@@ -1 +0,0 @@
1
- __version__ = '0.5.2'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes