aws-lambda-powertools 2.14.0__tar.gz → 2.15.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 (164) hide show
  1. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/PKG-INFO +28 -2
  2. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/README.md +26 -1
  3. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/formatter.py +2 -2
  4. aws_lambda_powertools-2.15.0/aws_lambda_powertools/logging/formatters/__init__.py +5 -0
  5. aws_lambda_powertools-2.15.0/aws_lambda_powertools/logging/formatters/datadog.py +77 -0
  6. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/metrics/base.py +23 -10
  7. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/batch/base.py +18 -7
  8. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/batch/exceptions.py +5 -3
  9. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py +9 -2
  10. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/code_pipeline_job_event.py +2 -0
  11. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/common.py +56 -3
  12. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/kafka_event.py +2 -3
  13. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/kinesis_firehose_event.py +2 -3
  14. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/sqs_event.py +43 -2
  15. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/jmespath_utils/envelopes.py +5 -0
  16. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/__init__.py +6 -0
  17. aws_lambda_powertools-2.15.0/aws_lambda_powertools/utilities/parser/models/s3_event_notification.py +14 -0
  18. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/sqs.py +2 -2
  19. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/pyproject.toml +11 -10
  20. aws_lambda_powertools-2.15.0/setup.py +64 -0
  21. aws_lambda_powertools-2.14.0/setup.py +0 -63
  22. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/LICENSE +0 -0
  23. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/THIRD-PARTY-LICENSES +0 -0
  24. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/__init__.py +0 -0
  25. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/event_handler/__init__.py +0 -0
  26. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/event_handler/api_gateway.py +0 -0
  27. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/event_handler/appsync.py +0 -0
  28. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/event_handler/content_types.py +0 -0
  29. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/event_handler/exceptions.py +0 -0
  30. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/event_handler/lambda_function_url.py +0 -0
  31. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/event_handler/router.py +0 -0
  32. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/exceptions/__init__.py +0 -0
  33. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/__init__.py +0 -0
  34. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/correlation_paths.py +0 -0
  35. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/exceptions.py +0 -0
  36. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/filters.py +0 -0
  37. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/lambda_context.py +0 -0
  38. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/logger.py +0 -0
  39. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/logging/utils.py +0 -0
  40. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/metrics/__init__.py +0 -0
  41. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/metrics/exceptions.py +0 -0
  42. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/metrics/metric.py +0 -0
  43. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/metrics/metrics.py +0 -0
  44. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/metrics/types.py +0 -0
  45. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/middleware_factory/__init__.py +0 -0
  46. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/middleware_factory/exceptions.py +0 -0
  47. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/middleware_factory/factory.py +0 -0
  48. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/package_logger.py +0 -0
  49. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/py.typed +0 -0
  50. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/__init__.py +0 -0
  51. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/cache_dict.py +0 -0
  52. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/constants.py +0 -0
  53. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/cookies.py +0 -0
  54. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/functions.py +0 -0
  55. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/headers_serializer.py +0 -0
  56. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/json_encoder.py +0 -0
  57. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/lazy_import.py +0 -0
  58. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/shared/types.py +0 -0
  59. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/tracing/__init__.py +0 -0
  60. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/tracing/base.py +0 -0
  61. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/tracing/extensions.py +0 -0
  62. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/tracing/tracer.py +0 -0
  63. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/__init__.py +0 -0
  64. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/batch/__init__.py +0 -0
  65. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/batch/decorators.py +0 -0
  66. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py +0 -0
  67. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/batch/types.py +0 -0
  68. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/__init__.py +0 -0
  69. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/active_mq_event.py +0 -0
  70. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/alb_event.py +0 -0
  71. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py +0 -0
  72. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/appsync/__init__.py +0 -0
  73. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/appsync/scalar_types_utils.py +0 -0
  74. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/appsync_authorizer_event.py +0 -0
  75. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py +0 -0
  76. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_custom_widget_event.py +0 -0
  77. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_logs_event.py +0 -0
  78. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/cognito_user_pool_event.py +0 -0
  79. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/connect_contact_flow_event.py +0 -0
  80. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/dynamo_db_stream_event.py +0 -0
  81. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py +0 -0
  82. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/event_source.py +0 -0
  83. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/kinesis_stream_event.py +0 -0
  84. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/lambda_function_url_event.py +0 -0
  85. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/rabbit_mq_event.py +0 -0
  86. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/s3_event.py +0 -0
  87. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/s3_object_event.py +0 -0
  88. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/ses_event.py +0 -0
  89. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/data_classes/sns_event.py +0 -0
  90. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/feature_flags/__init__.py +0 -0
  91. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/feature_flags/appconfig.py +0 -0
  92. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/feature_flags/base.py +0 -0
  93. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/feature_flags/exceptions.py +0 -0
  94. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +0 -0
  95. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/feature_flags/schema.py +0 -0
  96. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/feature_flags/time_conditions.py +0 -0
  97. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/__init__.py +0 -0
  98. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/base.py +0 -0
  99. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/config.py +0 -0
  100. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/exceptions.py +0 -0
  101. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/idempotency.py +0 -0
  102. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/persistence/__init__.py +0 -0
  103. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/persistence/base.py +0 -0
  104. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py +0 -0
  105. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/jmespath_utils/__init__.py +0 -0
  106. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/__init__.py +0 -0
  107. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/appconfig.py +0 -0
  108. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/base.py +0 -0
  109. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/dynamodb.py +0 -0
  110. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/exceptions.py +0 -0
  111. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/secrets.py +0 -0
  112. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/ssm.py +0 -0
  113. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parameters/types.py +0 -0
  114. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/__init__.py +0 -0
  115. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/__init__.py +0 -0
  116. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/apigw.py +0 -0
  117. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py +0 -0
  118. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/base.py +0 -0
  119. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py +0 -0
  120. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py +0 -0
  121. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py +0 -0
  122. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/kafka.py +0 -0
  123. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py +0 -0
  124. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py +0 -0
  125. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py +0 -0
  126. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/sns.py +0 -0
  127. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/envelopes/sqs.py +0 -0
  128. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/exceptions.py +0 -0
  129. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/alb.py +0 -0
  130. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/apigw.py +0 -0
  131. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/apigwv2.py +0 -0
  132. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/cloudwatch.py +0 -0
  133. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/dynamodb.py +0 -0
  134. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/event_bridge.py +0 -0
  135. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/kafka.py +0 -0
  136. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/kinesis.py +0 -0
  137. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py +0 -0
  138. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/lambda_function_url.py +0 -0
  139. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/s3.py +0 -0
  140. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/s3_object_event.py +0 -0
  141. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/ses.py +0 -0
  142. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/models/sns.py +0 -0
  143. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/parser.py +0 -0
  144. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/pydantic.py +0 -0
  145. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/parser/types.py +0 -0
  146. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/__init__.py +0 -0
  147. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py +0 -0
  148. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/compat.py +0 -0
  149. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/s3_object.py +0 -0
  150. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/transformations/__init__.py +0 -0
  151. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/transformations/base.py +0 -0
  152. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/transformations/csv.py +0 -0
  153. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/transformations/gzip.py +0 -0
  154. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/streaming/transformations/zip.py +0 -0
  155. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/typing/__init__.py +0 -0
  156. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/typing/lambda_client_context.py +0 -0
  157. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/typing/lambda_client_context_mobile_client.py +0 -0
  158. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/typing/lambda_cognito_identity.py +0 -0
  159. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/typing/lambda_context.py +0 -0
  160. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/validation/__init__.py +0 -0
  161. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/validation/base.py +0 -0
  162. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/validation/envelopes.py +0 -0
  163. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/validation/exceptions.py +0 -0
  164. {aws_lambda_powertools-2.14.0 → aws_lambda_powertools-2.15.0}/aws_lambda_powertools/utilities/validation/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aws-lambda-powertools
