aws-lambda-powertools 3.28.0__tar.gz → 3.29.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 (310) hide show
  1. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/PKG-INFO +2 -2
  2. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/api_gateway.py +206 -10
  3. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/http_resolver.py +5 -69
  4. aws_lambda_powertools-3.29.0/aws_lambda_powertools/event_handler/middlewares/async_utils.py +224 -0
  5. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +5 -1
  6. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/params.py +3 -1
  7. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/version.py +1 -1
  8. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/base.py +2 -2
  9. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/persistence/redis.py +2 -2
  10. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/apigw.py +4 -4
  11. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/apigw_websocket.py +4 -4
  12. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py +4 -4
  13. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/base.py +5 -1
  14. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/bedrock_agent.py +7 -7
  15. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py +4 -4
  16. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py +4 -4
  17. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py +4 -4
  18. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/kafka.py +4 -4
  19. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py +4 -4
  20. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py +4 -4
  21. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py +4 -4
  22. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/sns.py +7 -7
  23. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/sqs.py +4 -4
  24. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/vpc_lattice.py +4 -4
  25. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/vpc_latticev2.py +4 -4
  26. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/functions.py +2 -2
  27. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/parser.py +5 -1
  28. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/pyproject.toml +4 -4
  29. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/setup.py +3 -3
  30. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/LICENSE +0 -0
  31. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/README.md +0 -0
  32. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/THIRD-PARTY-LICENSES +0 -0
  33. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/__init__.py +0 -0
  34. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/__init__.py +0 -0
  35. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/appsync.py +0 -0
  36. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/bedrock_agent.py +0 -0
  37. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/bedrock_agent_function.py +0 -0
  38. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/content_types.py +0 -0
  39. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/depends.py +0 -0
  40. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/__init__.py +0 -0
  41. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/_registry.py +0 -0
  42. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/appsync_events.py +0 -0
  43. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/base.py +0 -0
  44. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/exceptions.py +0 -0
  45. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/functions.py +0 -0
  46. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/router.py +0 -0
  47. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/events_appsync/types.py +0 -0
  48. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/exception_handling.py +0 -0
  49. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/exceptions.py +0 -0
  50. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/graphql_appsync/__init__.py +0 -0
  51. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/graphql_appsync/_registry.py +0 -0
  52. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/graphql_appsync/base.py +0 -0
  53. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/graphql_appsync/exceptions.py +0 -0
  54. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/graphql_appsync/router.py +0 -0
  55. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/lambda_function_url.py +0 -0
  56. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/middlewares/__init__.py +0 -0
  57. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/middlewares/base.py +0 -0
  58. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/middlewares/schema_validation.py +0 -0
  59. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/__init__.py +0 -0
  60. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/compat.py +0 -0
  61. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/config.py +0 -0
  62. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/constants.py +0 -0
  63. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/dependant.py +0 -0
  64. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/encoders.py +0 -0
  65. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/exceptions.py +0 -0
  66. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/merge.py +0 -0
  67. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/models.py +0 -0
  68. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/pydantic_loader.py +0 -0
  69. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/schema_generator.py +0 -0
  70. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/__init__.py +0 -0
  71. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py +0 -0
  72. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py +0 -0
  73. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/swagger-ui-bundle.min.js +0 -0
  74. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/swagger-ui.min.css +0 -0
  75. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/openapi/types.py +0 -0
  76. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/request.py +0 -0
  77. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/router.py +0 -0
  78. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/types.py +0 -0
  79. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/util.py +0 -0
  80. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/event_handler/vpc_lattice.py +0 -0
  81. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/exceptions/__init__.py +0 -0
  82. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/__init__.py +0 -0
  83. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/buffer/__init__.py +0 -0
  84. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/buffer/cache.py +0 -0
  85. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/buffer/config.py +0 -0
  86. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/buffer/functions.py +0 -0
  87. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/buffer/handler.py +0 -0
  88. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/constants.py +0 -0
  89. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/correlation_paths.py +0 -0
  90. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/exceptions.py +0 -0
  91. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/filters.py +0 -0
  92. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/formatter.py +0 -0
  93. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/formatters/__init__.py +0 -0
  94. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/formatters/datadog.py +0 -0
  95. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/lambda_context.py +0 -0
  96. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/logger.py +0 -0
  97. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/types.py +0 -0
  98. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/logging/utils.py +0 -0
  99. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/__init__.py +0 -0
  100. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/base.py +0 -0
  101. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/exceptions.py +0 -0
  102. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/functions.py +0 -0
  103. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/metric.py +0 -0
  104. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/metrics.py +0 -0
  105. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/__init__.py +0 -0
  106. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/base.py +0 -0
  107. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/__init__.py +0 -0
  108. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py +0 -0
  109. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/constants.py +0 -0
  110. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py +0 -0
  111. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/metric_properties.py +0 -0
  112. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/types.py +0 -0
  113. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/cold_start.py +0 -0
  114. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/datadog/__init__.py +0 -0
  115. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/datadog/datadog.py +0 -0
  116. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/datadog/metrics.py +0 -0
  117. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/provider/datadog/warnings.py +0 -0
  118. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/metrics/types.py +0 -0
  119. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/middleware_factory/__init__.py +0 -0
  120. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/middleware_factory/exceptions.py +0 -0
  121. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/middleware_factory/factory.py +0 -0
  122. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/package_logger.py +0 -0
  123. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/py.typed +0 -0
  124. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/__init__.py +0 -0
  125. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/cache_dict.py +0 -0
  126. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/constants.py +0 -0
  127. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/cookies.py +0 -0
  128. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/dynamodb_deserializer.py +0 -0
  129. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/functions.py +0 -0
  130. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/headers_serializer.py +0 -0
  131. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/json_encoder.py +0 -0
  132. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/lazy_import.py +0 -0
  133. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/types.py +0 -0
  134. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/shared/user_agent.py +0 -0
  135. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/tracing/__init__.py +0 -0
  136. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/tracing/base.py +0 -0
  137. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/tracing/extensions.py +0 -0
  138. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/tracing/tracer.py +0 -0
  139. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/__init__.py +0 -0
  140. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/batch/__init__.py +0 -0
  141. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/batch/base.py +0 -0
  142. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/batch/decorators.py +0 -0
  143. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/batch/exceptions.py +0 -0
  144. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py +0 -0
  145. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/batch/types.py +0 -0
  146. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/__init__.py +0 -0
  147. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/active_mq_event.py +0 -0
  148. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/alb_event.py +0 -0
  149. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py +0 -0
  150. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py +0 -0
  151. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_websocket_event.py +0 -0
  152. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/appsync/__init__.py +0 -0
  153. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/appsync/scalar_types_utils.py +0 -0
  154. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/appsync_authorizer_event.py +0 -0
  155. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py +0 -0
  156. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/appsync_resolver_events_event.py +0 -0
  157. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/aws_config_rule_event.py +0 -0
  158. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/bedrock_agent_event.py +0 -0
  159. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/bedrock_agent_function_event.py +0 -0
  160. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_alarm_event.py +0 -0
  161. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_custom_widget_event.py +0 -0
  162. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_logs_event.py +0 -0
  163. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/cloudformation_custom_resource_event.py +0 -0
  164. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/code_deploy_lifecycle_hook_event.py +0 -0
  165. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/code_pipeline_job_event.py +0 -0
  166. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/cognito_user_pool_event.py +0 -0
  167. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/common.py +0 -0
  168. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/connect_contact_flow_event.py +0 -0
  169. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/dynamo_db_stream_event.py +0 -0
  170. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py +0 -0
  171. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/event_source.py +0 -0
  172. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/iot_registry_event.py +0 -0
  173. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/kafka_event.py +0 -0
  174. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/kinesis_firehose_event.py +0 -0
  175. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/kinesis_stream_event.py +0 -0
  176. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/lambda_function_url_event.py +0 -0
  177. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/rabbit_mq_event.py +0 -0
  178. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/s3_batch_operation_event.py +0 -0
  179. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/s3_event.py +0 -0
  180. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/s3_object_event.py +0 -0
  181. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/secrets_manager_event.py +0 -0
  182. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/ses_event.py +0 -0
  183. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/shared_functions.py +0 -0
  184. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/sns_event.py +0 -0
  185. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/sqs_event.py +0 -0
  186. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/transfer_family_event.py +0 -0
  187. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +0 -0
  188. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/__init__.py +0 -0
  189. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/base.py +0 -0
  190. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/constants.py +0 -0
  191. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/exceptions.py +0 -0
  192. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/provider/__init__.py +0 -0
  193. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/provider/base.py +0 -0
  194. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/provider/kms/__init__.py +0 -0
  195. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/data_masking/provider/kms/aws_encryption_sdk.py +0 -0
  196. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/__init__.py +0 -0
  197. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/appconfig.py +0 -0
  198. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/base.py +0 -0
  199. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/comparators.py +0 -0
  200. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/constants.py +0 -0
  201. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/exceptions.py +0 -0
  202. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +0 -0
  203. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/schema.py +0 -0
  204. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/feature_flags/types.py +0 -0
  205. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/__init__.py +0 -0
  206. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/config.py +0 -0
  207. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/exceptions.py +0 -0
  208. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/hook.py +0 -0
  209. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/idempotency.py +0 -0
  210. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/persistence/__init__.py +0 -0
  211. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/persistence/base.py +0 -0
  212. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/persistence/cache.py +0 -0
  213. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/persistence/datarecord.py +0 -0
  214. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py +0 -0
  215. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/serialization/__init__.py +0 -0
  216. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/serialization/base.py +0 -0
  217. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/serialization/custom_dict.py +0 -0
  218. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/serialization/dataclass.py +0 -0
  219. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/serialization/functions.py +0 -0
  220. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/serialization/no_op.py +0 -0
  221. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/idempotency/serialization/pydantic.py +0 -0
  222. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/jmespath_utils/__init__.py +0 -0
  223. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/jmespath_utils/envelopes.py +0 -0
  224. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/__init__.py +0 -0
  225. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/consumer_records.py +0 -0
  226. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/deserializer/__init__.py +0 -0
  227. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/deserializer/avro.py +0 -0
  228. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/deserializer/base.py +0 -0
  229. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/deserializer/default.py +0 -0
  230. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/deserializer/deserializer.py +0 -0
  231. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/deserializer/json.py +0 -0
  232. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/deserializer/protobuf.py +0 -0
  233. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/exceptions.py +0 -0
  234. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/kafka_consumer.py +0 -0
  235. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/schema_config.py +0 -0
  236. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/serialization/__init__.py +0 -0
  237. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/serialization/base.py +0 -0
  238. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/serialization/custom_dict.py +0 -0
  239. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/serialization/dataclass.py +0 -0
  240. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/serialization/pydantic.py +0 -0
  241. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/serialization/serialization.py +0 -0
  242. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/kafka/serialization/types.py +0 -0
  243. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/metadata/__init__.py +0 -0
  244. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/metadata/exceptions.py +0 -0
  245. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/metadata/lambda_metadata.py +0 -0
  246. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/__init__.py +0 -0
  247. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/appconfig.py +0 -0
  248. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/base.py +0 -0
  249. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/constants.py +0 -0
  250. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/dynamodb.py +0 -0
  251. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/exceptions.py +0 -0
  252. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/secrets.py +0 -0
  253. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/ssm.py +0 -0
  254. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parameters/types.py +0 -0
  255. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/__init__.py +0 -0
  256. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/envelopes/__init__.py +0 -0
  257. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/exceptions.py +0 -0
  258. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/__init__.py +0 -0
  259. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/alb.py +0 -0
  260. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/apigw.py +0 -0
  261. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/apigw_websocket.py +0 -0
  262. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/apigwv2.py +0 -0
  263. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/appsync.py +0 -0
  264. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/appsync_events.py +0 -0
  265. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/bedrock_agent.py +0 -0
  266. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/cloudformation_custom_resource.py +0 -0
  267. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/cloudwatch.py +0 -0
  268. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/cognito.py +0 -0
  269. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/dynamodb.py +0 -0
  270. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/event_bridge.py +0 -0
  271. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py +0 -0
  272. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/kafka.py +0 -0
  273. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/kinesis.py +0 -0
  274. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py +0 -0
  275. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/kinesis_firehose_sqs.py +0 -0
  276. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/lambda_function_url.py +0 -0
  277. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/s3.py +0 -0
  278. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py +0 -0
  279. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/s3_event_notification.py +0 -0
  280. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/s3_object_event.py +0 -0
  281. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/ses.py +0 -0
  282. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/sns.py +0 -0
  283. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/sqs.py +0 -0
  284. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/transfer_family.py +0 -0
  285. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/vpc_lattice.py +0 -0
  286. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/models/vpc_latticev2.py +0 -0
  287. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/parser/types.py +0 -0
  288. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/serialization.py +0 -0
  289. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/__init__.py +0 -0
  290. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py +0 -0
  291. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/compat.py +0 -0
  292. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/constants.py +0 -0
  293. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/s3_object.py +0 -0
  294. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/transformations/__init__.py +0 -0
  295. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/transformations/base.py +0 -0
  296. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/transformations/csv.py +0 -0
  297. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/transformations/gzip.py +0 -0
  298. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/transformations/zip.py +0 -0
  299. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/streaming/types.py +0 -0
  300. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/typing/__init__.py +0 -0
  301. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/typing/lambda_client_context.py +0 -0
  302. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/typing/lambda_client_context_mobile_client.py +0 -0
  303. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/typing/lambda_cognito_identity.py +0 -0
  304. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/typing/lambda_context.py +0 -0
  305. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/validation/__init__.py +0 -0
  306. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/validation/base.py +0 -0
  307. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/validation/envelopes.py +0 -0
  308. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/validation/exceptions.py +0 -0
  309. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/utilities/validation/validator.py +0 -0
  310. {aws_lambda_powertools-3.28.0 → aws_lambda_powertools-3.29.0}/aws_lambda_powertools/warnings/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: aws_lambda_powertools
