aws-lambda-powertools 2.35.0__tar.gz → 2.36.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 (240) hide show
  1. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/PKG-INFO +1 -1
  2. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/api_gateway.py +54 -33
  3. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +15 -2
  4. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/encoders.py +8 -1
  5. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/types.py +1 -1
  6. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/logger.py +1 -1
  7. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/base.py +32 -1
  8. aws_lambda_powertools-2.36.0/aws_lambda_powertools/metrics/functions.py +137 -0
  9. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/metrics.py +13 -0
  10. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py +29 -1
  11. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/constants.py +41 -33
  12. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/functions.py +5 -7
  13. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/version.py +1 -1
  14. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/tracing/tracer.py +14 -7
  15. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/batch/exceptions.py +16 -0
  16. aws_lambda_powertools-2.36.0/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py +114 -0
  17. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/__init__.py +14 -0
  18. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/bedrock_agent_event.py +14 -0
  19. aws_lambda_powertools-2.36.0/aws_lambda_powertools/utilities/data_classes/cloud_watch_alarm_event.py +243 -0
  20. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/common.py +8 -5
  21. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/sqs_event.py +4 -1
  22. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parameters/__init__.py +4 -2
  23. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parameters/base.py +6 -0
  24. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parameters/exceptions.py +8 -0
  25. aws_lambda_powertools-2.36.0/aws_lambda_powertools/utilities/parameters/secrets.py +444 -0
  26. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parameters/ssm.py +209 -4
  27. aws_lambda_powertools-2.36.0/aws_lambda_powertools/utilities/parameters/types.py +20 -0
  28. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/pyproject.toml +23 -23
  29. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/setup.py +1 -1
  30. aws_lambda_powertools-2.35.0/aws_lambda_powertools/metrics/functions.py +0 -71
  31. aws_lambda_powertools-2.35.0/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py +0 -92
  32. aws_lambda_powertools-2.35.0/aws_lambda_powertools/utilities/parameters/secrets.py +0 -184
  33. aws_lambda_powertools-2.35.0/aws_lambda_powertools/utilities/parameters/types.py +0 -3
  34. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/LICENSE +0 -0
  35. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/README.md +0 -0
  36. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/THIRD-PARTY-LICENSES +0 -0
  37. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/__init__.py +0 -0
  38. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/__init__.py +0 -0
  39. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/appsync.py +0 -0
  40. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/bedrock_agent.py +0 -0
  41. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/content_types.py +0 -0
  42. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/exceptions.py +0 -0
  43. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/lambda_function_url.py +0 -0
  44. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/middlewares/__init__.py +0 -0
  45. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/middlewares/base.py +0 -0
  46. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/middlewares/schema_validation.py +0 -0
  47. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/__init__.py +0 -0
  48. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/compat.py +0 -0
  49. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/constants.py +0 -0
  50. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/dependant.py +0 -0
  51. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/exceptions.py +0 -0
  52. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/models.py +0 -0
  53. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/params.py +0 -0
  54. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/pydantic_loader.py +0 -0
  55. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/__init__.py +0 -0
  56. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py +0 -0
  57. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/swagger-ui-bundle.min.js +0 -0
  58. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/openapi/swagger_ui/swagger-ui.min.css +0 -0
  59. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/router.py +0 -0
  60. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/types.py +0 -0
  61. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/util.py +0 -0
  62. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/event_handler/vpc_lattice.py +0 -0
  63. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/exceptions/__init__.py +0 -0
  64. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/__init__.py +0 -0
  65. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/correlation_paths.py +0 -0
  66. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/exceptions.py +0 -0
  67. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/filters.py +0 -0
  68. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/formatter.py +0 -0
  69. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/formatters/__init__.py +0 -0
  70. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/formatters/datadog.py +0 -0
  71. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/lambda_context.py +0 -0
  72. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/types.py +0 -0
  73. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/logging/utils.py +0 -0
  74. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/__init__.py +0 -0
  75. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/exceptions.py +0 -0
  76. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/metric.py +0 -0
  77. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/__init__.py +0 -0
  78. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/base.py +0 -0
  79. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/__init__.py +0 -0
  80. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/constants.py +0 -0
  81. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py +0 -0
  82. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/metric_properties.py +0 -0
  83. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/cloudwatch_emf/types.py +0 -0
  84. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/cold_start.py +0 -0
  85. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/datadog/__init__.py +0 -0
  86. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/datadog/datadog.py +0 -0
  87. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/datadog/metrics.py +0 -0
  88. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/provider/datadog/warnings.py +0 -0
  89. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/metrics/types.py +0 -0
  90. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/middleware_factory/__init__.py +0 -0
  91. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/middleware_factory/exceptions.py +0 -0
  92. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/middleware_factory/factory.py +0 -0
  93. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/package_logger.py +0 -0
  94. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/py.typed +0 -0
  95. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/__init__.py +0 -0
  96. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/cache_dict.py +0 -0
  97. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/cookies.py +0 -0
  98. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/headers_serializer.py +0 -0
  99. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/json_encoder.py +0 -0
  100. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/lazy_import.py +0 -0
  101. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/types.py +0 -0
  102. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/shared/user_agent.py +0 -0
  103. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/tracing/__init__.py +0 -0
  104. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/tracing/base.py +0 -0
  105. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/tracing/extensions.py +0 -0
  106. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/__init__.py +0 -0
  107. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/batch/__init__.py +0 -0
  108. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/batch/base.py +0 -0
  109. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/batch/decorators.py +0 -0
  110. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/batch/types.py +0 -0
  111. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/active_mq_event.py +0 -0
  112. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/alb_event.py +0 -0
  113. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py +0 -0
  114. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py +0 -0
  115. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/appsync/__init__.py +0 -0
  116. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/appsync/scalar_types_utils.py +0 -0
  117. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/appsync_authorizer_event.py +0 -0
  118. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/appsync_resolver_event.py +0 -0
  119. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/aws_config_rule_event.py +0 -0
  120. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_custom_widget_event.py +0 -0
  121. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/cloud_watch_logs_event.py +0 -0
  122. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/code_pipeline_job_event.py +0 -0
  123. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/cognito_user_pool_event.py +0 -0
  124. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/connect_contact_flow_event.py +0 -0
  125. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/dynamo_db_stream_event.py +0 -0
  126. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py +0 -0
  127. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/event_source.py +0 -0
  128. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/kafka_event.py +0 -0
  129. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/kinesis_firehose_event.py +0 -0
  130. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/kinesis_stream_event.py +0 -0
  131. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/lambda_function_url_event.py +0 -0
  132. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/rabbit_mq_event.py +0 -0
  133. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/s3_batch_operation_event.py +0 -0
  134. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/s3_event.py +0 -0
  135. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/s3_object_event.py +0 -0
  136. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/secrets_manager_event.py +0 -0
  137. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/ses_event.py +0 -0
  138. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/shared_functions.py +0 -0
  139. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/sns_event.py +0 -0
  140. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +0 -0
  141. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/__init__.py +0 -0
  142. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/base.py +0 -0
  143. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/constants.py +0 -0
  144. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/exceptions.py +0 -0
  145. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/provider/__init__.py +0 -0
  146. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/provider/base.py +0 -0
  147. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/provider/kms/__init__.py +0 -0
  148. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/data_masking/provider/kms/aws_encryption_sdk.py +0 -0
  149. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/feature_flags/__init__.py +0 -0
  150. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/feature_flags/appconfig.py +0 -0
  151. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/feature_flags/base.py +0 -0
  152. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/feature_flags/comparators.py +0 -0
  153. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/feature_flags/exceptions.py +0 -0
  154. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +0 -0
  155. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/feature_flags/schema.py +0 -0
  156. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/__init__.py +0 -0
  157. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/base.py +0 -0
  158. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/config.py +0 -0
  159. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/exceptions.py +0 -0
  160. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/idempotency.py +0 -0
  161. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/persistence/__init__.py +0 -0
  162. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/persistence/base.py +0 -0
  163. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/persistence/datarecord.py +0 -0
  164. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py +0 -0
  165. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/persistence/redis.py +0 -0
  166. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/serialization/__init__.py +0 -0
  167. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/serialization/base.py +0 -0
  168. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/serialization/custom_dict.py +0 -0
  169. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/serialization/dataclass.py +0 -0
  170. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/serialization/no_op.py +0 -0
  171. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/idempotency/serialization/pydantic.py +0 -0
  172. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/jmespath_utils/__init__.py +0 -0
  173. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/jmespath_utils/envelopes.py +0 -0
  174. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parameters/appconfig.py +0 -0
  175. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parameters/dynamodb.py +0 -0
  176. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/__init__.py +0 -0
  177. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/compat.py +0 -0
  178. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/__init__.py +0 -0
  179. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/apigw.py +0 -0
  180. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py +0 -0
  181. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/base.py +0 -0
  182. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/bedrock_agent.py +0 -0
  183. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py +0 -0
  184. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py +0 -0
  185. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py +0 -0
  186. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/kafka.py +0 -0
  187. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py +0 -0
  188. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py +0 -0
  189. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py +0 -0
  190. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/sns.py +0 -0
  191. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/sqs.py +0 -0
  192. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/vpc_lattice.py +0 -0
  193. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/envelopes/vpc_latticev2.py +0 -0
  194. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/exceptions.py +0 -0
  195. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/__init__.py +0 -0
  196. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/alb.py +0 -0
  197. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/apigw.py +0 -0
  198. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/apigwv2.py +0 -0
  199. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/bedrock_agent.py +0 -0
  200. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/cloudformation_custom_resource.py +0 -0
  201. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/cloudwatch.py +0 -0
  202. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/dynamodb.py +0 -0
  203. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/event_bridge.py +0 -0
  204. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/kafka.py +0 -0
  205. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/kinesis.py +0 -0
  206. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py +0 -0
  207. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/kinesis_firehose_sqs.py +0 -0
  208. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/lambda_function_url.py +0 -0
  209. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/s3.py +0 -0
  210. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py +0 -0
  211. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/s3_event_notification.py +0 -0
  212. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/s3_object_event.py +0 -0
  213. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/ses.py +0 -0
  214. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/sns.py +0 -0
  215. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/sqs.py +0 -0
  216. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/vpc_lattice.py +0 -0
  217. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/models/vpc_latticev2.py +0 -0
  218. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/parser.py +0 -0
  219. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/pydantic.py +0 -0
  220. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/parser/types.py +0 -0
  221. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/serialization.py +0 -0
  222. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/__init__.py +0 -0
  223. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/_s3_seekable_io.py +0 -0
  224. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/compat.py +0 -0
  225. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/s3_object.py +0 -0
  226. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/transformations/__init__.py +0 -0
  227. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/transformations/base.py +0 -0
  228. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/transformations/csv.py +0 -0
  229. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/transformations/gzip.py +0 -0
  230. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/streaming/transformations/zip.py +0 -0
  231. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/typing/__init__.py +0 -0
  232. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/typing/lambda_client_context.py +0 -0
  233. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/typing/lambda_client_context_mobile_client.py +0 -0
  234. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/typing/lambda_cognito_identity.py +0 -0
  235. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/typing/lambda_context.py +0 -0
  236. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/validation/__init__.py +0 -0
  237. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/validation/base.py +0 -0
  238. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/validation/envelopes.py +0 -0
  239. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.0}/aws_lambda_powertools/utilities/validation/exceptions.py +0 -0
  240. {aws_lambda_powertools-2.35.0 → aws_lambda_powertools-2.36.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.35.0
3
+ Version: 2.36.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
@@ -503,6 +503,18 @@ class Route:
503
503
  if request_body_oai:
504
504
  operation["requestBody"] = request_body_oai
505
505
 
506
+ # Validation failure response (422) will always be part of the schema
507
+ operation_responses: Dict[int, OpenAPIResponse] = {
508
+ 422: {
509
+ "description": "Validation Error",
510
+ "content": {
511
+ "application/json": {
512
+ "schema": {"$ref": COMPONENT_REF_PREFIX + "HTTPValidationError"},
513
+ },
514
+ },
515
+ },
516
+ }
517
+
506
518
  # Add the response to the OpenAPI operation
507
519
  if self.responses:
508
520
  for status_code in list(self.responses):
@@ -549,45 +561,34 @@ class Route:
549
561
 
550
562
  response["content"][content_type] = new_payload
551
563
 
552
- operation["responses"] = self.responses
564
+ # Merge the user provided response with the default responses
565
+ operation_responses[status_code] = response
553
566
  else:
554
567
  # Set the default 200 response
555
- responses = operation.setdefault("responses", {})
556
- success_response = responses.setdefault(200, {})
557
- success_response["description"] = self.response_description or _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION
558
- success_response["content"] = {"application/json": {"schema": {}}}
559
- json_response = success_response["content"].setdefault("application/json", {})
560
-
561
- # Add the response schema to the OpenAPI 200 response
562
- json_response.update(
563
- self._openapi_operation_return(
564
- param=dependant.return_param,
565
- model_name_map=model_name_map,
566
- field_mapping=field_mapping,
567
- ),
568
+ response_schema = self._openapi_operation_return(
569
+ param=dependant.return_param,
570
+ model_name_map=model_name_map,
571
+ field_mapping=field_mapping,
568
572
  )
569
573
 
570
- # Add validation failure response (422)
571
- operation["responses"][422] = {
572
- "description": "Validation Error",
573
- "content": {
574
- "application/json": {
575
- "schema": {"$ref": COMPONENT_REF_PREFIX + "HTTPValidationError"},
576
- },
577
- },
574
+ # Add the response schema to the OpenAPI 200 response
575
+ operation_responses[200] = {
576
+ "description": self.response_description or _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION,
577
+ "content": {"application/json": response_schema},
578
578
  }
579
579
 
580
- # Add the validation error schema to the definitions, but only if it hasn't been added yet
581
- if "ValidationError" not in definitions:
582
- definitions.update(
583
- {
584
- "ValidationError": validation_error_definition,
585
- "HTTPValidationError": validation_error_response_definition,
586
- },
587
- )
588
-
580
+ operation["responses"] = operation_responses
589
581
  path[self.method.lower()] = operation
590
582
 
583
+ # Add the validation error schema to the definitions, but only if it hasn't been added yet
584
+ if "ValidationError" not in definitions:
585
+ definitions.update(
586
+ {
587
+ "ValidationError": validation_error_definition,
588
+ "HTTPValidationError": validation_error_response_definition,
589
+ },
590
+ )
591
+
591
592
  # Generate the response schema
592
593
  return path, definitions
593
594
 
@@ -1401,7 +1402,9 @@ class ApiGatewayResolver(BaseRouter):
1401
1402
  if self._enable_validation:
1402
1403
  from aws_lambda_powertools.event_handler.middlewares.openapi_validation import OpenAPIValidationMiddleware
1403
1404
 
1404
- self.use([OpenAPIValidationMiddleware()])
1405
+ # Note the serializer argument: only use custom serializer if provided by the caller
1406
+ # Otherwise, fully rely on the internal Pydantic based mechanism to serialize responses for validation.
1407
+ self.use([OpenAPIValidationMiddleware(validation_serializer=serializer)])
1405
1408
 
1406
1409
  def get_openapi_schema(
1407
1410
  self,
@@ -1621,6 +1624,7 @@ class ApiGatewayResolver(BaseRouter):
1621
1624
  license_info: Optional["License"] = None,
1622
1625
  swagger_base_url: Optional[str] = None,
1623
1626
  middlewares: Optional[List[Callable[..., Response]]] = None,
1627
+ compress: bool = False,
1624
1628
  ):
1625
1629
  """
1626
1630
  Returns the OpenAPI schema as a JSON serializable dict
@@ -1653,11 +1657,13 @@ class ApiGatewayResolver(BaseRouter):
1653
1657
  The base url for the swagger UI. If not provided, we will serve a recent version of the Swagger UI.
1654
1658
  middlewares: List[Callable[..., Response]], optional
1655
1659
  List of middlewares to be used for the swagger route.
1660
+ compress: bool, default = False
1661
+ Whether or not to enable gzip compression swagger route.
1656
1662
  """
1657
1663
  from aws_lambda_powertools.event_handler.openapi.compat import model_json
1658
1664
  from aws_lambda_powertools.event_handler.openapi.models import Server
1659
1665
 
1660
- @self.get(path, middlewares=middlewares, include_in_schema=False)
1666
+ @self.get(path, middlewares=middlewares, include_in_schema=False, compress=compress)
1661
1667
  def swagger_handler():
1662
1668
  base_path = self._get_base_path()
1663
1669
 
@@ -2128,6 +2134,9 @@ class ApiGatewayResolver(BaseRouter):
2128
2134
  logger.debug("Appending Router middlewares into App middlewares.")
2129
2135
  self._router_middlewares = self._router_middlewares + router._router_middlewares
2130
2136
 
2137
+ logger.debug("Appending Router exception_handler into App exception_handler.")
2138
+ self._exception_handlers.update(router._exception_handlers)
2139
+
2131
2140
  # use pointer to allow context clearance after event is processed e.g., resolve(evt, ctx)
2132
2141
  router.context = self.context
2133
2142
 
@@ -2193,6 +2202,7 @@ class Router(BaseRouter):
2193
2202
  self._routes_with_middleware: Dict[tuple, List[Callable]] = {}
2194
2203
  self.api_resolver: Optional[BaseRouter] = None
2195
2204
  self.context = {} # early init as customers might add context before event resolution
2205
+ self._exception_handlers: Dict[Type, Callable] = {}
2196
2206
 
2197
2207
  def route(
2198
2208
  self,
@@ -2247,6 +2257,17 @@ class Router(BaseRouter):
2247
2257
 
2248
2258
  return register_route
2249
2259
 
2260
+ def exception_handler(self, exc_class: Union[Type[Exception], List[Type[Exception]]]):
2261
+ def register_exception_handler(func: Callable):
2262
+ if isinstance(exc_class, list):
2263
+ for exp in exc_class:
2264
+ self._exception_handlers[exp] = func
2265
+ else:
2266
+ self._exception_handlers[exc_class] = func
2267
+ return func
2268
+
2269
+ return register_exception_handler
2270
+
2250
2271
 
2251
2272
  class APIGatewayRestResolver(ApiGatewayResolver):
2252
2273
  current_event: APIGatewayProxyEvent
@@ -2,7 +2,7 @@ import dataclasses
2
2
  import json
3
3
  import logging
4
4
  from copy import deepcopy
5
- from typing import Any, Dict, List, Mapping, Optional, Sequence, Tuple
5
+ from typing import Any, Callable, Dict, List, Mapping, Optional, Sequence, Tuple
6
6
 
7
7
  from pydantic import BaseModel
8
8
 
@@ -55,6 +55,18 @@ class OpenAPIValidationMiddleware(BaseMiddlewareHandler):
55
55
  ```
56
56
  """
57
57
 
58
+ def __init__(self, validation_serializer: Optional[Callable[[Any], str]] = None):
59
+ """
60
+ Initialize the OpenAPIValidationMiddleware.
61
+
62
+ Parameters
63
+ ----------
64
+ validation_serializer : Callable, optional
65
+ Optional serializer to use when serializing the response for validation.
66
+ Use it when you have a custom type that cannot be serialized by the default jsonable_encoder.
67
+ """
68
+ self._validation_serializer = validation_serializer
69
+
58
70
  def handler(self, app: EventHandlerInstance, next_middleware: NextMiddleware) -> Response:
59
71
  logger.debug("OpenAPIValidationMiddleware handler")
60
72
 
@@ -181,10 +193,11 @@ class OpenAPIValidationMiddleware(BaseMiddlewareHandler):
181
193
  exclude_unset=exclude_unset,
182
194
  exclude_defaults=exclude_defaults,
183
195
  exclude_none=exclude_none,
196
+ custom_serializer=self._validation_serializer,
184
197
  )
185
198
  else:
186
199
  # Just serialize the response content returned from the handler
187
- return jsonable_encoder(response_content)
200
+ return jsonable_encoder(response_content, custom_serializer=self._validation_serializer)
188
201
 
189
202
  def _prepare_response_content(
190
203
  self,
@@ -29,6 +29,7 @@ def jsonable_encoder( # noqa: PLR0911
29
29
  exclude_unset: bool = False,
30
30
  exclude_defaults: bool = False,
31
31
  exclude_none: bool = False,
32
+ custom_serializer: Optional[Callable[[Any], str]] = None,
32
33
  ) -> Any:
33
34
  """
34
35
  JSON encodes an arbitrary Python object into JSON serializable data types.
@@ -55,6 +56,8 @@ def jsonable_encoder( # noqa: PLR0911
55
56
  by default False
56
57
  exclude_none : bool, optional
57
58
  Whether fields that are equal to None should be excluded, by default False
59
+ custom_serializer : Callable, optional
60
+ A custom serializer to use for encoding the object, when everything else fails.
58
61
 
59
62
  Returns
60
63
  -------
@@ -134,6 +137,10 @@ def jsonable_encoder( # noqa: PLR0911
134
137
  if isinstance(obj, classes_tuple):
135
138
  return encoder(obj)
136
139
 
140
+ # Use custom serializer if present
141
+ if custom_serializer:
142
+ return custom_serializer(obj)
143
+
137
144
  # Default
138
145
  return _dump_other(
139
146
  obj=obj,
@@ -259,7 +266,7 @@ def _dump_other(
259
266
  exclude_defaults: bool = False,
260
267
  ) -> Any:
261
268
  """
262
- Dump an object to ah hashable object, using the same parameters as jsonable_encoder
269
+ Dump an object to a hashable object, using the same parameters as jsonable_encoder
263
270
  """
264
271
  try:
265
272
  data = dict(obj)
@@ -28,7 +28,7 @@ validation_error_definition = {
28
28
  "type": "array",
29
29
  "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
30
30
  },
31
- "msg": {"title": "Message", "type": "string"},
31
+ # For security reasons, we hide **msg** details (don't leak Python, Pydantic or filenames)
32
32
  "type": {"title": "Error Type", "type": "string"},
33
33
  },
34
34
  "required": ["loc", "msg", "type"],
@@ -580,7 +580,7 @@ class Logger:
580
580
  extra=extra,
581
581
  )
582
582
 
583
- def append_keys(self, **additional_keys) -> None:
583
+ def append_keys(self, **additional_keys: object) -> None:
584
584
  self.registered_formatter.append_keys(**additional_keys)
585
585
 
586
586
  def remove_keys(self, keys: Iterable[str]) -> None:
@@ -17,6 +17,7 @@ from aws_lambda_powertools.metrics.exceptions import (
17
17
  MetricValueError,
18
18
  SchemaValidationError,
19
19
  )
20
+ from aws_lambda_powertools.metrics.functions import convert_timestamp_to_emf_format, validate_emf_timestamp
20
21
  from aws_lambda_powertools.metrics.provider import cold_start
21
22
  from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
22
23
  from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
@@ -76,6 +77,8 @@ class MetricManager:
76
77
  self.namespace = resolve_env_var_choice(choice=namespace, env=os.getenv(constants.METRICS_NAMESPACE_ENV))
77
78
  self.service = resolve_env_var_choice(choice=service, env=os.getenv(constants.SERVICE_NAME_ENV))
78
79
  self.metadata_set = metadata_set if metadata_set is not None else {}
80
+ self.timestamp: int | None = None
81
+
79
82
  self._metric_units = [unit.value for unit in MetricUnit]
80
83
  self._metric_unit_valid_options = list(MetricUnit.__members__)
81
84
  self._metric_resolutions = [resolution.value for resolution in MetricResolution]
@@ -224,7 +227,7 @@ class MetricManager:
224
227
 
225
228
  return {
226
229
  "_aws": {
227
- "Timestamp": int(datetime.datetime.now().timestamp() * 1000), # epoch
230
+ "Timestamp": self.timestamp or int(datetime.datetime.now().timestamp() * 1000), # epoch
228
231
  "CloudWatchMetrics": [
229
232
  {
230
233
  "Namespace": self.namespace, # "test_namespace"
@@ -296,6 +299,31 @@ class MetricManager:
296
299
  else:
297
300
  self.metadata_set[str(key)] = value
298
301
 
302
+ def set_timestamp(self, timestamp: int | datetime.datetime):
303
+ """
304
+ Set the timestamp for the metric.
305
+
306
+ Parameters:
307
+ -----------
308
+ timestamp: int | datetime.datetime
309
+ The timestamp to create the metric.
310
+ If an integer is provided, it is assumed to be the epoch time in milliseconds.
311
+ If a datetime object is provided, it will be converted to epoch time in milliseconds.
312
+ """
313
+ # The timestamp must be a Datetime object or an integer representing an epoch time.
314
+ # This should not exceed 14 days in the past or be more than 2 hours in the future.
315
+ # Any metrics failing to meet this criteria will be skipped by Amazon CloudWatch.
316
+ # See: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html
317
+ # See: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CloudWatch-Logs-Monitoring-CloudWatch-Metrics.html
318
+ if not validate_emf_timestamp(timestamp):
319
+ warnings.warn(
320
+ "This metric doesn't meet the requirements and will be skipped by Amazon CloudWatch. "
321
+ "Ensure the timestamp is within 14 days past or 2 hours future.",
322
+ stacklevel=2,
323
+ )
324
+
325
+ self.timestamp = convert_timestamp_to_emf_format(timestamp)
326
+
299
327
  def clear_metrics(self) -> None:
300
328
  logger.debug("Clearing out existing metric set from memory")
301
329
  self.metric_set.clear()
@@ -576,6 +604,9 @@ def single_metric(
576
604
  Metric value
577
605
  namespace: str
578
606
  Namespace for metrics
607
+ default_dimensions: Dict[str, str], optional
608
+ Metric dimensions as key=value that will always be present
609
+
579
610
 
580
611
  Yields
581
612
  -------
@@ -0,0 +1,137 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime
4
+
5
+ from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import (
6
+ MetricResolutionError,
7
+ MetricUnitError,
8
+ )
9
+ from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
10
+ from aws_lambda_powertools.shared import constants
11
+ from aws_lambda_powertools.shared.types import List
12
+
13
+
14
+ def extract_cloudwatch_metric_resolution_value(metric_resolutions: List, resolution: int | MetricResolution) -> int:
15
+ """Return metric value from CloudWatch metric unit whether that's str or MetricResolution enum
16
+
17
+ Parameters
18
+ ----------
19
+ unit : Union[int, MetricResolution]
20
+ Metric resolution
21
+
22
+ Returns
23
+ -------
24
+ int
25
+ Metric resolution value must be 1 or 60
26
+
27
+ Raises
28
+ ------
29
+ MetricResolutionError
30
+ When metric resolution is not supported by CloudWatch
31
+ """
32
+ if isinstance(resolution, MetricResolution):
33
+ return resolution.value
34
+
35
+ if isinstance(resolution, int) and resolution in metric_resolutions:
36
+ return resolution
37
+
38
+ raise MetricResolutionError(
39
+ f"Invalid metric resolution '{resolution}', expected either option: {metric_resolutions}", # noqa: E501
40
+ )
41
+
42
+
43
+ def extract_cloudwatch_metric_unit_value(metric_units: List, metric_valid_options: List, unit: str | MetricUnit) -> str:
44
+ """Return metric value from CloudWatch metric unit whether that's str or MetricUnit enum
45
+
46
+ Parameters
47
+ ----------
48
+ unit : Union[str, MetricUnit]
49
+ Metric unit
50
+
51
+ Returns
52
+ -------
53
+ str
54
+ Metric unit value (e.g. "Seconds", "Count/Second")
55
+
56
+ Raises
57
+ ------
58
+ MetricUnitError
59
+ When metric unit is not supported by CloudWatch
60
+ """
61
+
62
+ if isinstance(unit, str):
63
+ if unit in metric_valid_options:
64
+ unit = MetricUnit[unit].value
65
+
66
+ if unit not in metric_units:
67
+ raise MetricUnitError(
68
+ f"Invalid metric unit '{unit}', expected either option: {metric_valid_options}",
69
+ )
70
+
71
+ if isinstance(unit, MetricUnit):
72
+ unit = unit.value
73
+
74
+ return unit
75
+
76
+
77
+ def validate_emf_timestamp(timestamp: int | datetime) -> bool:
78
+ """
79
+ Validates a given timestamp based on CloudWatch Timestamp guidelines.
80
+
81
+ Timestamp must meet CloudWatch requirements, otherwise an InvalidTimestampError will be raised.
82
+ See [Timestamps](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#about_timestamp)
83
+ for valid values.
84
+
85
+ Parameters:
86
+ ----------
87
+ timestamp: int | datetime
88
+ Datetime object or epoch time in milliseconds representing the timestamp to validate.
89
+
90
+ Returns
91
+ -------
92
+ bool
93
+ Valid or not timestamp values
94
+ """
95
+
96
+ if not isinstance(timestamp, (int, datetime)):
97
+ return False
98
+
99
+ if isinstance(timestamp, datetime):
100
+ # Converting timestamp to epoch time in milliseconds
101
+ timestamp = int(timestamp.timestamp() * 1000)
102
+
103
+ # Consider current timezone when working with date and time
104
+ current_timezone = datetime.now().astimezone().tzinfo
105
+
106
+ current_time = int(datetime.now(current_timezone).timestamp() * 1000)
107
+ min_valid_timestamp = current_time - constants.EMF_MAX_TIMESTAMP_PAST_AGE
108
+ max_valid_timestamp = current_time + constants.EMF_MAX_TIMESTAMP_FUTURE_AGE
109
+
110
+ return min_valid_timestamp <= timestamp <= max_valid_timestamp
111
+
112
+
113
+ def convert_timestamp_to_emf_format(timestamp: int | datetime) -> int:
114
+ """
115
+ Converts a timestamp to EMF compatible format.
116
+
117
+ Parameters
118
+ ----------
119
+ timestamp: int | datetime
120
+ The timestamp to convert. If already in epoch milliseconds format, returns it as is.
121
+ If datetime object, converts it to milliseconds since Unix epoch.
122
+
123
+ Returns:
124
+ --------
125
+ int
126
+ The timestamp converted to EMF compatible format (milliseconds since Unix epoch).
127
+ """
128
+ if isinstance(timestamp, int):
129
+ return timestamp
130
+
131
+ try:
132
+ return int(round(timestamp.timestamp() * 1000))
133
+ except AttributeError:
134
+ # If this point is reached, it indicates timestamp is not a datetime object
135
+ # Returning zero represents the initial date of epoch time,
136
+ # which will be skipped by Amazon CloudWatch.
137
+ return 0
@@ -125,6 +125,19 @@ class Metrics:
125
125
  def add_metadata(self, key: str, value: Any) -> None:
126
126
  self.provider.add_metadata(key=key, value=value)
127
127
 
128
+ def set_timestamp(self, timestamp: int):
129
+ """
130
+ Set the timestamp for the metric.
131
+
132
+ Parameters:
133
+ -----------
134
+ timestamp: int | datetime.datetime
135
+ The timestamp to create the metric.
136
+ If an integer is provided, it is assumed to be the epoch time in milliseconds.
137
+ If a datetime object is provided, it will be converted to epoch time in milliseconds.
138
+ """
139
+ self.provider.set_timestamp(timestamp=timestamp)
140
+
128
141
  def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None:
129
142
  self.provider.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics)
130
143
 
@@ -12,8 +12,10 @@ from typing import Any, Dict, List
12
12
  from aws_lambda_powertools.metrics.base import single_metric
13
13
  from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError
14
14
  from aws_lambda_powertools.metrics.functions import (
15
+ convert_timestamp_to_emf_format,
15
16
  extract_cloudwatch_metric_resolution_value,
16
17
  extract_cloudwatch_metric_unit_value,
18
+ validate_emf_timestamp,
17
19
  )
18
20
  from aws_lambda_powertools.metrics.provider.base import BaseProvider
19
21
  from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
@@ -73,6 +75,7 @@ class AmazonCloudWatchEMFProvider(BaseProvider):
73
75
  self.namespace = resolve_env_var_choice(choice=namespace, env=os.getenv(constants.METRICS_NAMESPACE_ENV))
74
76
  self.service = resolve_env_var_choice(choice=service, env=os.getenv(constants.SERVICE_NAME_ENV))
75
77
  self.metadata_set = metadata_set if metadata_set is not None else {}
78
+ self.timestamp: int | None = None
76
79
 
77
80
  self._metric_units = [unit.value for unit in MetricUnit]
78
81
  self._metric_unit_valid_options = list(MetricUnit.__members__)
@@ -231,7 +234,7 @@ class AmazonCloudWatchEMFProvider(BaseProvider):
231
234
 
232
235
  return {
233
236
  "_aws": {
234
- "Timestamp": int(datetime.datetime.now().timestamp() * 1000), # epoch
237
+ "Timestamp": self.timestamp or int(datetime.datetime.now().timestamp() * 1000), # epoch
235
238
  "CloudWatchMetrics": [
236
239
  {
237
240
  "Namespace": self.namespace, # "test_namespace"
@@ -304,6 +307,31 @@ class AmazonCloudWatchEMFProvider(BaseProvider):
304
307
  else:
305
308
  self.metadata_set[str(key)] = value
306
309
 
310
+ def set_timestamp(self, timestamp: int | datetime.datetime):
311
+ """
312
+ Set the timestamp for the metric.
313
+
314
+ Parameters:
315
+ -----------
316
+ timestamp: int | datetime.datetime
317
+ The timestamp to create the metric.
318
+ If an integer is provided, it is assumed to be the epoch time in milliseconds.
319
+ If a datetime object is provided, it will be converted to epoch time in milliseconds.
320
+ """
321
+ # The timestamp must be a Datetime object or an integer representing an epoch time.
322
+ # This should not exceed 14 days in the past or be more than 2 hours in the future.
323
+ # Any metrics failing to meet this criteria will be skipped by Amazon CloudWatch.
324
+ # See: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html
325
+ # See: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CloudWatch-Logs-Monitoring-CloudWatch-Metrics.html
326
+ if not validate_emf_timestamp(timestamp):
327
+ warnings.warn(
328
+ "This metric doesn't meet the requirements and will be skipped by Amazon CloudWatch. "
329
+ "Ensure the timestamp is within 14 days past or 2 hours future.",
330
+ stacklevel=2,
331
+ )
332
+
333
+ self.timestamp = convert_timestamp_to_emf_format(timestamp)
334
+
307
335
  def clear_metrics(self) -> None:
308
336
  logger.debug("Clearing out existing metric set from memory")
309
337
  self.metric_set.clear()
@@ -1,32 +1,17 @@
1
+ # Tracer constants
1
2
  TRACER_CAPTURE_RESPONSE_ENV: str = "POWERTOOLS_TRACER_CAPTURE_RESPONSE"
2
3
  TRACER_CAPTURE_ERROR_ENV: str = "POWERTOOLS_TRACER_CAPTURE_ERROR"
3
4
  TRACER_DISABLED_ENV: str = "POWERTOOLS_TRACE_DISABLED"
5
+ XRAY_SDK_MODULE: str = "aws_xray_sdk"
6
+ XRAY_SDK_CORE_MODULE: str = "aws_xray_sdk.core"
7
+ XRAY_TRACE_ID_ENV: str = "_X_AMZN_TRACE_ID"
8
+ MIDDLEWARE_FACTORY_TRACE_ENV: str = "POWERTOOLS_TRACE_MIDDLEWARES"
9
+ INVALID_XRAY_NAME_CHARACTERS = r"[?;*()!$~^<>]"
4
10
 
11
+ # Logger constants
5
12
  LOGGER_LOG_SAMPLING_RATE: str = "POWERTOOLS_LOGGER_SAMPLE_RATE"
6
13
  LOGGER_LOG_EVENT_ENV: str = "POWERTOOLS_LOGGER_LOG_EVENT"
7
14
  LOGGER_LOG_DEDUPLICATION_ENV: str = "POWERTOOLS_LOG_DEDUPLICATION_DISABLED"
8
-
9
- MIDDLEWARE_FACTORY_TRACE_ENV: str = "POWERTOOLS_TRACE_MIDDLEWARES"
10
-
11
- METRICS_NAMESPACE_ENV: str = "POWERTOOLS_METRICS_NAMESPACE"
12
-
13
- DATADOG_FLUSH_TO_LOG: str = "DD_FLUSH_TO_LOG"
14
-
15
- SERVICE_NAME_ENV: str = "POWERTOOLS_SERVICE_NAME"
16
- XRAY_TRACE_ID_ENV: str = "_X_AMZN_TRACE_ID"
17
- LAMBDA_TASK_ROOT_ENV: str = "LAMBDA_TASK_ROOT"
18
-
19
-
20
- LAMBDA_FUNCTION_NAME_ENV: str = "AWS_LAMBDA_FUNCTION_NAME"
21
-
22
- XRAY_SDK_MODULE: str = "aws_xray_sdk"
23
- XRAY_SDK_CORE_MODULE: str = "aws_xray_sdk.core"
24
-
25
- IDEMPOTENCY_DISABLED_ENV: str = "POWERTOOLS_IDEMPOTENCY_DISABLED"
26
-
27
- PARAMETERS_SSM_DECRYPT_ENV: str = "POWERTOOLS_PARAMETERS_SSM_DECRYPT"
28
- PARAMETERS_MAX_AGE_ENV: str = "POWERTOOLS_PARAMETERS_MAX_AGE"
29
-
30
15
  LOGGER_LAMBDA_CONTEXT_KEYS = [
31
16
  "function_arn",
32
17
  "function_memory_size",
@@ -35,17 +20,6 @@ LOGGER_LAMBDA_CONTEXT_KEYS = [
35
20
  "cold_start",
36
21
  "xray_trace_id",
37
22
  ]
38
-
39
- # JSON indentation level
40
- PRETTY_INDENT: int = 4
41
- COMPACT_INDENT = None
42
-
43
- POWERTOOLS_DEV_ENV: str = "POWERTOOLS_DEV"
44
- POWERTOOLS_DEBUG_ENV: str = "POWERTOOLS_DEBUG"
45
- POWERTOOLS_LOG_LEVEL_ENV: str = "POWERTOOLS_LOG_LEVEL"
46
- POWERTOOLS_LOG_LEVEL_LEGACY_ENV: str = "LOG_LEVEL"
47
- LAMBDA_LOG_LEVEL_ENV: str = "AWS_LAMBDA_LOG_LEVEL"
48
-
49
23
  # Mapping of Lambda log levels to Python logging levels
50
24
  # https://docs.aws.amazon.com/lambda/latest/dg/configuration-logging.html#configuration-logging-log-levels
51
25
  LAMBDA_ADVANCED_LOGGING_LEVELS = {
@@ -57,3 +31,37 @@ LAMBDA_ADVANCED_LOGGING_LEVELS = {
57
31
  "ERROR": "ERROR",
58
32
  "FATAL": "CRITICAL",
59
33
  }
34
+ POWERTOOLS_LOG_LEVEL_ENV: str = "POWERTOOLS_LOG_LEVEL"
35
+ POWERTOOLS_LOG_LEVEL_LEGACY_ENV: str = "LOG_LEVEL"
36
+ LAMBDA_LOG_LEVEL_ENV: str = "AWS_LAMBDA_LOG_LEVEL"
37
+
38
+ # Metrics constants
39
+ METRICS_NAMESPACE_ENV: str = "POWERTOOLS_METRICS_NAMESPACE"
40
+ DATADOG_FLUSH_TO_LOG: str = "DD_FLUSH_TO_LOG"
41
+ SERVICE_NAME_ENV: str = "POWERTOOLS_SERVICE_NAME"
42
+ # If the timestamp of log event is more than 2 hours in future, the log event is skipped.
43
+ # If the timestamp of log event is more than 14 days in past, the log event is skipped.
44
+ # See https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html
45
+ EMF_MAX_TIMESTAMP_PAST_AGE = 14 * 24 * 60 * 60 * 1000 # 14 days
46
+ EMF_MAX_TIMESTAMP_FUTURE_AGE = 2 * 60 * 60 * 1000 # 2 hours
47
+
48
+ # Parameters constants
49
+ PARAMETERS_SSM_DECRYPT_ENV: str = "POWERTOOLS_PARAMETERS_SSM_DECRYPT"
50
+ PARAMETERS_MAX_AGE_ENV: str = "POWERTOOLS_PARAMETERS_MAX_AGE"
51
+
52
+ # Runtime and environment constants
53
+ LAMBDA_TASK_ROOT_ENV: str = "LAMBDA_TASK_ROOT"
54
+ SAM_LOCAL_ENV: str = "AWS_SAM_LOCAL"
55
+ CHALICE_LOCAL_ENV: str = "AWS_CHALICE_CLI_MODE"
56
+ LAMBDA_FUNCTION_NAME_ENV: str = "AWS_LAMBDA_FUNCTION_NAME"
57
+
58
+ # Debug constants
59
+ POWERTOOLS_DEV_ENV: str = "POWERTOOLS_DEV"
60
+ POWERTOOLS_DEBUG_ENV: str = "POWERTOOLS_DEBUG"
61
+
62
+ # JSON constants
63
+ PRETTY_INDENT: int = 4
64
+ COMPACT_INDENT = None
65
+
66
+ # Idempotency constants
67
+ IDEMPOTENCY_DISABLED_ENV: str = "POWERTOOLS_IDEMPOTENCY_DISABLED"
@@ -4,6 +4,7 @@ import base64
4
4
  import itertools
5
5
  import logging
6
6
  import os
7
+ import re
7
8
  import warnings
8
9
  from binascii import Error as BinAsciiError
9
10
  from pathlib import Path
@@ -275,13 +276,10 @@ def abs_lambda_path(relative_path: str = "") -> str:
275
276
  If the path is empty, it will return the current working directory.
276
277
  """
277
278
  # Retrieve the LAMBDA_TASK_ROOT environment variable or default to an empty string
278
- current_working_directory = os.environ.get("LAMBDA_TASK_ROOT", "")
279
+ current_working_directory = os.environ.get("LAMBDA_TASK_ROOT", "") or str(Path.cwd())
279
280
 
280
- # If LAMBDA_TASK_ROOT is not set, use the current working directory
281
- if not current_working_directory:
282
- current_working_directory = str(Path.cwd())
281
+ return str(Path(current_working_directory, relative_path))
283
282
 
284
- # Combine the current working directory and the relative path to get the absolute path
285
- absolute_path = str(Path(current_working_directory, relative_path))
286
283
 
287
- return absolute_path
284
+ def sanitize_xray_segment_name(name: str) -> str:
285
+ return re.sub(constants.INVALID_XRAY_NAME_CHARACTERS, "", name)
@@ -1,3 +1,3 @@
1
1
  """Exposes version constant to avoid circular dependencies."""
2
2
 
3
- VERSION = "2.35.0"
3
+ VERSION = "2.36.0"