nui-python-shared-utils 2.2__py3-none-any.whl → 2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nui-python-shared-utils
3
- Version: 2.2
3
+ Version: 2.3
4
4
  Summary: Shared Python utilities for AWS Lambda, CLI tools, and agents with Slack, Elasticsearch, and monitoring integrations
5
5
  Home-page: https://github.com/nuimarkets/nui-python-shared-utils
6
6
  Author: NUI Markets
@@ -1,4 +1,4 @@
1
- nui_python_shared_utils-2.2.dist-info/licenses/LICENSE,sha256=vGe2mC5yLUb8toYlY3T36ZwCB5zQUW5hlCtEMiqokhM,1071
1
+ nui_python_shared_utils-2.3.dist-info/licenses/LICENSE,sha256=vGe2mC5yLUb8toYlY3T36ZwCB5zQUW5hlCtEMiqokhM,1071
2
2
  nui_shared_utils/__init__.py,sha256=wbm10x7THNbrCBGClWiWSVkTNxcBKcHZ-HjYpRQBFrk,13354
3
3
  nui_shared_utils/base_client.py,sha256=I1lKQGhrKyvujV2zps0TrtEdPDqMCwRQaIh6ceGONXQ,11016
4
4
  nui_shared_utils/cli.py,sha256=JJpSoQWKvAz4b8cO30yFNi5vY9jmqrCHzbFpvrVTkbU,8747
@@ -12,7 +12,7 @@ nui_shared_utils/jwt_auth.py,sha256=2Ag1zZKxd2R8QBz3aQA4h8OtKHQvUVKrjUp6lXpJxJU,
12
12
  nui_shared_utils/lambda_helpers.py,sha256=psHVotpmOfnmyQCoOt4MSIEj7VwWcy6gZM3vYSZwjOk,3041
13
13
  nui_shared_utils/llm.py,sha256=adNUO8Qbeb3__GvpROxWSUERkpiazKiGJFE5xzU5eZ0,8351
14
14
  nui_shared_utils/log_processors.py,sha256=x5gz1LEkbmoMCZ3ZB6q-mbn26dSzwh1trz4wSkBGxqk,5538
15
- nui_shared_utils/powertools_helpers.py,sha256=qc-lYLfY-QX20gALfPOJcihrtJhiCU-fJW8rsPT7LJE,11037
15
+ nui_shared_utils/powertools_helpers.py,sha256=R4awhoo0w0niL662DMZvNa5sDjjP8Vh6m0pSpnOD1aU,12286
16
16
  nui_shared_utils/secrets_helper.py,sha256=_jQkMWzjayZ8vvyHG2yuuxur-SQYUUONfcsZ0MF8qOw,7025
17
17
  nui_shared_utils/slack_client.py,sha256=jvkLeBMA8WHOqdRzCEpG42FfBlMeWue8bZ1g1ZxF-UI,40304
18
18
  nui_shared_utils/slack_formatter.py,sha256=QT9VXApE0q09n_PmEVvaLCSfLW24vmowlCXF3Dzimfk,10850
@@ -27,8 +27,8 @@ nui_shared_utils/slack_setup/__init__.py,sha256=OElyS3xk4F_YKH5uUUTDpN0ah1dOO3e5
27
27
  nui_shared_utils/slack_setup/channel_creator.py,sha256=0gyCBIS0EC96SVn1Z2dD4Fpzk0xNdHSWyiCxoUQIUe8,10667
28
28
  nui_shared_utils/slack_setup/channel_definitions.py,sha256=atfz5ZhpqefOeLh1gShbWd-TLzgjPmhv95bfuTdmZog,5676
29
29
  nui_shared_utils/slack_setup/setup_helpers.py,sha256=pzzXMs12GI9sdZttWeYzgLPgC0xqPz7ZLHM1GUPNNXc,7219
