boto3-assist 0.5.0__py3-none-any.whl → 0.5.1__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.
@@ -1,7 +1,14 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
1
7
  from typing import Optional
8
+ from boto3_assist.models.serializable_model import SerializableModel
2
9
 
3
10
 
4
- class CognitoUser:
11
+ class CognitoUser(SerializableModel):
5
12
  """A generic way to represent a cognito user"""
6
13
 
7
14
  def __init__(
@@ -0,0 +1,30 @@
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
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
+ @staticmethod
18
+ def map(source: dict | object, target: T, coerce: bool = True) -> T:
19
+ """
20
+ Map the source dictionary to the target object.
21
+
22
+ Args:
23
+ - source: The dictionary to map from.
24
+ - target: The object to map to.
25
+ """
26
+ mapped = Serialization.map(source, target, coerce=coerce)
27
+ if mapped is None:
28
+ raise ValueError("Unable to map source to target")
29
+
30
+ return mapped
@@ -5,11 +5,11 @@ from decimal import Decimal
5
5
  from typing import Dict, List, TypeVar
6
6
  import json
7
7
  import jsons
8
- from aws_lambda_powertools import Logger, Tracer
8
+ from aws_lambda_powertools import Logger
9
9
 
10
10
  T = TypeVar("T")
11
11
 
12
- tracer = Tracer()
12
+
13
13
  logger = Logger()
14
14
 
15
15
 
@@ -67,7 +67,7 @@ class Serialization:
67
67
  raise ValueError("Unable to convert object to dictionary")
68
68
 
69
69
  @staticmethod
70
- def map(source: object, target: T) -> T | None:
70
+ def map(source: object, target: T, coerce: bool = True) -> T | None:
71
71
  """Map an object from one object to another"""
72
72
  source_dict: dict | object
73
73
  if isinstance(source, dict):
@@ -76,12 +76,26 @@ class Serialization:
76
76
  source_dict = Serialization.convert_object_to_dict(source)
77
77
  if not isinstance(source_dict, dict):
78
78
  return None
79
- return Serialization.load_properties(source_dict, target=target)
79
+ return Serialization.load_properties(
80
+ source=source_dict, target=target, coerce=coerce
81
+ )
80
82
 
81
83
  @staticmethod
82
- def load_properties(source: dict, target: T) -> T | None:
84
+ def load_properties(
85
+ source: dict,
86
+ target: T,
87
+ coerce: bool = True,
88
+ ) -> T | None:
83
89
  """
84
- Converts a source to an object
90
+ Converts a source dictionary to a target object.
91
+
92
+ Args:
93
+ source (dict): The source dictionary containing properties.
94
+ target (T): The target object to populate.
95
+ coerce (bool): If True, attempts to convert values to the target attribute types. If False, raises an error for type mismatches.
96
+
97
+ Returns:
98
+ T | None: The populated target object, or None if an error occurred.
85
99
  """
86
100
  # Ensure target is an instance of the class
87
101
  if isinstance(target, type):
@@ -95,28 +109,56 @@ class Serialization:
95
109
  setattr(target, "__actively_serializing_data__", True)
96
110
 
97
111
  for key, value in source.items():
98
- if Serialization.has_attribute(target, key): # hasattr(target, key):
112
+ if Serialization.has_attribute(target, key):
99
113
  attr = getattr(target, key)
100
- if isinstance(attr, (int, float, str, bool, type(None))):
101
- try:
114
+ expected_type = type(attr)
115
+
116
+ try:
117
+ if isinstance(attr, (int, float, str, bool)):
118
+ if not isinstance(value, expected_type):
119
+ if coerce:
120
+ # Attempt to coerce the value to the expected type
121
+ try:
122
+ value = expected_type(value)
123
+ except ValueError as e:
124
+ logger.warning(
125
+ f"Warning coercing attribute {key} with value {value}: {e}"
126
+ )
127
+ # TODO: should we set numbers to 0 or a NaN or raise an error
128
+
129
+ setattr(target, key, value)
130
+ # raise ValueError( # pylint: disable=w0707
131
+ # f"Type mismatch for attribute {key}. Expected {expected_type}, got {type(value)}."
132
+ # )
133
+ else:
134
+ raise ValueError(
135
+ f"Type mismatch for attribute {key}. Expected {expected_type}, got {type(value)}."
136
+ )
137
+ setattr(target, key, value)
138
+ elif isinstance(attr, type(None)):
139
+ setattr(target, key, value)
140
+ elif isinstance(attr, list) and isinstance(value, list):
141
+ attr.clear()
142
+ attr.extend(value)
143
+ elif isinstance(attr, dict) and isinstance(value, dict):
144
+ Serialization.load_properties(value, attr, coerce=coerce)
145
+ elif hasattr(attr, "__dict__") and isinstance(value, dict):
146
+ Serialization.load_properties(value, attr, coerce=coerce)
147
+ else:
102
148
  setattr(target, key, value)
103
- except Exception as e: # pylint: disable=w0718
104
- logger.error(
105
- f"Error setting attribute {key} with value {value}: {e}. "
106
- "This usually occurs on properties that don't have setters. "
107
- "You can add a setter (even with a pass action) for this property, "
108
- "decorate it with the @exclude_from_serialization "
109
- "or ignore this error. "
110
- )
111
- elif isinstance(attr, list) and isinstance(value, list):
112
- attr.clear()
113
- attr.extend(value)
114
- elif isinstance(attr, dict) and isinstance(value, dict):
115
- Serialization.load_properties(value, attr)
116
- elif hasattr(attr, "__dict__") and isinstance(value, dict):
117
- Serialization.load_properties(value, attr)
118
- else:
119
- setattr(target, key, value)
149
+ except ValueError as e:
150
+ logger.error(
151
+ f"Error setting attribute {key} with value {value}: {e}"
152
+ )
153
+ raise
154
+ except Exception as e: # pylint: disable=w0718
155
+ logger.error(
156
+ f"Error setting attribute {key} with value {value}: {e}. "
157
+ "This usually occurs on properties that don't have setters. "
158
+ "You can add a setter (even with a pass action) for this property, "
159
+ "decorate it with the @exclude_from_serialization "
160
+ "or ignore this error. "
161
+ )
120
162
 
121
163
  if hasattr(target, "__actively_serializing_data__"):
122
164
  setattr(target, "__actively_serializing_data__", False)
boto3_assist/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.5.0'
1
+ __version__ = '0.5.1'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boto3_assist
3
- Version: 0.5.0
3
+ Version: 0.5.1
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
@@ -3,7 +3,7 @@ boto3_assist/boto3session.py,sha256=Q9sByNC0r_aMQfHnIEnxtTaiCMUqikm8UeSTxV7-Np0,
3
3
  boto3_assist/connection.py,sha256=CNGkAIRyfrELoWrV0ziQBA3oHacNFuLL3i8faUPRiO0,3486
4
4
  boto3_assist/connection_tracker.py,sha256=bfImvNVX-0Lhb-ombOurWUpNLdI0qVDil-kokBdIFkY,4345
5
5
  boto3_assist/http_status_codes.py,sha256=G0zRSWenwavYKETvDF9tNVUXQz3Ae2gXdBETYbjvJe8,3284
6
- boto3_assist/version.py,sha256=0PaI2eSOCp5kkNcpKpUSbLHf66rL9xQzFpYyLGpEtyM,22
6
+ boto3_assist/version.py,sha256=s8Yq9Om1yBxrMA7xYQ5Y13Paeuxnq99NxhyjuPlnH6A,22
7
7
  boto3_assist/aws_lambda/event_info.py,sha256=OkZ4WzuGaHEu_T8sB188KBgShAJhZpWASALKRGBOhMg,14648
8
8
  boto3_assist/cloudwatch/cloudwatch_connection.py,sha256=mnGWaLSQpHh5EeY7Ek_2o9JKHJxOELIYtQVMX1IaHn4,2480
9
9
  boto3_assist/cloudwatch/cloudwatch_connection_tracker.py,sha256=mzRtO1uHrcfJNh1XrGEiXdTqxwEP8d1RqJkraMNkgK0,410
@@ -14,7 +14,7 @@ boto3_assist/cognito/cognito_authorizer.py,sha256=ONcxzjTACgVYl6qI9kJAQ5SoRMtVHY
14
14
  boto3_assist/cognito/cognito_connection.py,sha256=deuXR3cNHz0mCYff2k0LfAvK--9OkqehWp0Bl--lDuw,1607
15
15
  boto3_assist/cognito/cognito_utility.py,sha256=kjzd2PcCCP9GbxlMlgYEIQE1FSyPPjsRPjr6-kN08Jc,18238
16
16
  boto3_assist/cognito/jwks_cache.py,sha256=1Y9r-YfQ8qrgZN5xYPvjUEEV0vthbdcPdAIaPbZP7kU,373
17
- boto3_assist/cognito/user.py,sha256=H8Sgu1tSkd22flwGkAa_9Im2jYw5ra7YhVJdtcoFMOs,623
17
+ boto3_assist/cognito/user.py,sha256=qc44qLx3gwq6q2zMxcPQze1EjeZwy5Kuav93vbe-4WU,820
18
18
  boto3_assist/dynamodb/dynamodb.py,sha256=q3U4uYqnKX1_u5TXv8Iq94JrBad16q0rL_vKxQyR_3k,15772
19
19
  boto3_assist/dynamodb/dynamodb_connection.py,sha256=x6Ylb_uVAY5TS0AIBUNOSyywKIqros3xX8diLTjZUsc,3275
20
20
  boto3_assist/dynamodb/dynamodb_helpers.py,sha256=ajpTJ5bJOm9PDgE2Zx9p2zkTRFV4xswqJRS81SOTn1s,12198
@@ -34,6 +34,7 @@ boto3_assist/environment_services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
34
34
  boto3_assist/environment_services/environment_loader.py,sha256=zCA4mRdVWMLKzjDRvrJbhQfRVP4HAMGpuQFi07zzULk,3396
35
35
  boto3_assist/environment_services/environment_variables.py,sha256=4ccBKdPt6O7hcRT3zBHd8vqu8yQU8udmoD5RLAT3iMs,6801
36
36
  boto3_assist/errors/custom_exceptions.py,sha256=zC2V2Y4PUtKj3uLPn8mB-JessksKWJWvKM9kp1dmvt8,760
37
+ boto3_assist/models/serializable_model.py,sha256=8CunaU2YDWs9vK2BShShnyAdktmeZ3R_o7p8Yt70nYQ,829
37
38
  boto3_assist/s3/s3.py,sha256=DFCJs5z1mMIT8nZfnqPyr_cvhi9-FePuYH--tzD7b5E,17104
38
39
  boto3_assist/s3/s3_connection.py,sha256=FI1AhZV4UbTXQRTb4TqL9mv88Gt018rPZVFBvLetVAw,2163
39
40
  boto3_assist/utilities/datetime_utility.py,sha256=dgAMB9VqakrYIPXlSoVQiLSsc_yhrJK4gMfJO9mX90w,11112
@@ -42,10 +43,10 @@ boto3_assist/utilities/file_operations.py,sha256=Zy8fu8fpuVNf7U9NimrLdy5FRF71XSI
42
43
  boto3_assist/utilities/http_utility.py,sha256=koFv7Va-8ng-47Nt1K2Sh7Ti95e62IYs9VMLlGh9Kt4,1173
43
44
  boto3_assist/utilities/logging_utility.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
45
  boto3_assist/utilities/numbers_utility.py,sha256=KIiNkBSRbfNWvtXG5SdHp625LTiW12VtADUa4ZlWMFo,8709
45
- boto3_assist/utilities/serialization_utility.py,sha256=vsipCQZu91hApkJ8tKRTxBa8kNRvn06ED-isquqAVQQ,5744
46
+ boto3_assist/utilities/serialization_utility.py,sha256=p9QQfc6EDOtD-mB6Ujhv-BRpDn3DCCG2z5VmXG1kmb0,7768
46
47
  boto3_assist/utilities/string_utility.py,sha256=sBY80aQO-fTRanlHryZFMQBxdo6OvLRvnZjZrQepHlI,9283
47
- boto3_assist-0.5.0.dist-info/METADATA,sha256=PnVWeXj0gPTylAWn97RKzRoTN1bS6YSZdk4yRETGJaY,1728
48
- boto3_assist-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
- boto3_assist-0.5.0.dist-info/licenses/LICENSE-EXPLAINED.txt,sha256=WFREvTpfTjPjDHpOLADxJpCKpIla3Ht87RUUGii4ODU,606
50
- boto3_assist-0.5.0.dist-info/licenses/LICENSE.txt,sha256=PXDhFWS5L5aOTkVhNvoitHKbAkgxqMI2uUPQyrnXGiI,1105
51
- boto3_assist-0.5.0.dist-info/RECORD,,
48
+ boto3_assist-0.5.1.dist-info/METADATA,sha256=r5iNwKDiUS06CIskAGuHnpvW3wXfD97QznVQhe07jWQ,1728
49
+ boto3_assist-0.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
50
+ boto3_assist-0.5.1.dist-info/licenses/LICENSE-EXPLAINED.txt,sha256=WFREvTpfTjPjDHpOLADxJpCKpIla3Ht87RUUGii4ODU,606
51
+ boto3_assist-0.5.1.dist-info/licenses/LICENSE.txt,sha256=PXDhFWS5L5aOTkVhNvoitHKbAkgxqMI2uUPQyrnXGiI,1105
52
+ boto3_assist-0.5.1.dist-info/RECORD,,