3
- Version: 3.28.0
3
+ Version: 3.29.0
4
4
  Summary: Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity.
5
5
  License: MIT
6
6
  Keywords: aws_lambda_powertools,aws,tracing,logging,lambda,powertools,feature_flags,idempotency,middleware
@@ -29,7 +29,7 @@ Provides-Extra: tracer
29
29
  Provides-Extra: validation
30
30
  Provides-Extra: valkey
31
31
  Requires-Dist: avro (>=1.12.0,<2.0.0) ; extra == "kafka-consumer-avro"
32
- Requires-Dist: aws-encryption-sdk (>=3.1.1,<5.0.0) ; extra == "all" or extra == "datamasking"
32
+ Requires-Dist: aws-encryption-sdk (>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4,<5.0.0) ; extra == "all" or extra == "datamasking"
33
33
  Requires-Dist: aws-xray-sdk (>=2.8.0,<3.0.0) ; extra == "tracer" or extra == "all"
34
34
  Requires-Dist: boto3 (>=1.34.32,<2.0.0) ; extra == "aws-sdk"
35
35
  Requires-Dist: datadog-lambda (>=8.114.0,<9.0.0) ; extra == "datadog"
@@ -613,6 +613,63 @@ class Route:
613
613
 
614
614
  self._middleware_stack_built = True