30
- nui_python_shared_utils-2.2.dist-info/METADATA,sha256=QsygJarXaIbwKBA4-jRoTNQdsUHPvdgA0vtiVHWGsBw,22688
31
- nui_python_shared_utils-2.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
32
- nui_python_shared_utils-2.2.dist-info/entry_points.txt,sha256=TrJ3Z4kz3oXfy6InXn20jHu7rnTwo-4EA0KRFX3fkL0,66
33
- nui_python_shared_utils-2.2.dist-info/top_level.txt,sha256=YMRu5cnn3hxHoYq9wNvaI9atVHnTNVdswO5_cQSfnJI,17
34
- nui_python_shared_utils-2.2.dist-info/RECORD,,
30
+ nui_python_shared_utils-2.3.dist-info/METADATA,sha256=Ma366Cqx3pp_PW7xaSA-n1UmeniBgjvShEwb96vdOgc,22688
31
+ nui_python_shared_utils-2.3.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
32
+ nui_python_shared_utils-2.3.dist-info/entry_points.txt,sha256=TrJ3Z4kz3oXfy6InXn20jHu7rnTwo-4EA0KRFX3fkL0,66
33
+ nui_python_shared_utils-2.3.dist-info/top_level.txt,sha256=YMRu5cnn3hxHoYq9wNvaI9atVHnTNVdswO5_cQSfnJI,17
34
+ nui_python_shared_utils-2.3.dist-info/RECORD,,
@@ -145,6 +145,17 @@ def get_powertools_logger(
145
145
  return powertools_logger
146
146
 
147
147
 
148
+ def _is_sqs_event(event: Any) -> bool:
149
+ """True when ``event`` is a batch delivered by an SQS event source mapping."""
150
+ if not isinstance(event, dict):
151
+ return False
152
+ records = event.get("Records")
153
+ if not isinstance(records, list) or not records:
154
+ return False
155
+ first = records[0]
156
+ return isinstance(first, dict) and first.get("eventSource") == "aws:sqs"
157
+
158
+
148
159
  def powertools_handler(
149
160
  service_name: str,
150
161
  metrics_namespace: Optional[str] = None,
@@ -199,8 +210,17 @@ def powertools_handler(
199
210
  ... return {"statusCode": 200}
200
211
 
201
212
  Note:
202
- The decorated handler must return a dict with statusCode and optional body.
203
- On exception, returns: {"statusCode": 500, "body": "Internal Server Error"}
213
+ The handler's return value passes through unchanged: a ``statusCode`` dict
214
+ for API Gateway, ``{"batchItemFailures": [...]}`` for an SQS mapping with
215
+ ``ReportBatchItemFailures``.
216
+
217
+ On exception, returns ``{"statusCode": 500, "body": "Internal Server Error"}``,
218
+ except for SQS events, where the exception is re-raised after logging and
219
+ alerting. A returned value tells the SQS mapping the batch succeeded (with
220
+ ``ReportBatchItemFailures``, a response without ``batchItemFailures`` means
221
+ every record did), so the 500 dict would delete the batch. Re-raising leaves
222
+ it on the queue for redelivery, and in the DLQ after ``maxReceiveCount``
223
+ when the queue has a redrive policy.
204
224
  """
205
225
 
206
226
  def decorator(func: Callable) -> Callable:
@@ -231,6 +251,9 @@ def powertools_handler(
231
251
  if slack_client:
232
252
  slack_client.set_handler_context(context)
233
253
 
254
+ # Classify before the handler runs: it may consume or mutate event["Records"].
255
+ is_sqs = _is_sqs_event(event)
256
+
234
257
  try:
235
258
  # Apply logger context injection
236
259
  # Note: inject_lambda_context is added dynamically to logging.Logger (line 95)
@@ -274,6 +297,10 @@ def powertools_handler(
274
297
  except Exception as slack_error:
275
298
  logger.warning("Failed to send Slack alert: %s", slack_error)
276
299
 
300
+ # Re-raise for SQS so the batch stays on the queue; see the Note above.
301
+ if is_sqs:
302
+ raise
303
+
277
304
  # Return proper Lambda error response
278
305
  return {
279
306
  "statusCode": 500,