3
- Version: 2.14.0
3
+ Version: 2.15.0
4
4
  Summary: AWS Lambda Powertools is a developer toolkit to implement Serverless best practices and increase developer velocity.
5
5
  Home-page: https://github.com/awslabs/aws-lambda-powertools-python
6
6
  License: MIT
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.8
17
17
  Classifier: Programming Language :: Python :: 3.9
18
18
  Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.10
20
21
  Classifier: Programming Language :: Python :: 3.7
21
22
  Classifier: Programming Language :: Python :: 3.8
22
23
  Classifier: Programming Language :: Python :: 3.9
@@ -41,7 +42,7 @@ Description-Content-Type: text/markdown
41
42
 
42
43
  [![Build](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/python_build.yml/badge.svg)](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/python_build.yml)
43
44
  [![codecov.io](https://codecov.io/github/awslabs/aws-lambda-powertools-python/branch/develop/graphs/badge.svg)](https://app.codecov.io/gh/awslabs/aws-lambda-powertools-python)
44
- ![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.7|%203.8|%203.9&color=blue?style=flat-square&logo=python) ![PyPI version](https://badge.fury.io/py/aws-lambda-powertools.svg) ![PyPi monthly downloads](https://img.shields.io/pypi/dm/aws-lambda-powertools) [![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET)
45
+ ![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.7|%203.8|%203.9|%203.10&color=blue?style=flat-square&logo=python) ![PyPI version](https://badge.fury.io/py/aws-lambda-powertools.svg) ![PyPi monthly downloads](https://img.shields.io/pypi/dm/aws-lambda-powertools) [![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET)
45
46
 
46
47
  Powertools is a developer toolkit to implement Serverless [best practices and increase developer velocity](https://awslabs.github.io/aws-lambda-powertools-python/latest/#features).
47
48
 
@@ -83,6 +84,31 @@ With [pip](https://pip.pypa.io/en/latest/index.html) installed, run: ``pip insta
83
84
  * [Serverless E-commerce platform](https://github.com/aws-samples/aws-serverless-ecommerce-platform)
84
85
  * [Serverless GraphQL Nanny Booking Api](https://github.com/trey-rosius/babysitter_api)
85
86
 
87
+ ## How to support AWS Lambda Powertools for Python?
88
+
89
+ ### Becoming a reference customer
90
+
91
+ Knowing which companies are using this library is important to help prioritize the project internally. If your company is using AWS Lambda Powertools for Python, you can request to have your name and logo added to the README file by raising a [Support Lambda Powertools (become a reference)](https://github.com/awslabs/aws-lambda-powertools-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E) issue.
92
+
93
+ The following companies, among others, use Powertools:
94
+
95
+ * [CPQi (Exadel Financial Services)](https://cpqi.com/)
96
+ * [CloudZero](https://www.cloudzero.com/)
97
+ * [CyberArk](https://www.cyberark.com/)
98
+ * [globaldatanet](https://globaldatanet.com/)
99
+ * [IMS](https://ims.tech/)
100
+ * [Propellor.ai](https://www.propellor.ai/)
101
+ * [TopSport](https://www.topsport.com.au/)
102
+ * [Trek10](https://www.trek10.com/)
103
+
104
+ ### Sharing your work
105
+
106
+ Share what you did with Powertools 💞💞. Blog post, workshops, presentation, sample apps and others. Check out what the community has already shared about Powertools [here](https://awslabs.github.io/aws-lambda-powertools-python/latest/we_made_this/).
107
+
108
+ ### Using Lambda Layer or SAR
109
+
110
+ This helps us understand who uses Powertools in a non-intrusive way, and helps us gain future investments for other Powertools languages. When [using Layers](https://awslabs.github.io/aws-lambda-powertools-python/latest/#lambda-layer), you can add Powertools as a dev dependency (or as part of your virtual env) to not impact the development process.
111
+
86
112
  ## Credits
87
113
 
88
114
  * Structured logging initial implementation from [aws-lambda-logging](https://gitlab.com/hadrien/aws_lambda_logging)
@@ -3,7 +3,7 @@
3
3
 
4
4
  [![Build](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/python_build.yml/badge.svg)](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/python_build.yml)
5
5
  [![codecov.io](https://codecov.io/github/awslabs/aws-lambda-powertools-python/branch/develop/graphs/badge.svg)](https://app.codecov.io/gh/awslabs/aws-lambda-powertools-python)
6
- ![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.7|%203.8|%203.9&color=blue?style=flat-square&logo=python) ![PyPI version](https://badge.fury.io/py/aws-lambda-powertools.svg) ![PyPi monthly downloads](https://img.shields.io/pypi/dm/aws-lambda-powertools) [![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET)
6
+ ![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.7|%203.8|%203.9|%203.10&color=blue?style=flat-square&logo=python) ![PyPI version](https://badge.fury.io/py/aws-lambda-powertools.svg) ![PyPi monthly downloads](https://img.shields.io/pypi/dm/aws-lambda-powertools) [![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET)
7
7
 
8
8
  Powertools is a developer toolkit to implement Serverless [best practices and increase developer velocity](https://awslabs.github.io/aws-lambda-powertools-python/latest/#features).
9
9
 
@@ -45,6 +45,31 @@ With [pip](https://pip.pypa.io/en/latest/index.html) installed, run: ``pip insta
45
45
  * [Serverless E-commerce platform](https://github.com/aws-samples/aws-serverless-ecommerce-platform)
46
46
  * [Serverless GraphQL Nanny Booking Api](https://github.com/trey-rosius/babysitter_api)
47
47
 
48
+ ## How to support AWS Lambda Powertools for Python?
49
+
50
+ ### Becoming a reference customer
51
+
52
+ Knowing which companies are using this library is important to help prioritize the project internally. If your company is using AWS Lambda Powertools for Python, you can request to have your name and logo added to the README file by raising a [Support Lambda Powertools (become a reference)](https://github.com/awslabs/aws-lambda-powertools-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E) issue.
53
+
54
+ The following companies, among others, use Powertools:
55
+
56
+ * [CPQi (Exadel Financial Services)](https://cpqi.com/)
57
+ * [CloudZero](https://www.cloudzero.com/)
58
+ * [CyberArk](https://www.cyberark.com/)
59
+ * [globaldatanet](https://globaldatanet.com/)
60
+ * [IMS](https://ims.tech/)
61
+ * [Propellor.ai](https://www.propellor.ai/)
62
+ * [TopSport](https://www.topsport.com.au/)
63
+ * [Trek10](https://www.trek10.com/)
64
+
65
+ ### Sharing your work
66
+
67
+ Share what you did with Powertools 💞💞. Blog post, workshops, presentation, sample apps and others. Check out what the community has already shared about Powertools [here](https://awslabs.github.io/aws-lambda-powertools-python/latest/we_made_this/).
68
+
69
+ ### Using Lambda Layer or SAR
70
+
71
+ This helps us understand who uses Powertools in a non-intrusive way, and helps us gain future investments for other Powertools languages. When [using Layers](https://awslabs.github.io/aws-lambda-powertools-python/latest/#lambda-layer), you can add Powertools as a dev dependency (or as part of your virtual env) to not impact the development process.
72
+
48
73
  ## Credits
49
74
 
50
75
  * Structured logging initial implementation from [aws-lambda-logging](https://gitlab.com/hadrien/aws_lambda_logging)
@@ -139,11 +139,11 @@ class LambdaPowertoolsFormatter(BasePowertoolsFormatter):
139
139
  if self.utc:
140
140
  self.converter = time.gmtime
141
141
 
142
- super(LambdaPowertoolsFormatter, self).__init__(datefmt=self.datefmt)
143
-
144
142
  self.keys_combined = {**self._build_default_keys(), **kwargs}
145
143
  self.log_format.update(**self.keys_combined)
146
144
 
145
+ super().__init__(datefmt=self.datefmt)
146
+
147
147
  def serialize(self, log: Dict) -> str:
148
148
  """Serialize structured log dict to JSON str"""
149
149
  return self.json_serializer(log)
@@ -0,0 +1,5 @@
1
+ """Built-in Logger formatters for Observability Providers that require custom config."""
2
+
3
+ # NOTE: we don't expose formatters directly (barrel import)
4
+ # as we cannot know if they'll need additional dependencies in the future
5
+ # so we isolate to avoid a performance hit and workarounds like lazy imports
@@ -0,0 +1,77 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Callable
4
+
5
+ from aws_lambda_powertools.logging.formatter import LambdaPowertoolsFormatter
6
+
7
+
8
+ class DatadogLogFormatter(LambdaPowertoolsFormatter):
9
+ def __init__(
10
+ self,
11
+ json_serializer: Callable[[dict], str] | None = None,
12
+ json_deserializer: Callable[[dict | str | bool | int | float], str] | None = None,
13
+ json_default: Callable[[Any], Any] | None = None,
14
+ datefmt: str | None = None,
15
+ use_datetime_directive: bool = False,
16
+ log_record_order: list[str] | None = None,
17
+ utc: bool = False,
18
+ use_rfc3339: bool = True, # NOTE: The only change from our base formatter
19
+ **kwargs,
20
+ ):
21
+ """Datadog formatter to comply with Datadog log parsing
22
+
23
+ Changes compared to the default Logger Formatter:
24
+
25
+ - timestamp format to use RFC3339 e.g., "2023-05-01T15:34:26.841+0200"
26
+
27
+
28
+ Parameters
29
+ ----------
30
+ log_record_order : list[str] | None, optional
31
+ _description_, by default None
32
+
33
+ Parameters
34
+ ----------
35
+ json_serializer : Callable, optional
36
+ function to serialize `obj` to a JSON formatted `str`, by default json.dumps
37
+ json_deserializer : Callable, optional
38
+ function to deserialize `str`, `bytes`, bytearray` containing a JSON document to a Python `obj`,
39
+ by default json.loads
40
+ json_default : Callable, optional
41
+ function to coerce unserializable values, by default str
42
+
43
+ Only used when no custom JSON encoder is set
44
+
45
+ datefmt : str, optional
46
+ String directives (strftime) to format log timestamp.
47
+
48
+ See https://docs.python.org/3/library/time.html#time.strftime or
49
+ use_datetime_directive: str, optional
50
+ Interpret `datefmt` as a format string for `datetime.datetime.strftime`, rather than
51
+ `time.strftime` - Only useful when used alongside `datefmt`.
52
+
53
+ See https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior . This
54
+ also supports a custom %F directive for milliseconds.
55
+
56
+ log_record_order : list, optional
57
+ set order of log keys when logging, by default ["level", "location", "message", "timestamp"]
58
+
59
+ utc : bool, optional
60
+ set logging timestamp to UTC, by default False to continue to use local time as per stdlib
61
+ use_rfc3339: bool, optional
62
+ Whether to use a popular dateformat that complies with both RFC3339 and ISO8601.
63
+ e.g., 2022-10-27T16:27:43.738+02:00.
64
+ kwargs
65
+ Key-value to persist in all log messages
66
+ """
67
+ super().__init__(
68
+ json_serializer=json_serializer,
69
+ json_deserializer=json_deserializer,
70
+ json_default=json_default,
71
+ datefmt=datefmt,
72
+ use_datetime_directive=use_datetime_directive,
73
+ log_record_order=log_record_order,
74
+ utc=utc,
75
+ use_rfc3339=use_rfc3339,
76
+ **kwargs,
77
+ )
@@ -328,6 +328,28 @@ class MetricManager:
328
328
  self.dimension_set.clear()
329
329
  self.metadata_set.clear()
330
330
 
331
+ def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None:
332
+ """Manually flushes the metrics. This is normally not necessary,
333
+ unless you're running on other runtimes besides Lambda, where the @log_metrics
334
+ decorator already handles things for you.
335
+
336
+ Parameters
337
+ ----------
338
+ raise_on_empty_metrics : bool, optional
339
+ raise exception if no metrics are emitted, by default False
340
+ """
341
+ if not raise_on_empty_metrics and not self.metric_set:
342
+ warnings.warn(
343
+ "No application metrics to publish. The cold-start metric may be published if enabled. "
344
+ "If application metrics should never be empty, consider using 'raise_on_empty_metrics'",
345
+ stacklevel=2,
346
+ )
347
+ else:
348
+ logger.debug("Flushing existing metrics")
349
+ metrics = self.serialize_metric_set()
350
+ print(json.dumps(metrics, separators=(",", ":")))
351
+ self.clear_metrics()
352
+
331
353
  def log_metrics(
332
354
  self,
333
355
  lambda_handler: Union[Callable[[Dict, Any], Any], Optional[Callable[[Dict, Any, Optional[Dict]], Any]]] = None,
@@ -390,16 +412,7 @@ class MetricManager:
390
412
  if capture_cold_start_metric:
391
413
  self._add_cold_start_metric(context=context)
392
414
  finally:
393
- if not raise_on_empty_metrics and not self.metric_set:
394
- warnings.warn(
395
- "No application metrics to publish. The cold-start metric may be published if enabled. "
396
- "If application metrics should never be empty, consider using 'raise_on_empty_metrics'",
397
- stacklevel=2,
398
- )
399
- else:
400
- metrics = self.serialize_metric_set()
401
- self.clear_metrics()
402
- print(json.dumps(metrics, separators=(",", ":")))
415
+ self.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics)
403
416
 
404
417
  return response
405
418
 
@@ -26,7 +26,6 @@ from aws_lambda_powertools.utilities.data_classes.kinesis_stream_event import (
26
26
  KinesisStreamRecord,
27
27
  )
28
28
  from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
29
- from aws_lambda_powertools.utilities.parser import ValidationError
30
29
  from aws_lambda_powertools.utilities.typing import LambdaContext
31
30
 
32
31
  logger = logging.getLogger(__name__)
@@ -496,9 +495,15 @@ class BatchProcessor(BasePartialBatchProcessor): # Keep old name for compatibil
496
495
  result = self.handler(record=data)
497
496
 
498
497
  return self.success_handler(record=record, result=result)
499
- except ValidationError:
500
- return self._register_model_validation_error_record(record)
501
- except Exception:
498
+ except Exception as exc:
499
+ # NOTE: Pydantic is an optional dependency, but when used and a poison pill scenario happens
500
+ # we need to handle that exception differently.
501
+ # We check for a public attr in validation errors coming from Pydantic exceptions (subclass or not)
502
+ # and we compare if it's coming from the same model that trigger the exception in the first place
503
+ model = getattr(exc, "model", None)
504
+ if model == self.model:
505
+ return self._register_model_validation_error_record(record)
506
+
502
507
  return self.failure_handler(record=data, exception=sys.exc_info())
503
508
 
504
509
 
@@ -634,7 +639,13 @@ class AsyncBatchProcessor(BasePartialBatchProcessor):
634
639
  result = await self.handler(record=data)
635
640
 
636
641
  return self.success_handler(record=record, result=result)
637
- except ValidationError:
638
- return self._register_model_validation_error_record(record)
639
- except Exception:
642
+ except Exception as exc:
643
+ # NOTE: Pydantic is an optional dependency, but when used and a poison pill scenario happens
644
+ # we need to handle that exception differently.
645
+ # We check for a public attr in validation errors coming from Pydantic exceptions (subclass or not)
646
+ # and we compare if it's coming from the same model that trigger the exception in the first place
647
+ model = getattr(exc, "model", None)
648
+ if model == self.model:
649
+ return self._register_model_validation_error_record(record)
650
+
640
651
  return self.failure_handler(record=data, exception=sys.exc_info())
@@ -1,6 +1,8 @@
1
1
  """
2
2
  Batch processing exceptions
3
3
  """
4
+ from __future__ import annotations
5
+
4
6
  import traceback
5
7
  from types import TracebackType
6
8
  from typing import List, Optional, Tuple, Type
@@ -9,10 +11,10 @@ ExceptionInfo = Tuple[Optional[Type[BaseException]], Optional[BaseException], Op
9
11
 
10
12
 
11
13
  class BaseBatchProcessingError(Exception):
12
- def __init__(self, msg="", child_exceptions: Optional[List[ExceptionInfo]] = None):
14
+ def __init__(self, msg="", child_exceptions: List[ExceptionInfo] | None = None):
13
15
  super().__init__(msg)
14
16
  self.msg = msg
15
- self.child_exceptions = child_exceptions
17
+ self.child_exceptions = child_exceptions or []
16
18
 
17
19
  def format_exceptions(self, parent_exception_str):
18
20
  exception_list = [f"{parent_exception_str}\n"]
@@ -27,7 +29,7 @@ class BaseBatchProcessingError(Exception):
27
29
  class BatchProcessingError(BaseBatchProcessingError):
28
30
  """When all batch records failed to be processed"""
29
31
 
30
- def __init__(self, msg="", child_exceptions: Optional[List[ExceptionInfo]] = None):
32
+ def __init__(self, msg="", child_exceptions: List[ExceptionInfo] | None = None):
31
33
  super().__init__(msg, child_exceptions)
32
34
 
33
35
  def __str__(self):
@@ -21,8 +21,9 @@ class APIGatewayRouteArn:
21
21
  stage: str,
22
22
  http_method: str,
23
23
  resource: str,
24
+ partition: str = "aws",
24
25
  ):
25
- self.partition = "aws"
26
+ self.partition = partition
26
27
  self.region = region
27
28
  self.aws_account_id = aws_account_id
28
29
  self.api_id = api_id
@@ -55,6 +56,7 @@ def parse_api_gateway_arn(arn: str) -> APIGatewayRouteArn:
55
56
  arn_parts = arn.split(":")
56
57
  api_gateway_arn_parts = arn_parts[5].split("/")
57
58
  return APIGatewayRouteArn(
59
+ partition=arn_parts[1],
58
60
  region=arn_parts[3],
59
61
  aws_account_id=arn_parts[4],
60
62
  api_id=api_gateway_arn_parts[0],
@@ -369,6 +371,7 @@ class APIGatewayAuthorizerResponse:
369
371
  stage: str,
370
372
  context: Optional[Dict] = None,
371
373
  usage_identifier_key: Optional[str] = None,
374
+ partition: str = "aws",
372
375
  ):
373
376
  """
374
377
  Parameters
@@ -401,6 +404,9 @@ class APIGatewayAuthorizerResponse:
401
404
  If the API uses a usage plan (the apiKeySource is set to `AUTHORIZER`), the Lambda authorizer function
402
405
  must return one of the usage plan's API keys as the usageIdentifierKey property value.
403
406
  > **Note:** This only applies for REST APIs.
407
+ partition: str, optional
408
+ Optional, arn partition.
409
+ See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html
404
410
  """
405
411
  self.principal_id = principal_id
406
412
  self.region = region
@@ -412,6 +418,7 @@ class APIGatewayAuthorizerResponse:
412
418
  self._allow_routes: List[Dict] = []
413
419
  self._deny_routes: List[Dict] = []
414
420
  self._resource_pattern = re.compile(self.path_regex)
421
+ self.partition = partition
415
422
 
416
423
  @staticmethod
417
424
  def from_route_arn(
@@ -443,7 +450,7 @@ class APIGatewayAuthorizerResponse:
443
450
  raise ValueError(f"Invalid resource path: {resource}. Path should match {self.path_regex}")
444
451
 
445
452
  resource_arn = APIGatewayRouteArn(
446
- self.region, self.aws_account_id, self.api_id, self.stage, http_method, resource
453
+ self.region, self.aws_account_id, self.api_id, self.stage, http_method, resource, self.partition
447
454
  ).arn
448
455
 
449
456
  route = {"resourceArn": resource_arn, "conditions": conditions}
@@ -80,6 +80,8 @@ class CodePipelineArtifact(DictWrapper):
80
80
 
81
81
 
82
82
  class CodePipelineArtifactCredentials(DictWrapper):
83
+ _sensitive_properties = ["secret_access_key", "session_token"]
84
+
83
85
  @property
84
86
  def access_key_id(self) -> str:
85
87
  return self["accessKeyId"]
@@ -1,7 +1,7 @@
1
1
  import base64
2
2
  import json
3
3
  from collections.abc import Mapping
4
- from typing import Any, Dict, Iterator, Optional
4
+ from typing import Any, Callable, Dict, Iterator, List, Optional
5
5
 
6
6
  from aws_lambda_powertools.shared.headers_serializer import BaseHeadersSerializer
7
7
 
@@ -9,9 +9,19 @@ from aws_lambda_powertools.shared.headers_serializer import BaseHeadersSerialize
9
9
  class DictWrapper(Mapping):
10
10
  """Provides a single read only access to a wrapper dict"""
11
11
 
12
- def __init__(self, data: Dict[str, Any]):
12
+ def __init__(self, data: Dict[str, Any], json_deserializer: Optional[Callable] = None):
13
+ """
14
+ Parameters
15
+ ----------
16
+ data : Dict[str, Any]
17
+ Lambda Event Source Event payload
18
+ json_deserializer : Callable, optional
19
+ function to deserialize `str`, `bytes`, bytearray` containing a JSON document to a Python `obj`,
20
+ by default json.loads
21
+ """
13
22
  self._data = data
14
23
  self._json_data: Optional[Any] = None
24
+ self._json_deserializer = json_deserializer or json.loads
15
25
 
16
26
  def __getitem__(self, key: str) -> Any:
17
27
  return self._data[key]
@@ -28,6 +38,49 @@ class DictWrapper(Mapping):
28
38
  def __len__(self) -> int:
29
39
  return len(self._data)
30
40
 
41
+ def __str__(self) -> str:
42
+ return str(self._str_helper())
43
+
44
+ def _str_helper(self) -> Dict[str, Any]:
45
+ """
46
+ Recursively get a Dictionary of DictWrapper properties primarily
47
+ for use by __str__ for debugging purposes.
48
+
49
+ Will remove "raw_event" properties, and any defined by the Data Class
50
+ `_sensitive_properties` list field.
51
+ This should be used in case where secrets, such as access keys, are
52
+ stored in the Data Class but should not be logged out.
53
+ """
54
+ properties = self._properties()
55
+ sensitive_properties = ["raw_event"]
56
+ if hasattr(self, "_sensitive_properties"):
57
+ sensitive_properties.extend(self._sensitive_properties) # pyright: ignore
58
+
59
+ result: Dict[str, Any] = {}
60
+ for property_key in properties:
61
+ if property_key in sensitive_properties:
62
+ result[property_key] = "[SENSITIVE]"
63
+ else:
64
+ try:
65
+ property_value = getattr(self, property_key)
66
+ result[property_key] = property_value
67
+
68
+ # Checks whether the class is a subclass of the parent class to perform a recursive operation.
69
+ if issubclass(property_value.__class__, DictWrapper):
70
+ result[property_key] = property_value._str_helper()
71
+ # Checks if the key is a list and if it is a subclass of the parent class
72
+ elif isinstance(property_value, list):
73
+ for seq, item in enumerate(property_value):
74
+ if issubclass(item.__class__, DictWrapper):
75
+ result[property_key][seq] = item._str_helper()
76
+ except Exception:
77
+ result[property_key] = "[Cannot be deserialized]"
78
+
79
+ return result
80
+
81
+ def _properties(self) -> List[str]:
82
+ return [p for p in dir(self.__class__) if isinstance(getattr(self.__class__, p), property)]
83
+
31
84
  def get(self, key: str, default: Optional[Any] = None) -> Optional[Any]:
32
85
  return self._data.get(key, default)
33
86
 
@@ -79,7 +132,7 @@ class BaseProxyEvent(DictWrapper):
79
132
  def json_body(self) -> Any:
80
133
  """Parses the submitted body as json"""
81
134
  if self._json_data is None:
82
- self._json_data = json.loads(self.decoded_body)
135
+ self._json_data = self._json_deserializer(self.decoded_body)
83
136
  return self._json_data
84
137
 
85
138
  @property
@@ -1,5 +1,4 @@
1
1
  import base64
2
- import json
3
2
  from typing import Any, Dict, Iterator, List, Optional
4
3
 
5
4
  from aws_lambda_powertools.utilities.data_classes.common import DictWrapper
@@ -55,7 +54,7 @@ class KafkaEventRecord(DictWrapper):
55
54
  def json_value(self) -> Any:
56
55
  """Decodes the text encoded data as JSON."""
57
56
  if self._json_data is None:
58
- self._json_data = json.loads(self.decoded_value.decode("utf-8"))
57
+ self._json_data = self._json_deserializer(self.decoded_value.decode("utf-8"))
59
58
  return self._json_data
60
59
 
61
60
  @property
@@ -117,7 +116,7 @@ class KafkaEvent(DictWrapper):
117
116
  """The Kafka records."""
118
117
  for chunk in self["records"].values():
119
118
  for record in chunk:
120
- yield KafkaEventRecord(record)
119
+ yield KafkaEventRecord(data=record, json_deserializer=self._json_deserializer)
121
120
 
122
121
  @property
123
122
  def record(self) -> KafkaEventRecord:
@@ -1,5 +1,4 @@
1
1
  import base64
2
- import json
3
2
  from typing import Iterator, Optional
4
3
 
5
4
  from aws_lambda_powertools.utilities.data_classes.common import DictWrapper
@@ -75,7 +74,7 @@ class KinesisFirehoseRecord(DictWrapper):
75
74
  def data_as_json(self) -> dict:
76
75
  """Decoded base64-encoded data loaded to json"""
77
76
  if self._json_data is None:
78
- self._json_data = json.loads(self.data_as_text)
77
+ self._json_data = self._json_deserializer(self.data_as_text)
79
78
  return self._json_data
80
79
 
81
80
 
@@ -110,4 +109,4 @@ class KinesisFirehoseEvent(DictWrapper):
110
109
  @property
111
110
  def records(self) -> Iterator[KinesisFirehoseRecord]:
112
111
  for record in self["records"]:
113
- yield KinesisFirehoseRecord(record)
112
+ yield KinesisFirehoseRecord(data=record, json_deserializer=self._json_deserializer)
@@ -1,4 +1,4 @@
1
- from typing import Dict, Iterator, Optional
1
+ from typing import Any, Dict, Iterator, Optional
2
2
 
3
3
  from aws_lambda_powertools.utilities.data_classes.common import DictWrapper
4
4
 
@@ -103,6 +103,35 @@ class SQSRecord(DictWrapper):
103
103
  """The message's contents (not URL-encoded)."""
104
104
  return self["body"]
105
105
 
106
+ @property
107
+ def json_body(self) -> Any:
108
+ """Deserializes JSON string available in 'body' property
109
+
110
+ Notes
111
+ -----
112
+
113
+ **Strict typing**
114
+
115
+ Caller controls the type as we can't use recursive generics here.
116
+
117
+ JSON Union types would force caller to have to cast a type. Instead,
118
+ we choose Any to ease ergonomics and other tools receiving this data.
119
+
120
+ Examples
121
+ --------
122
+
123
+ **Type deserialized data from JSON string**
124
+
125
+ ```python
126
+ data: dict = record.json_body # {"telemetry": [], ...}
127
+ # or
128
+ data: list = record.json_body # ["telemetry_values"]
129
+ ```
130
+ """
131
+ if self._json_data is None:
132
+ self._json_data = self._json_deserializer(self["body"])
133
+ return self._json_data
134
+
106
135
  @property
107
136
  def attributes(self) -> SQSRecordAttributes:
108
137
  """A map of the attributes requested in ReceiveMessage to their respective values."""
@@ -133,6 +162,18 @@ class SQSRecord(DictWrapper):
133
162
  """aws region eg: us-east-1"""
134
163
  return self["awsRegion"]
135
164
 
165
+ @property
166
+ def queue_url(self) -> str:
167
+ """The URL of the queue."""
168
+ arn_parts = self["eventSourceARN"].split(":")
169
+ region = arn_parts[3]
170
+ account_id = arn_parts[4]
171
+ queue_name = arn_parts[5]
172
+
173
+ queue_url = f"https://sqs.{region}.amazonaws.com/{account_id}/{queue_name}"
174
+
175
+ return queue_url
176
+
136
177
 
137
178
  class SQSEvent(DictWrapper):
138
179
  """SQS Event
@@ -145,4 +186,4 @@ class SQSEvent(DictWrapper):
145
186
  @property
146
187
  def records(self) -> Iterator[SQSRecord]:
147
188
  for record in self["Records"]:
148
- yield SQSRecord(record)
189
+ yield SQSRecord(data=record, json_deserializer=self._json_deserializer)
@@ -6,3 +6,8 @@ EVENTBRIDGE = "detail"
6
6
  CLOUDWATCH_EVENTS_SCHEDULED = EVENTBRIDGE
7
7
  KINESIS_DATA_STREAM = "Records[*].kinesis.powertools_json(powertools_base64(data))"
8
8
  CLOUDWATCH_LOGS = "awslogs.powertools_base64_gzip(data) | powertools_json(@).logEvents[*]"
9
+ S3_SNS_SQS = "Records[*].powertools_json(body).powertools_json(Message).Records[0]"
10
+ S3_SQS = "Records[*].powertools_json(body).Records[0]"
11
+ S3_SNS_KINESIS_FIREHOSE = "records[*].powertools_json(powertools_base64(data)).powertools_json(Message).Records[0]"
12
+ S3_KINESIS_FIREHOSE = "records[*].powertools_json(powertools_base64(data)).Records[0]"
13
+ S3_EVENTBRIDGE_SQS = "Records[*].powertools_json(body).detail"
@@ -50,6 +50,10 @@ from .s3 import (
50
50
  S3Model,
51
51
  S3RecordModel,
52
52
  )
53
+ from .s3_event_notification import (
54
+ S3SqsEventNotificationModel,
55
+ S3SqsEventNotificationRecordModel,
56
+ )
53
57
  from .s3_object_event import (
54
58
  S3ObjectConfiguration,
55
59
  S3ObjectContext,
@@ -130,6 +134,8 @@ __all__ = [
130
134
  "SqsRecordModel",
131
135
  "SqsMsgAttributeModel",
132
136
  "SqsAttributesModel",
137
+ "S3SqsEventNotificationModel",
138
+ "S3SqsEventNotificationRecordModel",
133
139
  "APIGatewayProxyEventModel",
134
140
  "APIGatewayEventRequestContext",
135
141
  "APIGatewayEventAuthorizer",
@@ -0,0 +1,14 @@
1
+ from typing import List
2
+
3
+ from pydantic import Json
4
+
5
+ from aws_lambda_powertools.utilities.parser.models.s3 import S3Model
6
+ from aws_lambda_powertools.utilities.parser.models.sqs import SqsModel, SqsRecordModel
7
+
8
+
9
+ class S3SqsEventNotificationRecordModel(SqsRecordModel):
10
+ body: Json[S3Model]
11
+
12
+
13
+ class S3SqsEventNotificationModel(SqsModel):
14
+ Records: List[S3SqsEventNotificationRecordModel]
@@ -1,5 +1,5 @@
1
1
  from datetime import datetime
2
- from typing import Dict, List, Optional, Type, Union
2
+ from typing import Dict, List, Optional, Sequence, Type, Union
3
3
 
4
4
  from pydantic import BaseModel
5
5
 
@@ -63,4 +63,4 @@ class SqsRecordModel(BaseModel):
63
63
 
64
64
 
65
65
  class SqsModel(BaseModel):
66
- Records: List[SqsRecordModel]
66
+ Records: Sequence[SqsRecordModel]