615
615
 
616
+ async def call_async(
617
+ self,
618
+ router_middlewares: list[Callable],
619
+ app: ApiGatewayResolver,
620
+ route_arguments: dict[str, str],
621
+ ) -> dict | tuple | Response:
622
+ from aws_lambda_powertools.event_handler.middlewares.async_utils import (
623
+ AsyncMiddlewareFrame,
624
+ _registered_api_adapter_async,
625
+ )
626
+
627
+ all_middlewares: list[Callable[..., Any]] = []
628
+
629
+ route_validation_enabled = (
630
+ self.enable_validation if self.enable_validation is not None else app._enable_validation
631
+ )
632
+
633
+ if route_validation_enabled and not hasattr(app, "_request_validation_middleware"):
634
+ from aws_lambda_powertools.event_handler.middlewares.openapi_validation import (
635
+ OpenAPIRequestValidationMiddleware,
636
+ OpenAPIResponseValidationMiddleware,
637
+ )
638
+
639
+ app._request_validation_middleware = OpenAPIRequestValidationMiddleware()
640
+ app._response_validation_middleware = OpenAPIResponseValidationMiddleware(
641
+ validation_serializer=app._serializer,
642
+ has_response_validation_error=app._has_response_validation_error,
643
+ )
644
+
645
+ if route_validation_enabled and hasattr(app, "_request_validation_middleware"):
646
+ all_middlewares.append(app._request_validation_middleware)
647
+
648
+ all_middlewares.extend(router_middlewares + self.middlewares)
649
+
650
+ if route_validation_enabled and hasattr(app, "_response_validation_middleware"):
651
+ all_middlewares.append(app._response_validation_middleware)
652
+
653
+ all_middlewares.append(_registered_api_adapter_async)
654
+
655
+ logger.debug(f"Building async middleware stack: {all_middlewares}")
656
+
657
+ if app._debug:
658
+ print(f"\nProcessing Route (async):::{self.func.__name__} ({app.context['_path']})")
659
+ print("\nAsync Middleware Stack:")
660
+ print("=================")
661
+ print("\n".join(getattr(item, "__name__", "Unknown") for item in all_middlewares))
662
+ print("=================")
663
+
664
+ app.append_context(_route_args=route_arguments)
665
+
666
+ # Build async chain from inside-out (not cached, avoids state conflicts with sync cache)
667
+ next_handler: Callable = self.func
668
+ for handler in reversed(all_middlewares):
669
+ next_handler = AsyncMiddlewareFrame(current_middleware=handler, next_middleware=next_handler)
670
+
671
+ return await next_handler(app)
672
+
616
673
  @property
