boto3-assist 0.27.0__py3-none-any.whl → 0.28.0__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.
@@ -8,6 +8,7 @@ import datetime as dt
8
8
  import decimal
9
9
  import inspect
10
10
  import json
11
+ import typing
11
12
  import uuid
12
13
  from datetime import datetime
13
14
  from decimal import Decimal
@@ -116,6 +117,86 @@ class JsonConversions:
116
117
  Used for snake_case to camelCase and vice versa
117
118
  """
118
119
 
120
+ @staticmethod
121
+ def string_to_json_obj(
122
+ value: str | list | dict, raise_on_error: bool = True, retry: int = 0
123
+ ) -> typing.Union[dict, typing.Any, None]:
124
+ """
125
+ Converts a string to a JSON object.
126
+
127
+ Args:
128
+ value: The value to convert (string, list, or dict).
129
+ raise_on_error: Whether to raise an exception on error.
130
+ retry: The number of retry attempts made.
131
+
132
+ Returns:
133
+ The converted JSON object, or the original value if conversion fails.
134
+ """
135
+ # Handle empty/None values
136
+ if not value:
137
+ return {}
138
+
139
+ # Return dicts unchanged
140
+ if isinstance(value, dict):
141
+ return value
142
+
143
+ # Check retry limit early
144
+ if retry > 5:
145
+ raise RuntimeError("Too many attempts to convert string to JSON")
146
+
147
+ try:
148
+ # Convert to string if needed
149
+ if not isinstance(value, str):
150
+ value = str(value)
151
+
152
+ # Clean up the string
153
+ value = value.replace("\n", "").strip()
154
+ if value.startswith("'") and value.endswith("'"):
155
+ value = value.strip("'").strip()
156
+
157
+ # Parse JSON
158
+ parsed_value = json.loads(value)
159
+
160
+ # Handle nested string JSON (recursive case)
161
+ if isinstance(parsed_value, str):
162
+ return JsonConversions.string_to_json_obj(parsed_value, raise_on_error, retry + 1)
163
+
164
+ return parsed_value
165
+
166
+ except json.JSONDecodeError as e:
167
+ # Try to fix malformed JSON with single quotes
168
+ if "Expecting property name enclosed in double quotes" in str(e) and retry < 5:
169
+ if isinstance(value, str):
170
+ fixed_json = JsonConversions.convert_bad_json_string(value)
171
+ return JsonConversions.string_to_json_obj(fixed_json, raise_on_error, retry + 1)
172
+
173
+ if raise_on_error:
174
+ raise e
175
+ return {}
176
+
177
+ except Exception as e:
178
+ if raise_on_error:
179
+ logger.exception({"source": "string_to_json_obj", "error": str(e), "value": value})
180
+ raise e
181
+
182
+ logger.warning({"source": "string_to_json_obj", "returning_original": True, "value": value})
183
+ return value
184
+
185
+
186
+ @staticmethod
187
+ def convert_bad_json_string(bad_json: str) -> str:
188
+ """
189
+ Fixes malformed JSON by converting single quotes to double quotes.
190
+
191
+ Args:
192
+ bad_json: Malformed JSON string with single quotes.
193
+
194
+ Returns:
195
+ Fixed JSON string with proper double quotes.
196
+ """
197
+ # Use a placeholder to safely swap quotes
198
+ return bad_json.replace("'", "§§§").replace('"', "'").replace("§§§", '"')
199
+
119
200
  @staticmethod
120
201
  def _camel_to_snake(value: str) -> str:
121
202
  """Converts a camelCase to a snake_case"""
boto3_assist/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.27.0"
1
+ __version__ = "0.28.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boto3_assist
3
- Version: 0.27.0
3
+ Version: 0.28.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
@@ -6,7 +6,7 @@ boto3_assist/connection_tracker.py,sha256=UgfR9RlvXf3A4ssMr3gDMpw89ka8mSRvJn4M34
6
6
  boto3_assist/http_status_codes.py,sha256=G0zRSWenwavYKETvDF9tNVUXQz3Ae2gXdBETYbjvJe8,3284
7
7
  boto3_assist/role_assumption_mixin.py,sha256=PMUU5yC2FUBjFD1UokVkRY3CPB5zTw85AhIB5BMtbc8,1031
8
8
  boto3_assist/session_setup_mixin.py,sha256=X-JQKyyaWNA8Z8kKgf2V2I5vsiLAH8udLTX_xepnsdQ,3140
9
- boto3_assist/version.py,sha256=Hjsc9XQ3AkqXm-5cdlX-H8iKjURzi1FQeWNi2xx34Uo,23
9
+ boto3_assist/version.py,sha256=MRQGtOXBhcDKeeNOL0LiB-cllo6kfd8_KGJOvaDp0XQ,23
10
10
  boto3_assist/aws_lambda/event_info.py,sha256=OkZ4WzuGaHEu_T8sB188KBgShAJhZpWASALKRGBOhMg,14648
11
11
  boto3_assist/aws_lambda/mock_context.py,sha256=LPjHP-3YSoY6iPl1kPqJDwSVf1zLNTcukUunDtYcbK0,116
12
12
  boto3_assist/cloudwatch/cloudwatch_connection.py,sha256=mnGWaLSQpHh5EeY7Ek_2o9JKHJxOELIYtQVMX1IaHn4,2480
@@ -57,10 +57,10 @@ boto3_assist/utilities/file_operations.py,sha256=IYhJkh8wUPMvGnyDRRa9yOCDdHN9wR3
57
57
  boto3_assist/utilities/http_utility.py,sha256=_K39Fq0V4QcgklAWctUktuMjqXDTwgMld77IOUfR2zc,1282
58
58
  boto3_assist/utilities/logging_utility.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  boto3_assist/utilities/numbers_utility.py,sha256=wzv9d0uXT_2_ZHHio7LBzibwxPqhGpvbq9HinrVn_4A,10160
60
- boto3_assist/utilities/serialization_utility.py,sha256=Jc6H0cpcZjLO7tdyUZdBWHzItduLkw6sh2YQh8Hc8D8,21647
60
+ boto3_assist/utilities/serialization_utility.py,sha256=m5wRZNeWW9VltQPVNziR27OGKO3MDJm6mFmcDHwN-n4,24479
61
61
  boto3_assist/utilities/string_utility.py,sha256=XxUIz19L2LFFTRDAAmdPa8Qhn40u9yO7g4nULFuvg0M,11033
62
- boto3_assist-0.27.0.dist-info/METADATA,sha256=TllhWhaq5HhYO5rvlpXwLoEpYVmEsFIsIq2Sl27t4Qs,2879
63
- boto3_assist-0.27.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
64
- boto3_assist-0.27.0.dist-info/licenses/LICENSE-EXPLAINED.txt,sha256=WFREvTpfTjPjDHpOLADxJpCKpIla3Ht87RUUGii4ODU,606
65
- boto3_assist-0.27.0.dist-info/licenses/LICENSE.txt,sha256=PXDhFWS5L5aOTkVhNvoitHKbAkgxqMI2uUPQyrnXGiI,1105
66
- boto3_assist-0.27.0.dist-info/RECORD,,
62
+ boto3_assist-0.28.0.dist-info/METADATA,sha256=XrwSSxvnnUASG0OPp4ulP99LgF8CTTcwExXgXbZG1UE,2879
63
+ boto3_assist-0.28.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
64
+ boto3_assist-0.28.0.dist-info/licenses/LICENSE-EXPLAINED.txt,sha256=WFREvTpfTjPjDHpOLADxJpCKpIla3Ht87RUUGii4ODU,606
65
+ boto3_assist-0.28.0.dist-info/licenses/LICENSE.txt,sha256=PXDhFWS5L5aOTkVhNvoitHKbAkgxqMI2uUPQyrnXGiI,1105
66
+ boto3_assist-0.28.0.dist-info/RECORD,,