aws-lambda-powertools 2.38.1__tar.gz → 2.39.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 (242) hide show
  1. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/PKG-INFO +4 -2
  2. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/README.md +1 -0
  3. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/api_gateway.py +141 -46
  4. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/encoders.py +76 -69
  5. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/exceptions.py +12 -0
  6. aws_lambda_powertools-2.39.0/aws_lambda_powertools/event_handler/util.py +100 -0
  7. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/version.py +1 -1
  8. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/__init__.py +2 -0
  9. aws_lambda_powertools-2.39.0/aws_lambda_powertools/utilities/data_classes/cloudformation_custom_resource_event.py +45 -0
  10. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/cognito_user_pool_event.py +260 -1
  11. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/idempotency.py +21 -2
  12. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/__init__.py +5 -1
  13. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/cloudformation_custom_resource.py +2 -0
  14. aws_lambda_powertools-2.39.0/aws_lambda_powertools/warnings/__init__.py +23 -0
  15. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/pyproject.toml +23 -18
  16. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/setup.py +6 -5
  17. aws_lambda_powertools-2.38.1/aws_lambda_powertools/event_handler/util.py +0 -13
  18. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/LICENSE +0 -0
  19. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/THIRD-PARTY-LICENSES +0 -0
  20. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/__init__.py +0 -0
  21. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/__init__.py +0 -0
  22. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/appsync.py +0 -0
  23. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/bedrock_agent.py +0 -0
  24. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/content_types.py +0 -0
  25. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/exceptions.py +0 -0
  26. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/lambda_function_url.py +0 -0
  27. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/middlewares/__init__.py +0 -0
  28. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/middlewares/base.py +0 -0
  29. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +0 -0
  30. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/middlewares/schema_validation.py +0 -0
  31. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/__init__.py +0 -0
  32. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/compat.py +0 -0
  33. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/constants.py +0 -0
  34. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/dependant.py +0 -0
  35. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/models.py +0 -0
  36. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/params.py +0 -0
  37. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/pydantic_loader.py +0 -0
  38. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/__init__.py +0 -0
  39. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py +0 -0
  40. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py +0 -0
  41. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/swagger-ui-bundle.min.js +0 -0
  42. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/swagger-ui.min.css +0 -0
  43. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/openapi/types.py +0 -0
  44. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/router.py +0 -0
  45. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/types.py +0 -0
  46. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/event_handler/vpc_lattice.py +0 -0
  47. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/exceptions/__init__.py +0 -0
  48. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/__init__.py +0 -0
  49. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/constants.py +0 -0
  50. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/correlation_paths.py +0 -0
  51. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/exceptions.py +0 -0
  52. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/filters.py +0 -0
  53. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/formatter.py +0 -0
  54. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/formatters/__init__.py +0 -0
  55. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/formatters/datadog.py +0 -0
  56. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/lambda_context.py +0 -0
  57. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/logger.py +0 -0
  58. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/types.py +0 -0
  59. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/logging/utils.py +0 -0
  60. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/__init__.py +0 -0
  61. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/base.py +0 -0
  62. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/exceptions.py +0 -0
  63. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/functions.py +0 -0
  64. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/metric.py +0 -0
  65. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/metrics.py +0 -0
  66. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/__init__.py +0 -0
  67. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/base.py +0 -0
  68. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/__init__.py +0 -0
  69. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py +0 -0
  70. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/constants.py +0 -0
  71. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py +0 -0
  72. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/metric_properties.py +0 -0
  73. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/types.py +0 -0
  74. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/cold_start.py +0 -0
  75. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/datadog/__init__.py +0 -0
  76. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/datadog/datadog.py +0 -0
  77. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/datadog/metrics.py +0 -0
  78. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/provider/datadog/warnings.py +0 -0
  79. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/metrics/types.py +0 -0
  80. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/middleware_factory/__init__.py +0 -0
  81. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/middleware_factory/exceptions.py +0 -0
  82. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/middleware_factory/factory.py +0 -0
  83. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/package_logger.py +0 -0
  84. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/py.typed +0 -0
  85. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/__init__.py +0 -0
  86. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/cache_dict.py +0 -0
  87. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/constants.py +0 -0
  88. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/cookies.py +0 -0
  89. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/functions.py +0 -0
  90. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/headers_serializer.py +0 -0
  91. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/json_encoder.py +0 -0
  92. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/lazy_import.py +0 -0
  93. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/types.py +0 -0
  94. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/shared/user_agent.py +0 -0
  95. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/tracing/__init__.py +0 -0
  96. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/tracing/base.py +0 -0
  97. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/tracing/extensions.py +0 -0
  98. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/tracing/tracer.py +0 -0
  99. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/__init__.py +0 -0
  100. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/batch/__init__.py +0 -0
  101. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/batch/base.py +0 -0
  102. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/batch/decorators.py +0 -0
  103. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/batch/exceptions.py +0 -0
  104. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py +0 -0
  105. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/batch/types.py +0 -0
  106. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/active_mq_event.py +0 -0
  107. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/alb_event.py +0 -0
  108. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py +0 -0
  109. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py +0 -0
  110. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/appsync/__init__.py +0 -0
  111. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/appsync/scalar_types_utils.py +0 -0
  112. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/appsync_authorizer_event.py +0 -0
  113. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py +0 -0
  114. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/aws_config_rule_event.py +0 -0
  115. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/bedrock_agent_event.py +0 -0
  116. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_alarm_event.py +0 -0
  117. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_custom_widget_event.py +0 -0
  118. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_logs_event.py +0 -0
  119. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/code_pipeline_job_event.py +0 -0
  120. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/common.py +0 -0
  121. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/connect_contact_flow_event.py +0 -0
  122. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/dynamo_db_stream_event.py +0 -0
  123. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py +0 -0
  124. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/event_source.py +0 -0
  125. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/kafka_event.py +0 -0
  126. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/kinesis_firehose_event.py +0 -0
  127. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/kinesis_stream_event.py +0 -0
  128. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/lambda_function_url_event.py +0 -0
  129. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/rabbit_mq_event.py +0 -0
  130. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/s3_batch_operation_event.py +0 -0
  131. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/s3_event.py +0 -0
  132. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/s3_object_event.py +0 -0
  133. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/secrets_manager_event.py +0 -0
  134. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/ses_event.py +0 -0
  135. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/shared_functions.py +0 -0
  136. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/sns_event.py +0 -0
  137. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/sqs_event.py +0 -0
  138. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +0 -0
  139. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/__init__.py +0 -0
  140. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/base.py +0 -0
  141. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/constants.py +0 -0
  142. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/exceptions.py +0 -0
  143. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/provider/__init__.py +0 -0
  144. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/provider/base.py +0 -0
  145. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/provider/kms/__init__.py +0 -0
  146. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/data_masking/provider/kms/aws_encryption_sdk.py +0 -0
  147. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/feature_flags/__init__.py +0 -0
  148. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/feature_flags/appconfig.py +0 -0
  149. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/feature_flags/base.py +0 -0
  150. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/feature_flags/comparators.py +0 -0
  151. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/feature_flags/exceptions.py +0 -0
  152. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +0 -0
  153. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/feature_flags/schema.py +0 -0
  154. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/__init__.py +0 -0
  155. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/base.py +0 -0
  156. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/config.py +0 -0
  157. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/exceptions.py +0 -0
  158. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/hook.py +0 -0
  159. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/persistence/__init__.py +0 -0
  160. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/persistence/base.py +0 -0
  161. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/persistence/datarecord.py +0 -0
  162. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py +0 -0
  163. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/persistence/redis.py +0 -0
  164. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/serialization/__init__.py +0 -0
  165. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/serialization/base.py +0 -0
  166. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/serialization/custom_dict.py +0 -0
  167. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/serialization/dataclass.py +0 -0
  168. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/serialization/no_op.py +0 -0
  169. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/idempotency/serialization/pydantic.py +0 -0
  170. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/jmespath_utils/__init__.py +0 -0
  171. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/jmespath_utils/envelopes.py +0 -0
  172. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/__init__.py +0 -0
  173. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/appconfig.py +0 -0
  174. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/base.py +0 -0
  175. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/dynamodb.py +0 -0
  176. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/exceptions.py +0 -0
  177. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/secrets.py +0 -0
  178. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/ssm.py +0 -0
  179. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parameters/types.py +0 -0
  180. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/__init__.py +0 -0
  181. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/compat.py +0 -0
  182. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/__init__.py +0 -0
  183. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/apigw.py +0 -0
  184. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py +0 -0
  185. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/base.py +0 -0
  186. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/bedrock_agent.py +0 -0
  187. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py +0 -0
  188. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py +0 -0
  189. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py +0 -0
  190. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/kafka.py +0 -0
  191. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py +0 -0
  192. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py +0 -0
  193. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py +0 -0
  194. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/sns.py +0 -0
  195. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/sqs.py +0 -0
  196. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/vpc_lattice.py +0 -0
  197. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/envelopes/vpc_latticev2.py +0 -0
  198. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/exceptions.py +0 -0
  199. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/alb.py +0 -0
  200. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/apigw.py +0 -0
  201. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/apigwv2.py +0 -0
  202. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/bedrock_agent.py +0 -0
  203. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/cloudwatch.py +0 -0
  204. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/dynamodb.py +0 -0
  205. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/event_bridge.py +0 -0
  206. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/kafka.py +0 -0
  207. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/kinesis.py +0 -0
  208. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py +0 -0
  209. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/kinesis_firehose_sqs.py +0 -0
  210. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/lambda_function_url.py +0 -0
  211. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/s3.py +0 -0
  212. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py +0 -0
  213. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/s3_event_notification.py +0 -0
  214. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/s3_object_event.py +0 -0
  215. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/ses.py +0 -0
  216. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/sns.py +0 -0
  217. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/sqs.py +0 -0
  218. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/vpc_lattice.py +0 -0
  219. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/models/vpc_latticev2.py +0 -0
  220. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/parser.py +0 -0
  221. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/pydantic.py +0 -0
  222. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/parser/types.py +0 -0
  223. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/serialization.py +0 -0
  224. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/__init__.py +0 -0
  225. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py +0 -0
  226. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/compat.py +0 -0
  227. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/s3_object.py +0 -0
  228. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/transformations/__init__.py +0 -0
  229. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/transformations/base.py +0 -0
  230. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/transformations/csv.py +0 -0
  231. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/transformations/gzip.py +0 -0
  232. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/streaming/transformations/zip.py +0 -0
  233. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/typing/__init__.py +0 -0
  234. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/typing/lambda_client_context.py +0 -0
  235. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/typing/lambda_client_context_mobile_client.py +0 -0
  236. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/typing/lambda_cognito_identity.py +0 -0
  237. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/typing/lambda_context.py +0 -0
  238. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/validation/__init__.py +0 -0
  239. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/validation/base.py +0 -0
  240. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/validation/envelopes.py +0 -0
  241. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.0}/aws_lambda_powertools/utilities/validation/exceptions.py +0 -0
  242. {aws_lambda_powertools-2.38.1 → aws_lambda_powertools-2.39.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.38.1
3
+ Version: 2.39.0
4
4
  Summary: Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity.
5
5
  Home-page: https://github.com/aws-powertools/powertools-lambda-python
6
6
  License: MIT
@@ -29,8 +29,9 @@ Provides-Extra: validation
29
29
  Requires-Dist: aws-encryption-sdk (>=3.1.1,<4.0.0) ; extra == "datamasking"
30
30
  Requires-Dist: aws-xray-sdk (>=2.8.0,<3.0.0) ; extra == "tracer" or extra == "all"
31
31
  Requires-Dist: boto3 (>=1.26.164,<2.0.0) ; extra == "aws-sdk"
32
- Requires-Dist: datadog-lambda (>=4.77,<6.0) ; extra == "datadog"
32
+ Requires-Dist: datadog-lambda (>=4.77,<7.0) ; extra == "datadog"
33
33
  Requires-Dist: fastjsonschema (>=2.14.5,<3.0.0) ; extra == "validation" or extra == "all"
34
+ Requires-Dist: jmespath (>=1.0.1,<2.0.0)
34
35
  Requires-Dist: jsonpath-ng (>=1.6.0,<2.0.0) ; extra == "datamasking"
35
36
  Requires-Dist: pydantic (>=1.8.2,<2.0.0) ; extra == "parser" or extra == "all"
36
37
  Requires-Dist: redis (>=4.4,<6.0) ; extra == "redis"
@@ -104,6 +105,7 @@ The following companies, among others, use Powertools:
104
105
  * [IMS](https://ims.tech/)
105
106
  * [Jit Security](https://www.jit.io/)
106
107
  * [Propellor.ai](https://www.propellor.ai/)
108
+ * [Recast](https://getrecast.com/)
107
109
  * [TopSport](https://www.topsport.com.au/)
108
110
  * [Transformity](https://transformity.tech/)
109
111
  * [Trek10](https://www.trek10.com/)
@@ -61,6 +61,7 @@ The following companies, among others, use Powertools:
61
61
  * [IMS](https://ims.tech/)
62
62
  * [Jit Security](https://www.jit.io/)
63
63
  * [Propellor.ai](https://www.propellor.ai/)
64
+ * [Recast](https://getrecast.com/)
64
65
  * [TopSport](https://www.topsport.com.au/)
65
66
  * [Transformity](https://transformity.tech/)
66
67
  * [Trek10](https://www.trek10.com/)
@@ -33,7 +33,7 @@ from typing import (
33
33
  from aws_lambda_powertools.event_handler import content_types
34
34
  from aws_lambda_powertools.event_handler.exceptions import NotFoundError, ServiceError
35
35
  from aws_lambda_powertools.event_handler.openapi.constants import DEFAULT_API_VERSION, DEFAULT_OPENAPI_VERSION
36
- from aws_lambda_powertools.event_handler.openapi.exceptions import RequestValidationError
36
+ from aws_lambda_powertools.event_handler.openapi.exceptions import RequestValidationError, SchemaValidationError
37
37
  from aws_lambda_powertools.event_handler.openapi.types import (
38
38
  COMPONENT_REF_PREFIX,
39
39
  METHODS_WITH_BODY,
@@ -43,7 +43,12 @@ from aws_lambda_powertools.event_handler.openapi.types import (
43
43
  validation_error_definition,
44
44
  validation_error_response_definition,
45
45
  )
46
- from aws_lambda_powertools.event_handler.util import _FrozenDict
46
+ from aws_lambda_powertools.event_handler.util import (
47
+ _FrozenDict,
48
+ _FrozenListDict,
49
+ _validate_openapi_security_parameters,
50
+ extract_origin_header,
51
+ )
47
52
  from aws_lambda_powertools.shared.cookies import Cookie
48
53
  from aws_lambda_powertools.shared.functions import powertools_dev_is_set
49
54
  from aws_lambda_powertools.shared.json_encoder import Encoder
@@ -206,7 +211,7 @@ class CORSConfig:
206
211
  # The origin matched an allowed origin, so return the CORS headers
207
212
  headers = {
208
213
  "Access-Control-Allow-Origin": origin,
209
- "Access-Control-Allow-Headers": ",".join(sorted(self.allow_headers)),
214
+ "Access-Control-Allow-Headers": CORSConfig.build_allow_methods(self.allow_headers),
210
215
  }
211
216
 
212
217
  if self.expose_headers:
@@ -217,6 +222,23 @@ class CORSConfig:
217
222
  headers["Access-Control-Allow-Credentials"] = "true"
218
223
  return headers
219
224
 
225
+ @staticmethod
226
+ def build_allow_methods(methods: Set[str]) -> str:
227
+ """Build sorted comma delimited methods for Access-Control-Allow-Methods header
228
+
229
+ Parameters
230
+ ----------
231
+ methods : set[str]
232
+ Set of HTTP Methods
233
+
234
+ Returns
235
+ -------
236
+ set[str]
237
+ Formatted string with all HTTP Methods allowed for CORS e.g., `GET, OPTIONS`
238
+
239
+ """
240
+ return ",".join(sorted(methods))
241
+
220
242
 
221
243
  class Response(Generic[ResponseT]):
222
244
  """Response data class that provides greater control over what is returned from the proxy event"""
@@ -277,16 +299,16 @@ class Route:
277
299
  func: Callable,
278
300
  cors: bool,
279
301
  compress: bool,
280
- cache_control: Optional[str],
281
- summary: Optional[str],
282
- description: Optional[str],
283
- responses: Optional[Dict[int, OpenAPIResponse]],
284
- response_description: Optional[str],
285
- tags: Optional[List[str]],
286
- operation_id: Optional[str],
287
- include_in_schema: bool,
288
- security: Optional[List[Dict[str, List[str]]]],
289
- middlewares: Optional[List[Callable[..., Response]]],
302
+ cache_control: Optional[str] = None,
303
+ summary: Optional[str] = None,
304
+ description: Optional[str] = None,
305
+ responses: Optional[Dict[int, OpenAPIResponse]] = None,
306
+ response_description: Optional[str] = None,
307
+ tags: Optional[List[str]] = None,
308
+ operation_id: Optional[str] = None,
309
+ include_in_schema: bool = True,
310
+ security: Optional[List[Dict[str, List[str]]]] = None,
311
+ middlewares: Optional[List[Callable[..., Response]]] = None,
290
312
  ):
291
313
  """
292
314
 
@@ -703,6 +725,7 @@ class Route:
703
725
  from aws_lambda_powertools.event_handler.openapi.params import Param
704
726
 
705
727
  parameters = []
728
+ parameter: Dict[str, Any]
706
729
  for param in all_route_params:
707
730
  field_info = param.field_info
708
731
  field_info = cast(Param, field_info)
@@ -782,7 +805,8 @@ class ResponseBuilder(Generic[ResponseEventT]):
782
805
 
783
806
  def _add_cors(self, event: ResponseEventT, cors: CORSConfig):
784
807
  """Update headers to include the configured Access-Control headers"""
785
- self.response.headers.update(cors.to_dict(event.get_header_value("Origin")))
808
+ extracted_origin_header = extract_origin_header(event.resolved_headers_field)
809
+ self.response.headers.update(cors.to_dict(extracted_origin_header))
786
810
 
787
811
  def _add_cache_control(self, cache_control: str):
788
812
  """Set the specified cache control headers for 200 http responses. For non-200 `no-cache` is used."""
@@ -1399,7 +1423,6 @@ def _registered_api_adapter(
1399
1423
  """
1400
1424
  route_args: Dict = app.context.get("_route_args", {})
1401
1425
  logger.debug(f"Calling API Route Handler: {route_args}")
1402
-
1403
1426
  return app._to_response(next_middleware(**route_args))
1404
1427
 
1405
1428
 
@@ -1587,6 +1610,16 @@ class ApiGatewayResolver(BaseRouter):
1587
1610
 
1588
1611
  # Add routes to the OpenAPI schema
1589
1612
  for route in all_routes:
1613
+
1614
+ if route.security and not _validate_openapi_security_parameters(
1615
+ security=route.security,
1616
+ security_schemes=security_schemes,
1617
+ ):
1618
+ raise SchemaValidationError(
1619
+ "Security configuration was not found in security_schemas or security_schema was not defined. "
1620
+ "See: https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/#security-schemes",
1621
+ )
1622
+
1590
1623
  if not route.include_in_schema:
1591
1624
  continue
1592
1625
 
@@ -1629,15 +1662,15 @@ class ApiGatewayResolver(BaseRouter):
1629
1662
  security: Optional[List[Dict[str, List[str]]]],
1630
1663
  security_schemes: Optional[Dict[str, "SecurityScheme"]],
1631
1664
  ) -> Optional[List[Dict[str, List[str]]]]:
1665
+
1632
1666
  if not security:
1633
1667
  return None
1634
1668
 
1635
- if not security_schemes:
1636
- raise ValueError("security_schemes must be provided if security is provided")
1637
-
1638
- # Check if all keys in security are present in the security_schemes
1639
- if any(key not in security_schemes for sec in security for key in sec):
1640
- raise ValueError("Some security schemes not found in security_schemes")
1669
+ if not _validate_openapi_security_parameters(security=security, security_schemes=security_schemes):
1670
+ raise SchemaValidationError(
1671
+ "Security configuration was not found in security_schemas or security_schema was not defined. "
1672
+ "See: https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/#security-schemes",
1673
+ )
1641
1674
 
1642
1675
  return security
1643
1676
 
@@ -1950,6 +1983,36 @@ class ApiGatewayResolver(BaseRouter):
1950
1983
  def resolve(self, event, context) -> Dict[str, Any]:
1951
1984
  """Resolves the response based on the provide event and decorator routes
1952
1985
 
1986
+ ## Internals
1987
+
1988
+ Request processing chain is triggered by a Route object being called _(`_call_route` -> `__call__`)_:
1989
+
1990
+ 1. **When a route is matched**
1991
+ 1.1. Exception handlers _(if any exception bubbled up and caught)_
1992
+ 1.2. Global middlewares _(before, and after on the way back)_
1993
+ 1.3. Path level middleware _(before, and after on the way back)_
1994
+ 1.4. Middleware adapter to ensure Response is homogenous (_registered_api_adapter)
1995
+ 1.5. Run actual route
1996
+ 2. **When a route is NOT matched**
1997
+ 2.1. Exception handlers _(if any exception bubbled up and caught)_
1998
+ 2.2. Global middlewares _(before, and after on the way back)_
1999
+ 2.3. Path level middleware _(before, and after on the way back)_
2000
+ 2.4. Middleware adapter to ensure Response is homogenous (_registered_api_adapter)
2001
+ 2.5. Run 404 route handler
2002
+ 3. **When a route is a pre-flight CORS (often not matched)**
2003
+ 3.1. Exception handlers _(if any exception bubbled up and caught)_
2004
+ 3.2. Global middlewares _(before, and after on the way back)_
2005
+ 3.3. Path level middleware _(before, and after on the way back)_
2006
+ 3.4. Middleware adapter to ensure Response is homogenous (_registered_api_adapter)
2007
+ 3.5. Return 204 with appropriate CORS headers
2008
+ 4. **When a route is matched with Data Validation enabled**
2009
+ 4.1. Exception handlers _(if any exception bubbled up and caught)_
2010
+ 4.2. Data Validation middleware _(before, and after on the way back)_
2011
+ 4.3. Global middlewares _(before, and after on the way back)_
2012
+ 4.4. Path level middleware _(before, and after on the way back)_
2013
+ 4.5. Middleware adapter to ensure Response is homogenous (_registered_api_adapter)
2014
+ 4.6. Run actual route
2015
+
1953
2016
  Parameters
1954
2017
  ----------
1955
2018
  event: Dict[str, Any]
@@ -2073,7 +2136,9 @@ class ApiGatewayResolver(BaseRouter):
2073
2136
  method = self.current_event.http_method.upper()
2074
2137
  path = self._remove_prefix(self.current_event.path)
2075
2138
 
2076
- for route in self._static_routes + self._dynamic_routes:
2139
+ registered_routes = self._static_routes + self._dynamic_routes
2140
+
2141
+ for route in registered_routes:
2077
2142
  if method != route.method:
2078
2143
  continue
2079
2144
  match_results: Optional[Match] = route.rule.match(path)
@@ -2085,8 +2150,7 @@ class ApiGatewayResolver(BaseRouter):
2085
2150
  route_keys = self._convert_matches_into_route_keys(match_results)
2086
2151
  return self._call_route(route, route_keys) # pass fn args
2087
2152
 
2088
- logger.debug(f"No match found for path {path} and method {method}")
2089
- return self._not_found(method)
2153
+ return self._handle_not_found(method=method, path=path)
2090
2154
 
2091
2155
  def _remove_prefix(self, path: str) -> str:
2092
2156
  """Remove the configured prefix from the path"""
@@ -2124,35 +2188,65 @@ class ApiGatewayResolver(BaseRouter):
2124
2188
 
2125
2189
  return path.startswith(prefix + "/")
2126
2190
 
2127
- def _not_found(self, method: str) -> ResponseBuilder:
2191
+ def _handle_not_found(self, method: str, path: str) -> ResponseBuilder:
2128
2192
  """Called when no matching route was found and includes support for the cors preflight response"""
2129
- headers = {}
2130
- if self._cors:
2131
- logger.debug("CORS is enabled, updating headers.")
2132
- headers.update(self._cors.to_dict(self.current_event.get_header_value("Origin")))
2133
-
2134
- if method == "OPTIONS":
2135
- logger.debug("Pre-flight request detected. Returning CORS with null response")
2136
- headers["Access-Control-Allow-Methods"] = ",".join(sorted(self._cors_methods))
2137
- return ResponseBuilder(
2138
- response=Response(status_code=204, content_type=None, headers=headers, body=""),
2139
- serializer=self._serializer,
2140
- )
2193
+ logger.debug(f"No match found for path {path} and method {method}")
2141
2194
 
2142
- handler = self._lookup_exception_handler(NotFoundError)
2143
- if handler:
2144
- return self._response_builder_class(response=handler(NotFoundError()), serializer=self._serializer)
2195
+ def not_found_handler():
2196
+ """Route handler for 404s
2145
2197
 
2146
- return self._response_builder_class(
2147
- response=Response(
2198
+ It handles in the following order:
2199
+
2200
+ 1. Pre-flight CORS requests (OPTIONS)
2201
+ 2. Detects and calls custom HTTP 404 handler
2202
+ 3. Returns standard 404 along with CORS headers
2203
+
2204
+ Returns
2205
+ -------
2206
+ Response
2207
+ HTTP 404 response
2208
+ """
2209
+ _headers: Dict[str, Any] = {}
2210
+
2211
+ # Pre-flight request? Return immediately to avoid browser error
2212
+ if self._cors and method == "OPTIONS":
2213
+ logger.debug("Pre-flight request detected. Returning CORS with empty response")
2214
+ _headers["Access-Control-Allow-Methods"] = CORSConfig.build_allow_methods(self._cors_methods)
2215
+
2216
+ return Response(status_code=204, content_type=None, headers=_headers, body="")
2217
+
2218
+ # Customer registered 404 route? Call it.
2219
+ custom_not_found_handler = self._lookup_exception_handler(NotFoundError)
2220
+ if custom_not_found_handler:
2221
+ return custom_not_found_handler(NotFoundError())
2222
+
2223
+ # No CORS and no custom 404 fn? Default response
2224
+ return Response(
2148
2225
  status_code=HTTPStatus.NOT_FOUND.value,
2149
2226
  content_type=content_types.APPLICATION_JSON,
2150
- headers=headers,
2227
+ headers=_headers,
2151
2228
  body={"statusCode": HTTPStatus.NOT_FOUND.value, "message": "Not found"},
2152
- ),
2153
- serializer=self._serializer,
2229
+ )
2230
+
2231
+ # We create a route to trigger entire request chain (middleware+exception handlers)
2232
+ route = Route(
2233
+ rule=self._compile_regex(r".*"),
2234
+ method=method,
2235
+ path=path,
2236
+ func=not_found_handler,
2237
+ cors=self._cors_enabled,
2238
+ compress=False,
2154
2239
  )
2155
2240
 
2241
+ # Add matched Route reference into the Resolver context
2242
+ self.append_context(_route=route, _path=path)
2243
+
2244
+ # Kick-off request chain:
2245
+ # -> exception_handlers()
2246
+ # --> middlewares()
2247
+ # ---> not_found_route()
2248
+ return self._call_route(route=route, route_arguments={})
2249
+
2156
2250
  def _call_route(self, route: Route, route_arguments: Dict[str, str]) -> ResponseBuilder:
2157
2251
  """Actually call the matching route with any provided keyword arguments."""
2158
2252
  try:
@@ -2384,6 +2478,7 @@ class Router(BaseRouter):
2384
2478
  methods = (method,) if isinstance(method, str) else tuple(method)
2385
2479
  frozen_responses = _FrozenDict(responses) if responses else None
2386
2480
  frozen_tags = frozenset(tags) if tags else None
2481
+ frozen_security = _FrozenListDict(security) if security else None
2387
2482
 
2388
2483
  route_key = (
2389
2484
  rule,
@@ -2398,7 +2493,7 @@ class Router(BaseRouter):
2398
2493
  frozen_tags,
2399
2494
  operation_id,
2400
2495
  include_in_schema,
2401
- security,
2496
+ frozen_security,
2402
2497
  )
2403
2498
 
2404
2499
  # Collate Middleware for routes
@@ -14,6 +14,7 @@ from pydantic.color import Color
14
14
  from pydantic.types import SecretBytes, SecretStr
15
15
 
16
16
  from aws_lambda_powertools.event_handler.openapi.compat import _model_dump
17
+ from aws_lambda_powertools.event_handler.openapi.exceptions import SerializationError
17
18
  from aws_lambda_powertools.event_handler.openapi.types import IncEx
18
19
 
19
20
  """
@@ -69,88 +70,94 @@ def jsonable_encoder( # noqa: PLR0911
69
70
  if exclude is not None and not isinstance(exclude, (set, dict)):
70
71
  exclude = set(exclude)
71
72
 
72
- # Pydantic models
73
- if isinstance(obj, BaseModel):
74
- return _dump_base_model(
75
- obj=obj,
76
- include=include,
77
- exclude=exclude,
78
- by_alias=by_alias,
79
- exclude_unset=exclude_unset,
80
- exclude_none=exclude_none,
81
- exclude_defaults=exclude_defaults,
82
- )
73
+ try:
74
+ # Pydantic models
75
+ if isinstance(obj, BaseModel):
76
+ return _dump_base_model(
77
+ obj=obj,
78
+ include=include,
79
+ exclude=exclude,
80
+ by_alias=by_alias,
81
+ exclude_unset=exclude_unset,
82
+ exclude_none=exclude_none,
83
+ exclude_defaults=exclude_defaults,
84
+ )
83
85
 
84
- # Dataclasses
85
- if dataclasses.is_dataclass(obj):
86
- obj_dict = dataclasses.asdict(obj)
87
- return jsonable_encoder(
88
- obj_dict,
89
- include=include,
90
- exclude=exclude,
91
- by_alias=by_alias,
92
- exclude_unset=exclude_unset,
93
- exclude_defaults=exclude_defaults,
94
- exclude_none=exclude_none,
95
- )
86
+ # Dataclasses
87
+ if dataclasses.is_dataclass(obj):
88
+ obj_dict = dataclasses.asdict(obj)
89
+ return jsonable_encoder(
90
+ obj_dict,
91
+ include=include,
92
+ exclude=exclude,
93
+ by_alias=by_alias,
94
+ exclude_unset=exclude_unset,
95
+ exclude_defaults=exclude_defaults,
96
+ exclude_none=exclude_none,
97
+ )
96
98
 
97
- # Enums
98
- if isinstance(obj, Enum):
99
- return obj.value
99
+ # Enums
100
+ if isinstance(obj, Enum):
101
+ return obj.value
100
102
 
101
- # Paths
102
- if isinstance(obj, PurePath):
103
- return str(obj)
103
+ # Paths
104
+ if isinstance(obj, PurePath):
105
+ return str(obj)
104
106
 
105
- # Scalars
106
- if isinstance(obj, (str, int, float, type(None))):
107
- return obj
107
+ # Scalars
108
+ if isinstance(obj, (str, int, float, type(None))):
109
+ return obj
108
110
 
109
- # Dictionaries
110
- if isinstance(obj, dict):
111
- return _dump_dict(
112
- obj=obj,
113
- include=include,
114
- exclude=exclude,
115
- by_alias=by_alias,
116
- exclude_none=exclude_none,
117
- exclude_unset=exclude_unset,
118
- )
111
+ # Dictionaries
112
+ if isinstance(obj, dict):
113
+ return _dump_dict(
114
+ obj=obj,
115
+ include=include,
116
+ exclude=exclude,
117
+ by_alias=by_alias,
118
+ exclude_none=exclude_none,
119
+ exclude_unset=exclude_unset,
120
+ )
121
+
122
+ # Sequences
123
+ if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)):
124
+ return _dump_sequence(
125
+ obj=obj,
126
+ include=include,
127
+ exclude=exclude,
128
+ by_alias=by_alias,
129
+ exclude_none=exclude_none,
130
+ exclude_defaults=exclude_defaults,
131
+ exclude_unset=exclude_unset,
132
+ )
119
133
 
120
- # Sequences
121
- if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)):
122
- return _dump_sequence(
134
+ # Other types
135
+ if type(obj) in ENCODERS_BY_TYPE:
136
+ return ENCODERS_BY_TYPE[type(obj)](obj)
137
+
138
+ for encoder, classes_tuple in encoders_by_class_tuples.items():
139
+ if isinstance(obj, classes_tuple):
140
+ return encoder(obj)
141
+
142
+ # Use custom serializer if present
143
+ if custom_serializer:
144
+ return custom_serializer(obj)
145
+
146
+ # Default
147
+ return _dump_other(
123
148
  obj=obj,
124
149
  include=include,
125
150
  exclude=exclude,
126
151
  by_alias=by_alias,
127
152
  exclude_none=exclude_none,
128
- exclude_defaults=exclude_defaults,
129
153
  exclude_unset=exclude_unset,
154
+ exclude_defaults=exclude_defaults,
130
155
  )
131
-
132
- # Other types
133
- if type(obj) in ENCODERS_BY_TYPE:
134
- return ENCODERS_BY_TYPE[type(obj)](obj)
135
-
136
- for encoder, classes_tuple in encoders_by_class_tuples.items():
137
- if isinstance(obj, classes_tuple):
138
- return encoder(obj)
139
-
140
- # Use custom serializer if present
141
- if custom_serializer:
142
- return custom_serializer(obj)
143
-
144
- # Default
145
- return _dump_other(
146
- obj=obj,
147
- include=include,
148
- exclude=exclude,
149
- by_alias=by_alias,
150
- exclude_none=exclude_none,
151
- exclude_unset=exclude_unset,
152
- exclude_defaults=exclude_defaults,
153
- )
156
+ except ValueError as exc:
157
+ raise SerializationError(
158
+ f"Unable to serialize the object {obj} as it is not a supported type. Error details: {exc}",
159
+ "See: https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/#serializing-objects",
160
+ ) from exc
154
161
 
155
162
 
156
163
  def _dump_base_model(
@@ -21,3 +21,15 @@ class RequestValidationError(ValidationException):
21
21
  def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None:
22
22
  super().__init__(errors)
23
23
  self.body = body
24
+
25
+
26
+ class SerializationError(Exception):
27
+ """
28
+ Base exception for all encoding errors
29
+ """
30
+
31
+
32
+ class SchemaValidationError(ValidationException):
33
+ """
34
+ Raised when the OpenAPI schema validation fails
35
+ """
@@ -0,0 +1,100 @@
1
+ from typing import Any, Dict, List, Optional
2
+
3
+ from aws_lambda_powertools.event_handler.openapi.models import SecurityScheme
4
+ from aws_lambda_powertools.utilities.data_classes.shared_functions import get_header_value
5
+
6
+
7
+ class _FrozenDict(dict):
8
+ """
9
+ A dictionary that can be used as a key in another dictionary.
10
+
11
+ This is needed because the default dict implementation is not hashable.
12
+ The only usage for this right now is to store dicts as part of the Router key.
13
+ The implementation only takes into consideration the keys of the dictionary.
14
+
15
+ MAINTENANCE: this is a temporary solution until we refactor the route key into a class.
16
+ """
17
+
18
+ def __hash__(self):
19
+ return hash(frozenset(self.keys()))
20
+
21
+
22
+ class _FrozenListDict(List[Dict[str, List[str]]]):
23
+ """
24
+ Freezes a list of dictionaries containing lists of strings.
25
+
26
+ This function takes a list of dictionaries where the values are lists of strings and converts it into
27
+ a frozen set of frozen sets of frozen dictionaries. This is done by iterating over the input list,
28
+ converting each dictionary's values (lists of strings) into frozen sets of strings, and then
29
+ converting the resulting dictionary into a frozen dictionary. Finally, all these frozen dictionaries
30
+ are collected into a frozen set of frozen sets.
31
+
32
+ This operation is useful when you want to ensure the immutability of the data structure and make it
33
+ hashable, which is required for certain operations like using it as a key in a dictionary or as an
34
+ element in a set.
35
+
36
+ Example: [{"TestAuth": ["test", "test1"]}]
37
+ """
38
+
39
+ def __hash__(self):
40
+ hashable_items = []
41
+ for item in self:
42
+ hashable_items.extend((key, frozenset(value)) for key, value in item.items())
43
+ return hash(frozenset(hashable_items))
44
+
45
+
46
+ def extract_origin_header(resolver_headers: Dict[str, Any]):
47
+ """
48
+ Extracts the 'origin' or 'Origin' header from the provided resolver headers.
49
+
50
+ The 'origin' or 'Origin' header can be either a single header or a multi-header.
51
+
52
+ Parameters
53
+ ----------
54
+ resolver_headers: Dict
55
+ A dictionary containing the headers.
56
+
57
+ Returns
58
+ -------
59
+ Optional[str]
60
+ The value(s) of the origin header or None.
61
+ """
62
+ resolved_header = get_header_value(
63
+ headers=resolver_headers,
64
+ name="origin",
65
+ default_value=None,
66
+ case_sensitive=False,
67
+ )
68
+ if isinstance(resolved_header, list):
69
+ return resolved_header[0]
70
+
71
+ return resolved_header
72
+
73
+
74
+ def _validate_openapi_security_parameters(
75
+ security: List[Dict[str, List[str]]],
76
+ security_schemes: Optional[Dict[str, "SecurityScheme"]] = None,
77
+ ) -> bool:
78
+ """
79
+ This function checks if all security requirements listed in the 'security'
80
+ parameter are defined in the 'security_schemes' dictionary, as specified
81
+ in the OpenAPI schema.
82
+
83
+ Parameters
84
+ ----------
85
+ security: List[Dict[str, List[str]]]
86
+ A list of security requirements
87
+ security_schemes: Optional[Dict[str, "SecurityScheme"]]
88
+ A dictionary mapping security scheme names to their corresponding security scheme objects.
89
+
90
+ Returns
91
+ -------
92
+ bool
93
+ Whether list of security schemes match allowed security_schemes.
94
+ """
95
+
96
+ security_schemes = security_schemes or {}
97
+
98
+ security_schema_match = all(key in security_schemes for sec in security for key in sec)
99
+
100
+ return bool(security_schema_match and security_schemes)
@@ -1,3 +1,3 @@
1
1
  """Exposes version constant to avoid circular dependencies."""
2
2
 
3
- VERSION = "2.38.1"
3
+ VERSION = "2.39.0"
@@ -17,6 +17,7 @@ from .cloud_watch_alarm_event import (
17
17
  )
18
18
  from .cloud_watch_custom_widget_event import CloudWatchDashboardCustomWidgetEvent
19
19
  from .cloud_watch_logs_event import CloudWatchLogsEvent
20
+ from .cloudformation_custom_resource_event import CloudFormationCustomResourceEvent
20
21
  from .code_pipeline_job_event import CodePipelineJobEvent
21
22
  from .connect_contact_flow_event import ConnectContactFlowEvent
22
23
  from .dynamo_db_stream_event import DynamoDBStreamEvent
@@ -81,4 +82,5 @@ __all__ = [
81
82
  "AWSConfigRuleEvent",
82
83
  "VPCLatticeEvent",
83
84
  "VPCLatticeEventV2",
85
+ "CloudFormationCustomResourceEvent",
84
86
  ]