617
674
  def dependant(self) -> Dependant:
618
675
  if self._dependant is None:
@@ -2509,6 +2566,154 @@ class ApiGatewayResolver(BaseRouter):
2509
2566
 
2510
2567
  return response
2511
2568
 
2569
+ async def resolve_async(self, event: Mapping[str, Any], context: LambdaContext) -> dict[str, Any]:
2570
+ """Async version of resolve() for native async handler support.
2571
+
2572
+ Use this method when your route handlers use async/await. The resolution
2573
+ pipeline supports both sync and async handlers transparently.
2574
+
2575
+ Parameters
2576
+ ----------
2577
+ event: dict[str, Any]
2578
+ Event
2579
+ context: LambdaContext
2580
+ Lambda context
2581
+ Returns
2582
+ -------
2583
+ dict
2584
+ Returns the dict response
2585
+
2586
+ Example
2587
+ -------
2588
+
2589
+ ```python
2590
+ import asyncio
2591
+ from aws_lambda_powertools.event_handler import APIGatewayHttpResolver
2592
+
2593
+ app = APIGatewayHttpResolver()
2594
+
2595
+ @app.get("/async")
2596
+ async def async_handler():
2597
+ return {"message": "async works"}
2598
+
2599
+ def lambda_handler(event, context):
2600
+ return asyncio.run(app.resolve_async(event, context))
2601
+ ```
2602
+ """
2603
+ if isinstance(event, BaseProxyEvent):
2604
+ warnings.warn(
2605
+ "You don't need to serialize event to Event Source Data Class when using Event Handler; "
2606
+ "see issue #1152",
2607
+ stacklevel=2,
2608
+ )
2609
+ event = event.raw_event
2610
+
2611
+ if self._debug:
2612
+ print(self._serializer(cast(dict, event)))
2613
+
2614
+ BaseRouter.current_event = self._to_proxy_event(cast(dict, event))
2615
+ BaseRouter.lambda_context = context
2616
+
2617
+ response = (await self._resolve_async()).build(self.current_event, self._cors)
2618
+
2619
+ if self._debug:
2620
+ print("\nProcessed Middlewares:")
2621
+ print("======================")
2622
+ print("\n".join(self.processed_stack_frames))
2623
+ print("======================")
2624
+
2625
+ self.clear_context()
2626
+
2627
+ return response
2628
+
2629
+ async def _resolve_async(self) -> ResponseBuilder:
2630
+ method = self.current_event.http_method.upper()
2631
+ path = self._remove_prefix(self.current_event.path)
2632
+
2633
+ registered_routes = self._static_routes + self._dynamic_routes
2634
+
2635
+ for route in registered_routes:
2636
+ if method != route.method:
2637
+ continue
2638
+ match_results: Match | None = route.rule.match(path)
2639
+ if match_results:
2640
+ logger.debug("Found a registered route. Calling async function")
2641
+ self.append_context(_route=route, _path=path)
2642
+
2643
+ route_keys = self._convert_matches_into_route_keys(match_results)
2644
+ return await self._call_route_async(route, route_keys)
2645
+
2646
+ return await self._handle_not_found_async(method=method, path=path)
2647
+
2648
+ async def _call_route_async(self, route: Route, route_arguments: dict[str, str]) -> ResponseBuilder:
2649
+ try:
2650
+ self._reset_processed_stack()
2651
+
2652
+ response = await route.call_async(
2653
+ router_middlewares=self._router_middlewares,
2654
+ app=self,
2655
+ route_arguments=route_arguments,
2656
+ )
2657
+
2658
+ return self._response_builder_class(
2659
+ response=self._to_response(response), # type: ignore[arg-type]
2660
+ serializer=self._serializer,
2661
+ route=route,
2662
+ )
2663
+ except Exception as exc:
2664
+ response_builder = self._call_exception_handler(exc, route)
2665
+ if response_builder:
2666
+ return response_builder
2667
+
2668
+ logger.exception(exc)
2669
+ if self._debug:
2670
+ return self._response_builder_class(
2671
+ response=Response(
2672
+ status_code=500,
2673
+ content_type=content_types.TEXT_PLAIN,
2674
+ body="".join(traceback.format_exc()),
2675
+ ),
2676
+ serializer=self._serializer,
2677
+ route=route,
2678
+ )
2679
+
2680
+ raise
2681
+
2682
+ async def _handle_not_found_async(self, method: str, path: str) -> ResponseBuilder:
2683
+ logger.debug(f"No match found for path {path} and method {method}")
2684
+
2685
+ def not_found_handler():
2686
+ _headers: dict[str, Any] = {}
2687
+
2688
+ if self._cors and method == "OPTIONS":
2689
+ logger.debug("Pre-flight request detected. Returning CORS with empty response")
2690
+ _headers["Access-Control-Allow-Methods"] = CORSConfig.build_allow_methods(self._cors_methods)
2691
+ return Response(status_code=204, content_type=None, headers=_headers, body="")
2692
+
2693
+ custom_not_found_handler = self.exception_handler_manager.lookup_exception_handler(NotFoundError)
2694
+ if custom_not_found_handler:
2695
+ return custom_not_found_handler(NotFoundError())
2696
+
2697
+ return Response(
2698
+ status_code=HTTPStatus.NOT_FOUND.value,
2699
+ content_type=content_types.APPLICATION_JSON,
2700
+ headers=_headers,
2701
+ body={"statusCode": HTTPStatus.NOT_FOUND.value, "message": "Not found"},
2702
+ )
2703
+
2704
+ route = Route(
2705
+ rule=self._compile_regex(r".*"),
2706
+ method=method,
2707
+ path=path,
2708
+ func=not_found_handler,
2709
+ cors=self._cors_enabled,
2710
+ compress=False,
2711
+ )
2712
+
2713
+ self.append_context(_route=route, _path=path)
2714
+
2715
+ return await self._call_route_async(route=route, route_arguments={})
2716
+
2512
2717
  def __call__(self, event, context) -> Any:
2513
2718
  return self.resolve(event, context)
2514
2719
 
@@ -3138,22 +3343,13 @@ class ALBResolver(ApiGatewayResolver):
3138
3343
  # ALB doesn't have a stage variable, so we just return an empty string
3139
3344
  return ""
3140
3345
 
3141
- # BedrockResponse is not used here but adding the same signature to keep strong typing
3142
3346
  @override
3143
3347
  def _to_response(self, result: dict | tuple | Response | BedrockResponse) -> Response | BedrockResponse:
3144
3348
  """Convert the route's result to a Response
3145
3349
 
3146
3350
  ALB requires a non-null body otherwise it converts as HTTP 5xx
3147
-
3148
- 3 main result types are supported:
3149
-
3150
- - Dict[str, Any]: Rest api response with just the Dict to json stringify and content-type is set to
3151
- application/json
3152
- - Tuple[dict, int]: Same dict handling as above but with the option of including a status code
3153
- - Response: returned as is, and allows for more flexibility
3154
3351
  """
3155
-
3156
- # NOTE: Minor override for early return on Response with null body for ALB
3352
+ # ALB doesn't support null body - convert before building the final response
3157
3353
  if isinstance(result, Response) and result.body is None:
3158
3354
  logger.debug("ALB doesn't allow None responses; converting to empty string")
3159
3355
  result.body = ""
@@ -1,9 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- import asyncio
4
3
  import base64
5
4
  import inspect
6
- import threading
7
5
  import warnings
8
6
  from typing import TYPE_CHECKING, Any, Callable
9
7
  from urllib.parse import parse_qs
@@ -15,6 +13,7 @@ from aws_lambda_powertools.event_handler.api_gateway import (
15
13
  Response,
16
14
  Route,
17
15
  )
16
+ from aws_lambda_powertools.event_handler.middlewares.async_utils import wrap_middleware_async
18
17
  from aws_lambda_powertools.shared.headers_serializer import BaseHeadersSerializer
19
18
  from aws_lambda_powertools.utilities.data_classes.common import BaseProxyEvent
20
19
 
@@ -240,7 +239,7 @@ class HttpResolverLocal(ApiGatewayResolver):
240
239
  """Return the base path for HTTP resolver (no stage prefix)."""
241
240
  return ""
242
241
 
243
- async def _resolve_async(self) -> dict:
242
+ async def _resolve_async(self) -> dict: # type: ignore[override]
244
243
  """Async version of resolve that supports async handlers."""
245
244
  method = self.current_event.http_method.upper()
246
245
  path = self._remove_prefix(self.current_event.path)
@@ -259,7 +258,7 @@ class HttpResolverLocal(ApiGatewayResolver):
259
258
  # Handle not found
260
259
  return await self._handle_not_found_async()
261
260
 
262
- async def _call_route_async(self, route: Route, route_arguments: dict[str, str]) -> dict:
261
+ async def _call_route_async(self, route: Route, route_arguments: dict[str, str]) -> dict: # type: ignore[override]
263
262
  """Call route handler, supporting both sync and async handlers."""
264
263
  from aws_lambda_powertools.event_handler.api_gateway import ResponseBuilder
265
264
 
@@ -320,74 +319,11 @@ class HttpResolverLocal(ApiGatewayResolver):
320
319
  next_handler = final_handler
321
320
 
322
321
  for middleware in reversed(all_middlewares):
323
- next_handler = self._wrap_middleware_async(middleware, next_handler)
322
+ next_handler = wrap_middleware_async(middleware, next_handler)
324
323
 
325
324
  return await next_handler(self)
326
325
 
327
- def _wrap_middleware_async(self, middleware: Callable, next_handler: Callable) -> Callable:
328
- """Wrap a middleware to work in async context.
329
-
330
- For sync middlewares, we split execution into pre/post phases around the
331
- call to next(). The sync middleware runs its pre-processing (e.g. request
332
- validation), then we intercept the next() call, await the async handler,
333
- and resume the middleware with the real response so post-processing
334
- (e.g. response validation) sees the actual data.
335
- """
336
-
337
- async def wrapped(app):
338
- if inspect.iscoroutinefunction(middleware):
339
- return await middleware(app, next_handler)
340
-
341
- # We use an Event to coordinate: the sync middleware runs in a thread,
342
- # calls sync_next which signals us to resolve the async handler,
343
- # then waits for the real response.
344
- middleware_called_next = asyncio.Event()
345
- next_app_holder: list = []
346
- real_response_holder: list = []
347
- middleware_result_holder: list = []
348
- middleware_error_holder: list = []
349
-
350
- def sync_next(app):
351
- next_app_holder.append(app)
352
- middleware_called_next.set()
353
- # Block this thread until the real response is available
354
- event = threading.Event()
355
- next_app_holder.append(event)
356
- event.wait()
357
- return real_response_holder[0]
358
-
359
- def run_middleware():
360
- try:
361
- result = middleware(app, sync_next)
362
- middleware_result_holder.append(result)
363
- except Exception as e:
364
- middleware_error_holder.append(e)
365
-
366
- thread = threading.Thread(target=run_middleware, daemon=True)
367
- thread.start()
368
-
369
- # Wait for the middleware to call next()
370
- await middleware_called_next.wait()
371
-
372
- # Now resolve the async next_handler
373
- real_response = await next_handler(next_app_holder[0])
374
- real_response_holder.append(real_response)
375
-
376
- # Signal the thread that the response is ready
377
- threading_event = next_app_holder[1]
378
- threading_event.set()
379
-
380
- # Wait for the middleware thread to finish
381
- thread.join()
382
-
383
- if middleware_error_holder:
384
- raise middleware_error_holder[0]
385
-
386
- return middleware_result_holder[0]
387
-
388
- return wrapped
389
-
390
- async def _handle_not_found_async(self) -> dict:
326
+ async def _handle_not_found_async(self, method: str = "", path: str = "") -> dict: # type: ignore[override]
391
327
  """Handle 404 responses, using custom not_found handler if registered."""
392
328
  from http import HTTPStatus
393
329
 
@@ -0,0 +1,224 @@
1
+ """Async middleware utilities for bridging sync and async middleware execution."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import inspect
7
+ import logging
8
+ import threading
9
+ from typing import TYPE_CHECKING, Any
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Callable
15
+
16
+ from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, BedrockResponse, Response
17
+
18
+
19
+ def wrap_middleware_async(middleware: Callable, next_handler: Callable) -> Callable:
20
+ """Wrap a middleware to work in an async context.
21
+
22
+ For async middlewares, delegates directly with ``await``.
23
+
24
+ For sync middlewares, runs the middleware in a background thread and uses
25
+ ``asyncio.Event`` / ``threading.Event`` to coordinate the ``next()`` call
26
+ so the async handler can be awaited on the main event-loop while the sync
27
+ middleware blocks its own thread waiting for the result.
28
+
29
+ Parameters
30
+ ----------
31
+ middleware : Callable
32
+ A sync or async middleware ``(app, next_middleware) -> Response``.
33
+ next_handler : Callable
34
+ The next (async) handler in the chain.
35
+
36
+ Returns
37
+ -------
38
+ Callable
39
+ An async callable ``(app) -> Response`` that executes *middleware*
40
+ followed by *next_handler*.
41
+ """
42
+
43
+ async def wrapped(app: ApiGatewayResolver) -> Response:
44
+ if inspect.iscoroutinefunction(middleware):
45
+ return await middleware(app, next_handler)
46
+
47
+ return await _run_sync_middleware_in_thread(middleware, next_handler, app)
48
+
49
+ return wrapped
50
+
51
+
52
+ async def _run_sync_middleware_in_thread(
53
+ middleware: Callable,
54
+ next_handler: Callable,
55
+ app: Any,
56
+ ) -> Any:
57
+ """Execute a **sync** middleware inside a daemon thread.
58
+
59
+ The sync middleware calls ``sync_next(app)`` which:
60
+
61
+ 1. Signals the async side that the middleware is ready for the next handler.
62
+ 2. Blocks the thread until the async handler has produced a response.
63
+ 3. Returns the response so the middleware can do post-processing.
64
+
65
+ Meanwhile the async side awaits *next_handler*, feeds the response back,
66
+ and waits for the thread to finish.
67
+ """
68
+ middleware_called_next = asyncio.Event()
69
+ next_app_holder: list = []
70
+ real_response_holder: list = []
71
+ middleware_result_holder: list = []
72
+ middleware_error_holder: list = []
73
+
74
+ def sync_next(app: Any) -> Any:
75
+ next_app_holder.append(app)
76
+ middleware_called_next.set()
77
+ # Block this thread until the async handler resolves
78
+ event = threading.Event()
79
+ next_app_holder.append(event)
80
+ event.wait()
81
+ return real_response_holder[0]
82
+
83
+ def run_middleware() -> None:
84
+ try:
85
+ result = middleware(app, sync_next)
86
+ middleware_result_holder.append(result)
87
+ except Exception as e:
88
+ middleware_error_holder.append(e)
89
+ finally:
90
+ middleware_called_next.set()
91
+
92
+ thread = threading.Thread(target=run_middleware, daemon=True)
93
+ thread.start()
94
+
95
+ # Wait for the middleware to call next() or raise
96
+ await middleware_called_next.wait()
97
+
98
+ # If middleware raised before calling next, propagate immediately
99
+ if not next_app_holder:
100
+ thread.join()
101
+ raise middleware_error_holder[0]
102
+
103
+ # Resolve the async next_handler on the event-loop
104
+ real_response = await next_handler(next_app_holder[0])
105
+ real_response_holder.append(real_response)
106
+
107
+ # Unblock the middleware thread
108
+ threading_event = next_app_holder[1]
109
+ threading_event.set()
110
+
111
+ # Wait for the middleware thread to complete post-processing
112
+ thread.join()
113
+
114
+ if middleware_error_holder:
115
+ raise middleware_error_holder[0]
116
+
117
+ return middleware_result_holder[0]
118
+
119
+
120
+ class AsyncMiddlewareFrame:
121
+ """Async version of MiddlewareFrame for the async middleware chain.
122
+
123
+ Each instance wraps a middleware (sync or async) and the next handler in the stack.
124
+ When called, it auto-detects whether the current middleware is sync or async:
125
+
126
+ - **Async middleware**: awaited directly with ``(app, next_middleware)``
127
+ - **Sync middleware**: executed in a background thread so the event loop is never blocked
128
+
129
+ Parameters
130
+ ----------
131
+ current_middleware : Callable
132
+ The current middleware function to be called as a request is processed.
133
+ next_middleware : Callable
134
+ The next middleware in the middleware stack.
135
+ """
136
+
137
+ def __init__(
138
+ self,
139
+ current_middleware: Callable[..., Any],
140
+ next_middleware: Callable[..., Any],
141
+ ) -> None:
142
+ self.current_middleware: Callable[..., Any] = current_middleware
143
+ self.next_middleware: Callable[..., Any] = next_middleware
144
+ self._next_middleware_name = next_middleware.__name__
145
+
146
+ @property
147
+ def __name__(self) -> str: # noqa: A003
148
+ return self.current_middleware.__name__
149
+
150
+ def __str__(self) -> str:
151
+ middleware_name = self.__name__
152
+ return f"[{middleware_name}] next call chain is {middleware_name} -> {self._next_middleware_name}"
153
+
154
+ async def __call__(self, app: ApiGatewayResolver) -> dict | tuple | Response:
155
+ logger.debug("AsyncMiddlewareFrame: %s", self)
156
+ app._push_processed_stack_frame(str(self))
157
+
158
+ if inspect.iscoroutinefunction(self.current_middleware):
159
+ return await self.current_middleware(app, self.next_middleware)
160
+
161
+ loop = asyncio.get_running_loop()
162
+
163
+ def sync_next(app: ApiGatewayResolver) -> Any:
164
+ future = asyncio.run_coroutine_threadsafe(self.next_middleware(app), loop)
165
+ return future.result()
166
+
167
+ return await asyncio.to_thread(self.current_middleware, app, sync_next)
168
+
169
+
170
+ async def _registered_api_adapter_async(
171
+ app: ApiGatewayResolver,
172
+ next_middleware: Callable[..., Any],
173
+ ) -> dict | tuple | Response | BedrockResponse:
174
+ """
175
+ Async version of _registered_api_adapter.
176
+
177
+ Detects if the route handler is a coroutine and awaits it.
178
+ _to_response() stays sync (CPU-bound — no async benefit).
179
+
180
+ IMPORTANT: This is an internal building block only.
181
+ Nothing calls it in the resolve chain yet. It will be used
182
+ by resolve_async() (see issue #8137).
183
+
184
+ Parameters
185
+ ----------
186
+ app: ApiGatewayResolver
187
+ The API Gateway resolver
188
+ next_middleware: Callable[..., Any]
189
+ The function to handle the API
190
+
191
+ Returns
192
+ -------
193
+ Response
194
+ The API Response Object
195
+ """
196
+ route_args: dict = app.context.get("_route_args", {})
197
+ logger.debug(f"Calling API Route Handler: {route_args}")
198
+
199
+ route = app.context.get("_route")
200
+ if route is not None:
201
+ if not route.request_param_name_checked:
202
+ from aws_lambda_powertools.event_handler.api_gateway import _find_request_param_name
203
+
204
+ route.request_param_name = _find_request_param_name(next_middleware)
205
+ route.request_param_name_checked = True
206
+ if route.request_param_name:
207
+ route_args = {**route_args, route.request_param_name: app.request}
208
+
209
+ if route.has_dependencies:
210
+ from aws_lambda_powertools.event_handler.depends import build_dependency_tree, solve_dependencies
211
+
212
+ dep_values = solve_dependencies(
213
+ dependant=build_dependency_tree(route.func),
214
+ request=app.request,
215
+ dependency_overrides=app.dependency_overrides or None,
216
+ )
217
+ route_args.update(dep_values)
218
+
219
+ # Call handler — detect if result is a coroutine and await it
220
+ result = next_middleware(**route_args)
221
+ if inspect.iscoroutine(result):
222
+ result = await result
223
+
224
+ return app._to_response(result)
@@ -296,9 +296,13 @@ class OpenAPIResponseValidationMiddleware(BaseMiddlewareHandler):
296
296
  # JSON serialize the body without validation
297
297
  response.body = jsonable_encoder(response.body, custom_serializer=self._validation_serializer)
298
298
  else:
299
+ # ALB resolver converts None body to "" to prevent ALB 5xx errors,
300
+ # but the validation should still see it as None.
301
+ response_content = None if response.body == "" and field.type_ in (None, type(None)) else response.body
302
+
299
303
  response.body = self._serialize_response_with_validation(
300
304
  field=field,
301
- response_content=response.body,
305
+ response_content=response_content,
302
306
  has_route_custom_response_validation=route.custom_response_validation_http_code is not None,
303
307
  )
304
308
 
@@ -901,7 +901,7 @@ def analyze_param(
901
901
  if is_response_param:
902
902
  field_info.default = Required
903
903
 
904
- field = _create_model_field(field_info, type_annotation, param_name, is_path_param)
904
+ field = _create_model_field(field_info, type_annotation, param_name, is_path_param, is_response_param)
905
905
  return field
906
906
 
907
907
 
@@ -1138,6 +1138,7 @@ def _create_model_field(
1138
1138
  type_annotation: Any,
1139
1139
  param_name: str,
1140
1140
  is_path_param: bool,
1141
+ is_response_param: bool = False,
1141
1142
  ) -> ModelField | None:
1142
1143
  """
1143
1144
  Create a new ModelField from a FieldInfo and type annotation.
@@ -1164,4 +1165,5 @@ def _create_model_field(
1164
1165
  alias=field_info.alias,
1165
1166
  required=field_info.default in (Required, Undefined),
1166
1167
  field_info=field_info,
1168
+ mode="serialization" if is_response_param else "validation",
1167
1169
  )
@@ -1,3 +1,3 @@
1
1
  """Exposes version constant to avoid circular dependencies."""
2
2
 
3
- VERSION = "3.28.0"
3
+ VERSION = "3.29.0"
@@ -167,7 +167,7 @@ class IdempotencyHandler:
167
167
  # We give preference to ReturnValuesOnConditionCheckFailure because it is a faster and more cost-effective
168
168
  # way of retrieving the existing record after a failed conditional write operation.
169
169
  record = exc.old_data_record or self._get_idempotency_record()
170
- if is_replay and record is not None and record.status == "INPROGRESS":
170
+ if is_replay and record is not None and record.status == STATUS_CONSTANTS["INPROGRESS"]:
171
171
  return self._get_function_response()
172
172
  # If a record is found, handle it for status
173
173
  if record:
@@ -296,7 +296,7 @@ class IdempotencyHandler:
296
296
 
297
297
  else:
298
298
  try:
299
- serialized_response: dict = self.output_serializer.to_dict(response) if response else None
299
+ serialized_response: dict = self.output_serializer.to_dict(response) if response is not None else None
300
300
  self.persistence_store.save_success(data=self.data, result=serialized_response)
301
301
  except Exception as save_exception:
302
302
  raise IdempotencyPersistenceLayerError(
@@ -332,8 +332,8 @@ class RedisCachePersistenceLayer(BasePersistenceLayer):
332
332
  idempotency_key=idempotency_key,
333
333
  status=item[self.status_attr],
334
334
  in_progress_expiry_timestamp=in_progress_expiry_timestamp,
335
- response_data=str(item.get(self.data_attr)),
336
- payload_hash=str(item.get(self.validation_key_attr)),
335
+ response_data=item.get(self.data_attr, ""),
336
+ payload_hash=item.get(self.validation_key_attr, ""),
337
337
  expiry_timestamp=item.get("expiration"),
338
338
  )
339
339