From 603cdced0820852f94c636c0eb5e8c741bd63249 Mon Sep 17 00:00:00 2001 From: Avin Date: Thu, 18 Jun 2026 02:12:09 -0700 Subject: [PATCH 01/76] fix(event-handler): handle CORS preflight OPTIONS in HttpResolverLocal (#8268) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(http-resolver): fix OPTIONS preflight returning 500 when CORS configured HttpResolverLocal overrode _resolve_async, _call_route_async, _run_middleware_chain_async, and _handle_not_found_async, duplicating the parent's logic without the CORS preflight branch. OPTIONS requests fell through to the not-found handler and, if a generic exception handler was registered, returned 500 with no CORS headers. Replace all four overrides with a single thin _resolve_async that delegates to super()._resolve_async() and serializes the returned ResponseBuilder to dict. The parent already handles route matching, CORS preflight (OPTIONS → 204), not-found, and exception handling correctly. Fixes #8267 Co-authored-by: Avin E M Co-authored-by: Leandro Damascena --- .../event_handler/http_resolver.py | 116 +--------- .../test_http_resolver.py | 216 ++++++++++++++++++ 2 files changed, 222 insertions(+), 110 deletions(-) diff --git a/aws_lambda_powertools/event_handler/http_resolver.py b/aws_lambda_powertools/event_handler/http_resolver.py index da72f6fca4d..6ec0b064974 100644 --- a/aws_lambda_powertools/event_handler/http_resolver.py +++ b/aws_lambda_powertools/event_handler/http_resolver.py @@ -1,7 +1,6 @@ from __future__ import annotations import base64 -import inspect import warnings from typing import TYPE_CHECKING, Any, Callable from urllib.parse import parse_qs @@ -10,10 +9,7 @@ ApiGatewayResolver, BaseRouter, ProxyEventType, - Response, - Route, ) -from aws_lambda_powertools.event_handler.middlewares.async_utils import wrap_middleware_async from aws_lambda_powertools.shared.headers_serializer import BaseHeadersSerializer from aws_lambda_powertools.utilities.data_classes.common import BaseProxyEvent @@ -240,113 +236,13 @@ def _get_base_path(self) -> str: return "" async def _resolve_async(self) -> dict: # type: ignore[override] - """Async version of resolve that supports async handlers.""" - method = self.current_event.http_method.upper() - path = self._remove_prefix(self.current_event.path) - - registered_routes = self._static_routes + self._dynamic_routes - - for route in registered_routes: - if method != route.method: - continue - match_results = route.rule.match(path) - if match_results: - self.append_context(_route=route, _path=path) - route_keys = self._convert_matches_into_route_keys(match_results) - return await self._call_route_async(route, route_keys) - - # Handle not found - return await self._handle_not_found_async() - - async def _call_route_async(self, route: Route, route_arguments: dict[str, str]) -> dict: # type: ignore[override] - """Call route handler, supporting both sync and async handlers.""" - from aws_lambda_powertools.event_handler.api_gateway import ResponseBuilder - - try: - self._reset_processed_stack() - - # Get the route args (may be modified by validation middleware) - self.append_context(_route_args=route_arguments) - - # Run middleware chain (sync for now, handlers can be async) - response = await self._run_middleware_chain_async(route) - - response_builder: ResponseBuilder = ResponseBuilder( - response=response, - serializer=self._serializer, - route=route, - ) - - return response_builder.build(self.current_event, self._cors) - - except Exception as exc: - exc_response_builder = self._call_exception_handler(exc, route) - if exc_response_builder: - return exc_response_builder.build(self.current_event, self._cors) - raise - - async def _run_middleware_chain_async(self, route: Route) -> Response: - """Run the middleware chain, awaiting async handlers.""" - # Build middleware list - all_middlewares: list[Callable[..., Any]] = [] - - # Determine if validation should be enabled for this route - # If route has explicit enable_validation setting, use it; otherwise, use resolver's global setting - route_validation_enabled = ( - route.enable_validation if route.enable_validation is not None else self._enable_validation - ) - - if route_validation_enabled and hasattr(self, "_request_validation_middleware"): - all_middlewares.append(self._request_validation_middleware) - - all_middlewares.extend(self._router_middlewares + route.middlewares) - - if route_validation_enabled and hasattr(self, "_response_validation_middleware"): - all_middlewares.append(self._response_validation_middleware) - - # Create the final handler that calls the route function - async def final_handler(app): - route_args = app.context.get("_route_args", {}) - result = route.func(**route_args) - - # Await if coroutine - if inspect.iscoroutine(result): - result = await result - - return self._to_response(result) - - # Build middleware chain from end to start - next_handler = final_handler - - for middleware in reversed(all_middlewares): - next_handler = wrap_middleware_async(middleware, next_handler) - - return await next_handler(self) - - async def _handle_not_found_async(self, method: str = "", path: str = "") -> dict: # type: ignore[override] - """Handle 404 responses, using custom not_found handler if registered.""" - from http import HTTPStatus - - from aws_lambda_powertools.event_handler.api_gateway import ResponseBuilder - from aws_lambda_powertools.event_handler.exceptions import NotFoundError - - # Check for custom not_found handler - custom_not_found_handler = self.exception_handler_manager.lookup_exception_handler(NotFoundError) - if custom_not_found_handler: - response = custom_not_found_handler(NotFoundError()) - else: - response = Response( - status_code=HTTPStatus.NOT_FOUND.value, - content_type="application/json", - body={"statusCode": HTTPStatus.NOT_FOUND.value, "message": "Not found"}, - ) - - response_builder: ResponseBuilder = ResponseBuilder( - response=response, - serializer=self._serializer, - route=None, - ) + """Thin async resolver: delegates entirely to the parent and serializes to dict. + The parent's _resolve_async handles route matching, CORS preflight, not-found + logic, and exception handling. The only adaptation needed here is converting + the returned ResponseBuilder into the dict format that asgi_handler expects. + """ + response_builder = await super()._resolve_async() return response_builder.build(self.current_event, self._cors) async def asgi_handler(self, scope: dict, receive: Callable, send: Callable) -> None: diff --git a/tests/functional/event_handler/required_dependencies/test_http_resolver.py b/tests/functional/event_handler/required_dependencies/test_http_resolver.py index 40fb3d20c64..ada85cf59fc 100644 --- a/tests/functional/event_handler/required_dependencies/test_http_resolver.py +++ b/tests/functional/event_handler/required_dependencies/test_http_resolver.py @@ -1242,3 +1242,219 @@ def hello(): # THEN it returns 404 (method mismatch is treated as not found) assert captured["status_code"] == 404 + + +# ============================================================================= +# CORS Tests (issue #8267) +# ============================================================================= + + +@pytest.mark.asyncio +async def test_cors_options_preflight_returns_204(): + # GIVEN an app with CORSConfig and a POST route + from aws_lambda_powertools.event_handler.api_gateway import CORSConfig + + app = HttpResolverLocal(cors=CORSConfig(allow_origin="*")) + + @app.post("/items") + def create_item(): + return {"ok": True} + + # WHEN a browser sends a CORS preflight OPTIONS request + scope = { + "type": "http", + "method": "OPTIONS", + "path": "/items", + "query_string": b"", + "headers": [ + (b"origin", b"http://localhost:3000"), + (b"access-control-request-method", b"POST"), + ], + } + + receive = make_asgi_receive() + captured: dict[str, Any] = {"status_code": None, "headers": []} + + async def send(message: dict[str, Any]) -> None: + await asyncio.sleep(0) + if message["type"] == "http.response.start": + captured["status_code"] = message["status"] + captured["headers"].extend(message.get("headers", [])) + + await app(scope, receive, send) + + # THEN it returns 204 with CORS headers (not 500 or 404) + assert captured["status_code"] == 204 + + header_names = [name.lower() for name, _ in captured["headers"]] + assert b"access-control-allow-origin" in header_names + assert b"access-control-allow-methods" in header_names + + +@pytest.mark.asyncio +async def test_cors_options_preflight_with_exception_handler_does_not_return_500(): + # GIVEN an app with CORSConfig and a generic exception handler that returns 500 + import json + + from aws_lambda_powertools.event_handler.api_gateway import CORSConfig + + app = HttpResolverLocal(cors=CORSConfig(allow_origin="*")) + + @app.post("/items") + def create_item(): + return {"ok": True} + + @app.exception_handler(Exception) + def handle_server_error(ex: Exception): + return Response( + status_code=500, + content_type="application/json", + body=json.dumps({"error": "internal"}), + ) + + # WHEN a browser sends a CORS preflight OPTIONS request + scope = { + "type": "http", + "method": "OPTIONS", + "path": "/items", + "query_string": b"", + "headers": [ + (b"origin", b"http://localhost:3000"), + (b"access-control-request-method", b"POST"), + ], + } + + receive = make_asgi_receive() + captured: dict[str, Any] = {"status_code": None, "headers": []} + + async def send(message: dict[str, Any]) -> None: + await asyncio.sleep(0) + if message["type"] == "http.response.start": + captured["status_code"] = message["status"] + captured["headers"].extend(message.get("headers", [])) + + await app(scope, receive, send) + + # THEN the OPTIONS request returns 204, not 500 + assert captured["status_code"] == 204 + header_names = [name.lower() for name, _ in captured["headers"]] + assert b"access-control-allow-origin" in header_names + + +@pytest.mark.asyncio +async def test_no_cors_options_returns_404(): + # GIVEN an app WITHOUT CORSConfig + app = HttpResolverLocal() + + @app.post("/items") + def create_item(): + return {"ok": True} + + # WHEN a browser sends an OPTIONS request (no CORS configured) + scope = { + "type": "http", + "method": "OPTIONS", + "path": "/items", + "query_string": b"", + "headers": [], + } + + receive = make_asgi_receive() + send, captured = make_asgi_send() + + await app(scope, receive, send) + + # THEN it returns 404 (no CORS config, no special handling) + assert captured["status_code"] == 404 + + +@pytest.mark.asyncio +async def test_cors_options_includes_allowed_methods_header(): + # GIVEN an app with CORSConfig and multiple routes + from aws_lambda_powertools.event_handler.api_gateway import CORSConfig + + app = HttpResolverLocal(cors=CORSConfig(allow_origin="https://example.com")) + + @app.get("/resource") + def get_resource(): + return {"method": "GET"} + + @app.post("/resource") + def post_resource(): + return {"method": "POST"} + + # WHEN an OPTIONS preflight is sent + scope = { + "type": "http", + "method": "OPTIONS", + "path": "/resource", + "query_string": b"", + "headers": [ + (b"origin", b"https://example.com"), + (b"access-control-request-method", b"GET"), + ], + } + + receive = make_asgi_receive() + captured: dict[str, Any] = {"status_code": None, "headers": []} + + async def send(message: dict[str, Any]) -> None: + await asyncio.sleep(0) + if message["type"] == "http.response.start": + captured["status_code"] = message["status"] + captured["headers"].extend(message.get("headers", [])) + + await app(scope, receive, send) + + # THEN 204 is returned with Access-Control-Allow-Methods header + assert captured["status_code"] == 204 + allow_methods_headers = [v for name, v in captured["headers"] if name.lower() == b"access-control-allow-methods"] + assert len(allow_methods_headers) == 1 + + +@pytest.mark.asyncio +async def test_cors_disallowed_header_not_in_allow_headers(): + # GIVEN an app with CORSConfig that only allows specific headers + from aws_lambda_powertools.event_handler.api_gateway import CORSConfig + + app = HttpResolverLocal(cors=CORSConfig(allow_origin="*", allow_headers=["X-Custom-Allowed"])) + + @app.post("/items") + def create_item(): + return {"ok": True} + + # WHEN a preflight requests an unlisted header + scope = { + "type": "http", + "method": "OPTIONS", + "path": "/items", + "query_string": b"", + "headers": [ + (b"origin", b"http://localhost:3000"), + (b"access-control-request-method", b"POST"), + (b"access-control-request-headers", b"X-Not-Allowed"), + ], + } + + receive = make_asgi_receive() + captured: dict[str, Any] = {"status_code": None, "headers": []} + + async def send(message: dict[str, Any]) -> None: + await asyncio.sleep(0) + if message["type"] == "http.response.start": + captured["status_code"] = message["status"] + captured["headers"].extend(message.get("headers", [])) + + await app(scope, receive, send) + + # THEN the server still returns 204 (browser enforces the rejection, not the server) + assert captured["status_code"] == 204 + + # AND the unlisted header is absent from Access-Control-Allow-Headers + allow_headers_value = next( + (v.decode() for name, v in captured["headers"] if name.lower() == b"access-control-allow-headers"), + "", + ) + assert "X-Not-Allowed" not in allow_headers_value + # AND the explicitly allowed header IS present + assert "X-Custom-Allowed" in allow_headers_value From e0e2b4bb4fbfe85120289379e94ba4a705e0a67d Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 18 Jun 2026 11:26:59 +0200 Subject: [PATCH 02/76] chore(deps): consolidate Dependabot dependency updates (#8285) * chore(deps-dev): bump aws-cdk in the aws-cdk group Bumps the aws-cdk group with 1 update: [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `aws-cdk` from 2.1126.0 to 2.1127.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1127.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1127.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump ty from 0.0.35 to 0.0.49 Bumps [ty](https://github.com/astral-sh/ty) from 0.0.35 to 0.0.49. - [Release notes](https://github.com/astral-sh/ty/releases) - [Changelog](https://github.com/astral-sh/ty/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ty/compare/0.0.35...0.0.49) --- updated-dependencies: - dependency-name: ty dependency-version: 0.0.49 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps): bump aws-powertools/actions in the github-actions group Bumps the github-actions group with 1 update: [aws-powertools/actions](https://github.com/aws-powertools/actions). Updates `aws-powertools/actions` from 1.5.1 to 1.5.2 - [Release notes](https://github.com/aws-powertools/actions/releases) - [Commits](https://github.com/aws-powertools/actions/compare/828e78a26eee3554dc2e1d96048004548fbb169f...4bf64a4072489399fbf39b78f558eeeed6767189) --- updated-dependencies: - dependency-name: aws-powertools/actions dependency-version: 1.5.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] * chore(deps): bump valkey-glide from 2.3.1 to 2.4.1 Bumps [valkey-glide](https://github.com/valkey-io/valkey-glide) from 2.3.1 to 2.4.1. - [Release notes](https://github.com/valkey-io/valkey-glide/releases) - [Changelog](https://github.com/valkey-io/valkey-glide/blob/main/CHANGELOG.md) - [Commits](https://github.com/valkey-io/valkey-glide/compare/v2.3.1...v2.4.1) --- updated-dependencies: - dependency-name: valkey-glide dependency-version: 2.4.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump boto3-stubs from 1.43.24 to 1.43.29 Bumps [boto3-stubs](https://github.com/youtype/mypy_boto3_builder) from 1.43.24 to 1.43.29. - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) --- updated-dependencies: - dependency-name: boto3-stubs dependency-version: 1.43.29 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump cdklabs-generative-ai-cdk-constructs Bumps [cdklabs-generative-ai-cdk-constructs](https://github.com/awslabs/generative-ai-cdk-constructs) from 0.1.317 to 0.1.318. - [Release notes](https://github.com/awslabs/generative-ai-cdk-constructs/releases) - [Changelog](https://github.com/awslabs/generative-ai-cdk-constructs/blob/main/CHANGELOG.md) - [Commits](https://github.com/awslabs/generative-ai-cdk-constructs/commits) --- updated-dependencies: - dependency-name: cdklabs-generative-ai-cdk-constructs dependency-version: 0.1.318 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix(data_classes): align DictWrapper.get signature with Mapping protocol ty 0.0.49 enforces LSP checks on Mapping.get which requires `key: object`. Widen parameter type and coerce to str internally for dict lookup. Co-Authored-By: Claude Opus 4.6 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 --- .github/workflows/bootstrap_region.yml | 2 +- .../utilities/data_classes/common.py | 4 +- package-lock.json | 8 +- package.json | 2 +- poetry.lock | 134 +++++++++--------- pyproject.toml | 2 +- 6 files changed, 76 insertions(+), 76 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index 96911a8c9b7..2f095a63a51 100644 --- a/.github/workflows/bootstrap_region.yml +++ b/.github/workflows/bootstrap_region.yml @@ -52,7 +52,7 @@ jobs: with: node-version: "22" - name: Setup dependencies - uses: aws-powertools/actions/.github/actions/cached-node-modules@828e78a26eee3554dc2e1d96048004548fbb169f + uses: aws-powertools/actions/.github/actions/cached-node-modules@4bf64a4072489399fbf39b78f558eeeed6767189 - id: credentials name: AWS Credentials uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index c35a02cc3ce..3b9171b286d 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -163,8 +163,8 @@ def _str_helper(self) -> dict[str, Any]: def _properties(self) -> list[str]: return [p for p in dir(self.__class__) if isinstance(getattr(self.__class__, p), property)] - def get(self, key: str, default: Any | None = None) -> Any | None: - return self._data.get(key, default) + def get(self, key: object, default: Any | None = None) -> Any | None: # type: ignore[override] + return self._data.get(str(key), default) @property def raw_event(self) -> dict[str, Any]: diff --git a/package-lock.json b/package-lock.json index f0b022384df..ae5bec54f57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,13 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1126.0" + "aws-cdk": "^2.1127.0" } }, "node_modules/aws-cdk": { - "version": "2.1126.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1126.0.tgz", - "integrity": "sha512-uNoocb3vCPiAT3j9+SwL6pn/VVggHWBsgC2XpxyhNvYQYt6cE9BM/149GWwtdcwnLrPjnwW1+CV/5nSSh5dV+w==", + "version": "2.1127.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1127.0.tgz", + "integrity": "sha512-/6pUD6+cp3ObwItYEHXF+O+cUCtsKmCoeerCXA/xAfELAAJbdlu36Zx+LJZGbF32aO4xdk3zlH3F7rY657js3g==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 42de5c30465..199876efbd7 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1126.0" + "aws-cdk": "^2.1127.0" } } diff --git a/poetry.lock b/poetry.lock index 1bafb91820d..f431e0c0bb6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -498,14 +498,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "boto3-stubs" -version = "1.43.24" -description = "Type annotations for boto3 1.43.24 generated with mypy-boto3-builder 8.12.0" +version = "1.43.29" +description = "Type annotations for boto3 1.43.29 generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "boto3_stubs-1.43.24-py3-none-any.whl", hash = "sha256:d5d8c00769d46970efedbbe24fb99c26568dfa4cc12a9acb2ddba8667160dcc1"}, - {file = "boto3_stubs-1.43.24.tar.gz", hash = "sha256:1b60837a40179f668a6b2f5206fd67acb4bf636aff2cd401f84fcf651cb4c988"}, + {file = "boto3_stubs-1.43.29-py3-none-any.whl", hash = "sha256:6c4d1766c3b310d23c107a4bd437e139181c17492a468f62cc2a89dbcd7becf3"}, + {file = "boto3_stubs-1.43.29.tar.gz", hash = "sha256:4d7829eca11f02a652d72b353fbd81a5192ae55d9f7425b81d102a51f01d8e58"}, ] [package.dependencies] @@ -577,7 +577,7 @@ bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime ( bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)"] billing = ["mypy-boto3-billing (>=1.43.0,<1.44.0)"] billingconductor = ["mypy-boto3-billingconductor (>=1.43.0,<1.44.0)"] -boto3 = ["boto3 (==1.43.24)"] +boto3 = ["boto3 (==1.43.29)"] braket = ["mypy-boto3-braket (>=1.43.0,<1.44.0)"] budgets = ["mypy-boto3-budgets (>=1.43.0,<1.44.0)"] ce = ["mypy-boto3-ce (>=1.43.0,<1.44.0)"] @@ -1055,14 +1055,14 @@ typeguard = "2.13.3" [[package]] name = "cdklabs-generative-ai-cdk-constructs" -version = "0.1.317" +version = "0.1.318" description = "AWS Generative AI CDK Constructs is a library for well-architected generative AI patterns." optional = false python-versions = "~=3.10" groups = ["dev"] files = [ - {file = "cdklabs_generative_ai_cdk_constructs-0.1.317-py3-none-any.whl", hash = "sha256:86359377bbb56c946a460b0b7244ad5f9b8be3ab290201ad2e197fc7a6628dfb"}, - {file = "cdklabs_generative_ai_cdk_constructs-0.1.317.tar.gz", hash = "sha256:e04ed66168736f65cc4d13449a719dbb8d84c7ffb054d22a034865918315d157"}, + {file = "cdklabs_generative_ai_cdk_constructs-0.1.318-py3-none-any.whl", hash = "sha256:1a6717eeaf2b86cf1a60965eba52cf875355427c4de5ebded0b6d34c83182753"}, + {file = "cdklabs_generative_ai_cdk_constructs-0.1.318.tar.gz", hash = "sha256:bc685eeb633142abb7ffed4a90f029aec8e10ada8e63b99398b13f21b4d81f6f"}, ] [package.dependencies] @@ -4663,30 +4663,30 @@ files = [ [[package]] name = "ty" -version = "0.0.35" +version = "0.0.49" description = "An extremely fast Python type checker, written in Rust." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "ty-0.0.35-py3-none-linux_armv6l.whl", hash = "sha256:85ae1e59b9fb0b40e9d84fe61b29653c5f2f5e78b487ece371a7a38c20c781cf"}, - {file = "ty-0.0.35-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:709dbb7af4fcadb1196863c00b8791bbbbcc9dacbe15a0ff17f0af82b35d415b"}, - {file = "ty-0.0.35-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2cb0877419ab0c8708b6925cb0c2800b263842bd3c425113f200538772f3a0cc"}, - {file = "ty-0.0.35-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7afbcfc61904b7e82e7fe1a1db832a40d8f01e69dee1775f6594e552980536c"}, - {file = "ty-0.0.35-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b61498cc3e4178031c079951257fbdb209a891b4feb10ad6c40f615a51846f41"}, - {file = "ty-0.0.35-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:573b1eacda349fc8dba0d767b41631c3a6f66412363127c5bf2b1b40a1d898d2"}, - {file = "ty-0.0.35-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7209746158d6393c1040aa64b3ca29622e212ea7d8bae22ba50dbcbb4f96f0a"}, - {file = "ty-0.0.35-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4466a1470aa4418d49a9aa45d9da7de42033addd0a2837c5b2b0eb71d3c2bcd3"}, - {file = "ty-0.0.35-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb44bb742d52c309dcaa6598bcf4d82eb4bf1241b9e4940461e522e30093fe8b"}, - {file = "ty-0.0.35-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:34b219250736c989b2670a03782c61315f523f3a2be37f1f90b1207e2212c188"}, - {file = "ty-0.0.35-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:88e2ac497decc0940ef1a07571dee8a746112a93a09cdc7f8bca0099752e2e05"}, - {file = "ty-0.0.35-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:02cae51b53e6ec17d5d827ff1a3a76fd119705b56a92156e04399eda6e911596"}, - {file = "ty-0.0.35-py3-none-musllinux_1_2_i686.whl", hash = "sha256:11871d730c9400d899ac0b9f3d660ed2e7e433377c8725549f8250a36a7f2620"}, - {file = "ty-0.0.35-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ad0a2f0530d0933dcc99ad36ac556c63e384ea72ab9a18d23ad2e2c9fd61c73"}, - {file = "ty-0.0.35-py3-none-win32.whl", hash = "sha256:0e25d63ec4ab116e7f6757e44d16ca9216bca679d19ecc36d119cf80faada61a"}, - {file = "ty-0.0.35-py3-none-win_amd64.whl", hash = "sha256:6a0a6d259f6f2f8f2f954c6f013d4e0b5eba68af6b353bf19a47d59ec254a3d5"}, - {file = "ty-0.0.35-py3-none-win_arm64.whl", hash = "sha256:619c52c0fb2aa21961a848a1995135ad3b6d0a9aa54da0194e60f679cc200e13"}, - {file = "ty-0.0.35.tar.gz", hash = "sha256:8375c240ab38138a19db07996c9808fb7a92047c1492e1ce587c2ef5112ad3a9"}, + {file = "ty-0.0.49-py3-none-linux_armv6l.whl", hash = "sha256:12c0c4310b936d762a8586c210b53d4fa4bb361a04429afa89bf84b922e5e065"}, + {file = "ty-0.0.49-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:737bfdc2caf9712a8580944dcdc80a450a37a4f2bc83c8fa9b7433b374f9e471"}, + {file = "ty-0.0.49-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ab90c1baf3b1701d282fce4b02fa552a962d109f8972c46ef6b22429503bfea4"}, + {file = "ty-0.0.49-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ce8ecf6ba6fc79bd137cc0557a754f7e5f2dfe9436412551d480d680e248ad"}, + {file = "ty-0.0.49-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:10d85c6865c984e78661e0bd20b180514b4a289739224e84816e342bdf381e04"}, + {file = "ty-0.0.49-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d96a67a206619e01fa92f35a22267ec634bba62be24b1d0e947020cc179995b"}, + {file = "ty-0.0.49-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3de9f648564e0a66344ef397770387cb0d093735f8679d2c5a08a4741e79814d"}, + {file = "ty-0.0.49-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5779179ab397d15f8c9dbb8f506ec1b1745f54eac639982f76ef3ce538943b50"}, + {file = "ty-0.0.49-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792d4974e93cc09bd32f934586080bbbe21b8e777099cb521cb2de18b68a49f0"}, + {file = "ty-0.0.49-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:727bda86deb136073e525c2e78d60e38aedcce5d80579170844a52bbf7c1440d"}, + {file = "ty-0.0.49-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4f2fc2bc4a8d2ff1cca59fd94772cabdfec4062d47a0b3a0784be46d94d0540b"}, + {file = "ty-0.0.49-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3724bd9badef333321578b6a941fbc571ebf49141ec2356a8590fbe4c9aa588d"}, + {file = "ty-0.0.49-py3-none-musllinux_1_2_i686.whl", hash = "sha256:166c6eb52ee4af3c5a9bb267d165d93000daa55c6758cd8ff3199741fb75917d"}, + {file = "ty-0.0.49-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:91e81d832c287b05782ee32eb1b801f62c1fa08df37d589d2b88c3f1d51c9731"}, + {file = "ty-0.0.49-py3-none-win32.whl", hash = "sha256:7186af5ca9829d1f5d8916bcf767b8e819bfbf61b1b8ec843bb3fc699cb502e1"}, + {file = "ty-0.0.49-py3-none-win_amd64.whl", hash = "sha256:ae2142fc126a01effcca0c222908b0e6654b5ba1266d4e4d406e4866aef8e1d1"}, + {file = "ty-0.0.49-py3-none-win_arm64.whl", hash = "sha256:75d5e2e7649765f31f4bed6c8adb149a75b18edd3fa6336dac4d0efc1a66466f"}, + {file = "ty-0.0.49.tar.gz", hash = "sha256:0a027bd0c9c75d035641a365d087ad883446057f9be0b9826251c2aecafbf145"}, ] [[package]] @@ -4963,55 +4963,55 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "valkey-glide" -version = "2.3.1" +version = "2.4.1" description = "Valkey GLIDE Async client. Supports Valkey and Redis OSS." optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"valkey\"" files = [ - {file = "valkey_glide-2.3.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:736a3e58393fa4f0f2fbb10031d46da5f18ebb8e72d2f9428ff24f0f6addeb3f"}, - {file = "valkey_glide-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b2cd6f5c4e9b67b78873f34f19b9182bab5b07a9151855cf059303e05dac3b2f"}, - {file = "valkey_glide-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ddf70bc7888d565273e4bf858ff6047d5284140ff380a732f807c775be8e108"}, - {file = "valkey_glide-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f947dd44ba9741eadcab154443f447c19f23dab56de33f56d5f133ee0d597c2"}, - {file = "valkey_glide-2.3.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6ddc4c6bee1a9c102f003cddc5d1bad8173a9d90e1c9a0f73a285228ed8625af"}, - {file = "valkey_glide-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30590532136e4ea38b6a6389cbcfe4edc554418563c6e4f6357b0749907b2c20"}, - {file = "valkey_glide-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bbdb7baa7aac12c109aefd97f69f9780a4812429db18786254ef288ecf75f19"}, - {file = "valkey_glide-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fd64d77ae26efd524be58456e22636ce4cb0a6110ad722e89f249a45d098692"}, - {file = "valkey_glide-2.3.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:406b73f5ee080406fbfeda542d37de7e330fb4d83b0aa7212b92707d7b7b82a6"}, - {file = "valkey_glide-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0940d4069cbc4896dec3a1ab39db7bf86667fb32892df4dbf3b043129d26d6e5"}, - {file = "valkey_glide-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b47de0ec3d5a253c2b37d33266aaeb22503014f9e8f0611ba999e06f9804966a"}, - {file = "valkey_glide-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a364210002dd0e7c3362299f61a2a1cacf867594a8a0bbf157a345f3f40d4d94"}, - {file = "valkey_glide-2.3.1-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:86d56756842acd6286601128822c5f1f9dcd61305f0c6a80c3e7fb3a7e0404ef"}, - {file = "valkey_glide-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b307795a23473b8e7cff781eb54936cc672a430820f5fa71c6b6fb3748cc1189"}, - {file = "valkey_glide-2.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb570f5d637ee55300ccdecd39a51cbf25c67ab6e25f2022d42f32a7bec6163"}, - {file = "valkey_glide-2.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:506c7800eec05caf17136645cc642941a9536578f4d6733845e7d0ed36ed4e3e"}, - {file = "valkey_glide-2.3.1-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:3d6626e6f9ddfa7f8706023e167b4a2eca8a0f7b7fee1d30f91a83b4811349e4"}, - {file = "valkey_glide-2.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3466a0c113a951d722036704795ff0377eef11a44ab224472f98d99ac2c5ef28"}, - {file = "valkey_glide-2.3.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe53e4808bdac5b4e6482c66583e1980ecf75666b4e4d0984d89e8b693026543"}, - {file = "valkey_glide-2.3.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1a9662885ea8f3df97a6d873131dea983d42e4735750af368fe2d47e7e44f0c"}, - {file = "valkey_glide-2.3.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7cd8c7d52411d8add7640eb4982942e0fd0154db5d010e3a8094ae028f91d136"}, - {file = "valkey_glide-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b3037c5d477172d82ae443f1fbc664dba04a0184efd5a227d541cdf06be478f"}, - {file = "valkey_glide-2.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcac3e3064de88c57042eaa34980c6f35c8c09138148cceafd7dddbd830602ea"}, - {file = "valkey_glide-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1de33b66aba099e3f17199da4edefbeb38c91349a6c0d958581fa77be3475140"}, - {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5533a090953fd6af4c07b80bd042231540fbd1ede95fff42614750b435f01184"}, - {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f814ad759e9fdc6c5ced18ddba38cc2a3badb2839ce3555ec9b44beb794096e4"}, - {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dc6dea7ce627a8b166d33232aa7bc7f8dd9d224870235a560bc5d1c4ccec8cb"}, - {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1e135bb43e50b1cd6558d93b3108c40a79ce8dc119de883cebb7458d470f629"}, - {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:993c9bffde847fa3d36c6f11e5e50872dd491f245850d7c6ae1bbb8db5bff346"}, - {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:918ce3b8a2a3602e82d03f254bad5cc5bd1398eb84dec8eef77aefccc039bd5d"}, - {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28d4cbf00b07db273214488f17d59232baaddd0cc30c26064cf3bf384b03e9cd"}, - {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d93ef822a524c8f18c1b750f061373d95e842005116ebcf832d166533bf2bc2"}, - {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f66459238f68b165d6b3b8c1a0cb48e63ce291afa82e82f029dbd37b7b27099b"}, - {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7bc45d65196d03f8651a4f40d5be5faf6925edb3d8d37cc57a79fd555f70c368"}, - {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:115bd85a443fec57d12094aa8ae627a718df64044a978bc4d407f82a29db4c83"}, - {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beb25b2445e9be63784e67200fdf708694e842f3a6e93530fe974200411dfaf4"}, - {file = "valkey_glide-2.3.1.tar.gz", hash = "sha256:f4bae030c0aa6e55edb2c27dbd55f82cfb5f581904fff1318eec1c062f30d4b3"}, + {file = "valkey_glide-2.4.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:91c7ab69c121b28a21b3e36a084a792dfc21be7221a667c535dc7f36d4fb0e4b"}, + {file = "valkey_glide-2.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:68a4fa31431927f43d1fe7a34809ed3cde9a437d7ac7ec5af51871e4cf272edb"}, + {file = "valkey_glide-2.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f37d059d71520ac1bd25469cd4b67d87ea8cab995cc25af48d83d19469fd3048"}, + {file = "valkey_glide-2.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:927b85451f54e56e6469c321cf672f7ce47c597bf1c480dd1925f07d8c6b1971"}, + {file = "valkey_glide-2.4.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:d7285d03c2df040f26874b7f4ae96f040da2daecc9a34fa99da6f4e6ce5149c8"}, + {file = "valkey_glide-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d2e82b74127897ccb7a957ad455787816a75fdc8c60a5e8004aef65ea93e99c"}, + {file = "valkey_glide-2.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4094128cb07e06e87013b7afab1e9388f8f5aeebe48ea6cbd54de15bd772e644"}, + {file = "valkey_glide-2.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f8dc0f3a36adb1cbe4e167972ca4758acdfed6baf58a4db94bbb713df56c8f5"}, + {file = "valkey_glide-2.4.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:5f8df64f6a4f0fd7203113103101fdf0aaa7ff0e7557312611de11ab89c6db75"}, + {file = "valkey_glide-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b45e35f44c17e88f8cd8082f8d8061a9763238c44ef20b11b615f6d87235864a"}, + {file = "valkey_glide-2.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf812b498925a30abab6e1a9f82f5eb821e967904fe7724729b2c82c47e29edf"}, + {file = "valkey_glide-2.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:214e2faca98966eea3eaf9e09de616862423815a5059843a9884125e2427a344"}, + {file = "valkey_glide-2.4.1-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:c18976553ba663c03f7cc18c7e6075f4cbd2236c18b051e3d55bb213c6c44cb4"}, + {file = "valkey_glide-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:43006e19cd63d66051263fa34a8ad47ba7d08a199585689b3f12f56ed6c9a005"}, + {file = "valkey_glide-2.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b652a2a62aad87738e8f0e0aa5bf660ba91449c9fdb88550ccbc42e5fec08fe7"}, + {file = "valkey_glide-2.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd27d26947fd9f1b6e9eaf0abce4bccfde779c1e618b310c4d725424b609793"}, + {file = "valkey_glide-2.4.1-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:91fb7ff97acdabc8f641255b548a48627bb731e65037b1126745bf8a0022e87d"}, + {file = "valkey_glide-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d49a2537c2de44b0fc57691b1ae6c3d6f481e6f7f7eb879c0d28921d0aaec67d"}, + {file = "valkey_glide-2.4.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cded9f14e448da5a96f61c066395f2c7e2846f2afe74cacc8634da0ae0c3425f"}, + {file = "valkey_glide-2.4.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f249ab5bd0d69befe35897cf51a8fc9e01e9c8c9fe03087a68e6fe6d3e31d0d"}, + {file = "valkey_glide-2.4.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:87bf55231a35a786e93485b7d82c5775a287f969d2e0a16c99e877ac2460e29e"}, + {file = "valkey_glide-2.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6409985596b9f8adddbc62c0b5d1e192ce6467b0436d8d6a49dcaa3272fec4be"}, + {file = "valkey_glide-2.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eea949cba7fe3601d6dcd8e757885dfbf8af1b2654b1c81e5f64772bfa12c3f"}, + {file = "valkey_glide-2.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11d9ca55a7aab773ecb8fbad4efd186862ea4c911c9c522317eb2b10343ae567"}, + {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ade719b52a8a0c28f14792dd4fe9db718afce8e5a22e8289ffb430639744e419"}, + {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a29269ced9078b14c1de1c76412854021ca3acdad6476d89ea491a5cf7ddcae0"}, + {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1346846af82620def2303ef6085a31174ac80873931e455d29e1368c1ac7e359"}, + {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ad2f883ce828c4cbb892d472c9b3e21e714fc217f5a1ca80cfad110484d87a4"}, + {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:775df9c7421a187c41caf003e4af5f073ed7e4b8abe50f8b9bec712cb03e12bf"}, + {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0d87f21c77004240189cc3c5aab156966487afd81ffdee04225a52c7bd7132e4"}, + {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44376ef5fe7a25287095b073d8abde510a50b1ead0143662394b3da9717863ef"}, + {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a59cc0a21d7a8b1b3caeb299f23817429b5fe6579bd4cb016382e6b7a10de984"}, + {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f3ae6328f0e0a2e887791516192c881060f9407381bc8a80d288a48bd4351795"}, + {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0bcb83d35908ca34078785402b64dbf37073d5ff23d9da4890d93c2b3f09dc7"}, + {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdce17dc0aea468f17a85b92ac433bb91834e0c72c9d9530d81508186d4a9bea"}, + {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4ffe9c6b9b86a1064ac538d6ae4f85dffa56c9286400c82bc77eccc7286f0b4"}, + {file = "valkey_glide-2.4.1.tar.gz", hash = "sha256:f1155d84156d11b90488aa67e90102f0bf98a45314f5b99308ac9074c05f7241"}, ] [package.dependencies] anyio = ">=4.9.0" -protobuf = ">=6.20" +protobuf = ">=3.20" sniffio = "*" typing-extensions = {version = ">=4.8.0", markers = "python_version < \"3.11\""} @@ -5223,4 +5223,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "325feb84a282310b016844cd52100d9a18841c17bb80d556c550fe8f83c86f04" +content-hash = "8488be13a2ba128328fae0a536084af7a459cc9dd4eb79fb00006f60052d4839" diff --git a/pyproject.toml b/pyproject.toml index f4c2d56541e..0e06b7efaa3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,7 +129,7 @@ mkdocs-llmstxt = ">=0.2,<0.5" avro = "^1.12.0" protobuf = ">=6.30.2,<8.0.0" types-protobuf = ">=6.30.2.20250516,<8.0.0.0" -ty = ">=0.0.23,<0.0.36" +ty = ">=0.0.23,<0.0.50" [tool.coverage.run] source = ["aws_lambda_powertools"] From c0804d4e22f27db782469f17488188500d010781 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:38:27 +0200 Subject: [PATCH 03/76] chore(deps): bump cryptography from 46.0.7 to 48.0.1 (#8286) Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.7 to 48.0.1. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/46.0.7...48.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-version: 48.0.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 116 ++++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 62 deletions(-) diff --git a/poetry.lock b/poetry.lock index f431e0c0bb6..d0fd79c14bd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1093,6 +1093,7 @@ description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" groups = ["main", "dev"] +markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -1179,7 +1180,6 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] -markers = {main = "platform_python_implementation != \"PyPy\" and (extra == \"all\" or extra == \"datamasking\")", dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1521,77 +1521,69 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" -version = "46.0.7" +version = "48.0.1" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.8" +python-versions = "!=3.9.0,!=3.9.1,>=3.9" groups = ["main", "dev"] files = [ - {file = "cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb"}, - {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b"}, - {file = "cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85"}, - {file = "cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e"}, - {file = "cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457"}, - {file = "cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b"}, - {file = "cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1"}, - {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2"}, - {file = "cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e"}, - {file = "cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee"}, - {file = "cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298"}, - {file = "cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb"}, - {file = "cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006"}, - {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0"}, - {file = "cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85"}, - {file = "cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e"}, - {file = "cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246"}, - {file = "cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3"}, - {file = "cryptography-46.0.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f"}, - {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15"}, - {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455"}, - {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65"}, - {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968"}, - {file = "cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4"}, - {file = "cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5"}, + {file = "cryptography-48.0.1-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:3e4a1a3232eef2e6c732827d5722db29a0cc8b27af2a4d865b094cf954be9ca1"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:32143b24adb918f078134e1e230f1eb8cc04886b92c28b5f0041aaf3e5699225"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0d27a5696721ef7a672b8c810f6aded391058e0b9486e63e6d93baf765da691"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb86ce1af36fe65041b6db9a8bb064ee621a7e5fded0f80d475ec243477cd242"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b024e784ad6c077ee0147b35ea9cbfc1e34e1fd4c1dcca214c2794d73a12df08"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3752f2dbc8f07a30aad2932c986cea495b03bb554887828225da104f732852b6"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:bd81490cd5801d755cf97bb68ac191f14b708470b1c7cf4580f669b9c9264cd8"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:66fd0771e7b9c6dcd44cf1120690d2338d16d72795cf40cae2786a39eba65429"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:3fd2ca57062b241c856670b073487d2e86c4637937ca5601e48f97bf8e11fc8f"}, + {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:0ee6ea481db1ab889cba043ec1eda17bb9c1ea79db6722f779c3667f9f70322f"}, + {file = "cryptography-48.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f2ceef93cb096aa3c4cc4b5c94ca6131f9196d28c64d6111533402a9b2054d41"}, + {file = "cryptography-48.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bd3f92d76217892b15df84ca256c2c113d386fdda7a7d8691aeeced976507c6"}, + {file = "cryptography-48.0.1-cp311-abi3-win32.whl", hash = "sha256:b9a32b876490d66c8bcc9963ef220199569748434ab01a9d6aaeabf88e7f5158"}, + {file = "cryptography-48.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:39489bfca54c7a1f6b297efcd8bc608ab92d16c4ca631b0cad4da46724588b24"}, + {file = "cryptography-48.0.1-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:f817adc181390bd54f2f700107a7419040fb7c1bdf2fc26f36551a06a68c3345"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d5d30989c6917b478b5817902e85fddaea2261efa8648383d965381ccb9e1ac4"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:df637c05205ea7c1d7fbcbe54bbfea648a52951155f997af13d895d0ecc96991"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:869c3b8a53bfe27147832df48b32adadf558249d50e76cb3769d40e986b13265"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:e361afba8918070d376df76f408a4f67fec0ee9cff81a99e48fe9a233ef59e17"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:d069066deead00ac7f090be101be875a06855908f7ec004c27b8fefb4acfb411"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:09f73a725d582cef64b91281a322cd798d14a33b2b6f2b7ad9531dc336d84c02"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:15254441469dd6bf027039453288e2072124f8b6603563f5d759e1c9b69273fa"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:8ace4507d1e6533c125f4fac754f8bb8b6a74c08e92179dabd7e16571a3efbf3"}, + {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:b4e391975f038e66432328639620a4aff2d307513b004f1ca06d6225bced815c"}, + {file = "cryptography-48.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42fcd8e26fe555d9b3577a135f5091fefa0aa4e99129c23fb56787a1bd4ada72"}, + {file = "cryptography-48.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1400da5e32a43253392277eac7490a60e497d810a63dd5608d71bbd7af507c9"}, + {file = "cryptography-48.0.1-cp314-cp314t-win32.whl", hash = "sha256:0df56b056bc17c1b7d6821dfa65216e62bd232d8ab05eb3db44e71d235651471"}, + {file = "cryptography-48.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:9de21387aa95e2a895823d0745b430bed4f33503ba9ab5e0b5311f33e37d66d2"}, + {file = "cryptography-48.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:4fdc69f8e4316bcf0c8c8ec1f26f285d12e8142d88d96c876a59a03be3f6ae67"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48fe40804d4caa2288f24e70ca8c64c42dd826da0ad7e4f1b41b2128d679e6c8"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:86be3b1b0b6bf09482fb50a979c508d2950ed95f5621ec77f4e385962006b83a"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:4ab0a343c807bbcd90c971cd1ecf072937cd01847a9e002bef88fb47ac6be577"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9621de99d2da096006b629979efd8ae7eb2d8b822488d0c89ee4000c306c59b1"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:88c852a0ae366e262e5a1744b685e6a433dc8788dd2a277e418bf4904203609d"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:43c5835e2cb98c8733d86f57d6fc879b613f5c3478607281c3e36daffc6dd8a6"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:fe0180af5bf9236518a087e35bf2d9a347d5f5f51e63c579d683ddff424e3d46"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:b7a2d1a937a738a881737cec135a38bb61470589b17515b9f73f571d0ae10401"}, + {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b74ca3b8e5ecdd833bf6a002ca41b4793bb27fb8f1c06ffaf2643c9e9140e31b"}, + {file = "cryptography-48.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2c37f2461406063b417837f5f3daab668652acd82423efcd7f0a9f04be972de1"}, + {file = "cryptography-48.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:86fe77abb1bd87afb251d4d02ada7ecf53a32cee9b67d976abb2e45a13297475"}, + {file = "cryptography-48.0.1-cp39-abi3-win32.whl", hash = "sha256:6b2c0c3e6ccf3ade7750f836ef3ee36eea250cc467d45c256895573ac08cc6f1"}, + {file = "cryptography-48.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:9a49ca6c81417f6a5edb50375a60cccdd70fa0a91a5211829dbea74eba94d2ac"}, + {file = "cryptography-48.0.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:08a597acce1ff37f347400087776599e2348a3a8bc53b44120e463cd274efe4a"}, + {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:735824ec41b7f74a7c45fb1591349333e4c696cb6c044e5f46356e560143e4cd"}, + {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:92a46e1d638daa264ba2971c0b0489c9409787943efae4d60ffda3d091ef832c"}, + {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:7e234ac052af99f2700826a5c29ea99d9c1b1f80341cde62d11c8154dc8e0bd9"}, + {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:33842cf0888951cef5bc7ac724ab844a42044c1727b967b7f8997289a0464f92"}, + {file = "cryptography-48.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6184ca7b174f28d7c703f1290d4b297217c45355f77a98f67e9b7f14549ac54a"}, + {file = "cryptography-48.0.1.tar.gz", hash = "sha256:266f4ee051abb2f725b74ef8072b521ce1feacf685a3364fa6a6b45548db791a"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\""} [package.dependencies] -cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} +cffi = {version = ">=2.0.0", markers = "platform_python_implementation != \"PyPy\""} typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11.0\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox[uv] (>=2024.4.15)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.14)", "ruff (>=0.11.11)"] -sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==46.0.7)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] [[package]] name = "datadog" @@ -3432,11 +3424,11 @@ description = "C parser in Python" optional = false python-versions = ">=3.10" groups = ["main", "dev"] +markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"" files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] -markers = {main = "platform_python_implementation != \"PyPy\" and (extra == \"all\" or extra == \"datamasking\") and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""} [[package]] name = "pydantic" From 6497a4f4b2669fdce5a66aa6b686dc3717178d00 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 18 Jun 2026 07:01:13 -0400 Subject: [PATCH 04/76] docs(event-handler): add import path gotcha for dependency_overrides testing (#8269) * docs(event-handler): add import path gotcha for dependency_overrides testing docs(event-handler): add import path gotcha for dependency_overrides testing Signed-off-by: hirenkumar-n-dholariya * docs(event-handler): add import path gotcha for dependency_overrides testing docs(event-handler): add import path gotcha for dependency_overrides testing Signed-off-by: hirenkumar-n-dholariya --------- Signed-off-by: hirenkumar-n-dholariya Co-authored-by: Leandro Damascena --- docs/core/event_handler/api_gateway.md | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 076e2aa3c11..c4508976157 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -1459,6 +1459,33 @@ Use `dependency_overrides` to replace any dependency with a mock or stub during --8<-- "examples/event_handler_rest/src/dependency_injection_testing.py" ``` +???+ warning "Import path must match exactly when using dependency_overrides" + When using `dependency_overrides` in tests, the imported dependency reference must use the **exact same import path** as the handler file. Python treats differently-imported modules as different objects in `sys.modules`, so the override will be silently ignored otherwise. + + === "✅ Correct" + + ```python + # handler.py + from depends import get_config + + # test_handler.py - matches handler's import path exactly + from depends import get_config + + app.dependency_overrides[get_config] = lambda: "test-value" + ``` + + === "❌ Wrong" + + ```python + # handler.py + from depends import get_config + + # test_handler.py - different import path, override won't apply + from my_app.api_handler.depends import get_config + + app.dependency_overrides[get_config] = lambda: "test-value" + ``` + ???+ tip "Caching behavior" By default, dependencies are cached within the same invocation (`use_cache=True`). If the same dependency is used by multiple handlers or sub-dependencies, it is resolved once and the result is reused. Use `Depends(fn, use_cache=False)` to resolve every time. From f7239b82f0a7c6a13f37b3e958f02969ff444308 Mon Sep 17 00:00:00 2001 From: Lucas Kim <41357160+kimnamu@users.noreply.github.com> Date: Thu, 18 Jun 2026 20:26:27 +0900 Subject: [PATCH 05/76] feat(event_handler): allow custom serializer on BedrockAgentResolver (#8271) BedrockAgentResolver did not expose the `serializer` parameter that its parent ApiGatewayResolver and its sibling BedrockAgentFunctionResolver already accept, so there was no way to override the default `ensure_ascii=True` serialization. Non-ASCII agent responses (e.g. Korean/Japanese/emoji) were therefore always \uXXXX-escaped in responseBody.body. Expose the existing parent `serializer` argument and pass it through to super().__init__, matching the sibling resolver. Co-authored-by: Claude Opus 4.8 (1M context) Co-authored-by: Leandro Damascena --- .../event_handler/bedrock_agent.py | 9 +++-- .../_pydantic/test_bedrock_agent.py | 35 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/bedrock_agent.py b/aws_lambda_powertools/event_handler/bedrock_agent.py index a49ba38c214..6fef1044b97 100644 --- a/aws_lambda_powertools/event_handler/bedrock_agent.py +++ b/aws_lambda_powertools/event_handler/bedrock_agent.py @@ -99,12 +99,17 @@ def lambda_handler(event, context): current_event: BedrockAgentEvent - def __init__(self, debug: bool = False, enable_validation: bool = True): + def __init__( + self, + debug: bool = False, + enable_validation: bool = True, + serializer: Callable[[dict], str] | None = None, + ): super().__init__( proxy_type=ProxyEventType.BedrockAgentEvent, cors=None, debug=debug, - serializer=None, + serializer=serializer, strip_prefixes=None, enable_validation=enable_validation, json_body_deserializer=None, diff --git a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py index 9c46fe24eb7..4367a94f49d 100644 --- a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py +++ b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py @@ -1,4 +1,5 @@ import json +from functools import partial from typing import Any, Dict, Optional import pytest @@ -383,3 +384,37 @@ def run_sql_query(query: Annotated[str, Query()]): # THEN the parameter with commas should be correctly passed to the handler body = json.loads(result["response"]["responseBody"]["application/json"]["body"]) assert body["result"] == "SELECT a.source_name, b.thing FROM table" + + +def test_bedrock_agent_with_default_serializer_escapes_non_ascii(): + # GIVEN a Bedrock Agent resolver using the default serializer + app = BedrockAgentResolver() + + @app.get("/claims", description="Gets claims") + def claims() -> Dict[str, Any]: + return {"output": "잔액은 1,000원입니다 💰"} + + # WHEN calling the event handler + result = app(load_event("bedrockAgentEvent.json"), {}) + + # THEN the body is valid JSON and non-ASCII characters are escaped (default json.dumps behavior) + body = result["response"]["responseBody"]["application/json"]["body"] + assert "\\uc794" in body # "잔" escaped + assert json.loads(body) == {"output": "잔액은 1,000원입니다 💰"} + + +def test_bedrock_agent_with_custom_serializer_preserves_non_ascii(): + # GIVEN a Bedrock Agent resolver initialized with a custom serializer that keeps non-ASCII characters + app = BedrockAgentResolver(serializer=partial(json.dumps, ensure_ascii=False)) + + @app.get("/claims", description="Gets claims") + def claims() -> Dict[str, Any]: + return {"output": "잔액은 1,000원입니다 💰"} + + # WHEN calling the event handler + result = app(load_event("bedrockAgentEvent.json"), {}) + + # THEN the non-ASCII characters are preserved verbatim in the response body + body = result["response"]["responseBody"]["application/json"]["body"] + assert "잔액은 1,000원입니다 💰" in body + assert json.loads(body) == {"output": "잔액은 1,000원입니다 💰"} From 50541feefc9d525f3bfc2dd55ab5e84ade979ad8 Mon Sep 17 00:00:00 2001 From: Sujit Patil Date: Sat, 20 Jun 2026 15:21:42 +0530 Subject: [PATCH 06/76] fix(batch): add optional logger injection for BatchProcessors (#7553) (#8272) * chore: fix minor typos and grammar in docs and comments * fix(batch): add optional logger injection for BatchProcessors (#7553) * fix: satisfy batch logger mypy checks * chore: address batch logger review feedback * chore: simplify batch logger warning guard --------- Co-authored-by: AI Bot Co-authored-by: Leandro Damascena Co-authored-by: Sujit --- aws_lambda_powertools/utilities/batch/base.py | 22 +++++- .../batch/sqs_fifo_partial_processor.py | 11 ++- .../test_utilities_batch.py | 74 +++++++++++++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/aws_lambda_powertools/utilities/batch/base.py b/aws_lambda_powertools/utilities/batch/base.py index 4cb1337cafd..e1266b69d2a 100644 --- a/aws_lambda_powertools/utilities/batch/base.py +++ b/aws_lambda_powertools/utilities/batch/base.py @@ -14,7 +14,7 @@ import sys from abc import ABC, abstractmethod from enum import Enum -from typing import TYPE_CHECKING, Any, Tuple, Union, overload +from typing import TYPE_CHECKING, Any, Tuple, TypeGuard, Union, overload from aws_lambda_powertools.shared import constants from aws_lambda_powertools.utilities.batch.exceptions import ( @@ -35,6 +35,7 @@ if TYPE_CHECKING: from collections.abc import Callable + from types import TracebackType from aws_lambda_powertools.utilities.batch.types import ( PartialItemFailureResponse, @@ -61,6 +62,10 @@ class EventType(Enum): FailureResponse = Tuple[str, str, BatchEventTypes] +def _has_traceback(exception: ExceptionInfo) -> TypeGuard[tuple[type[BaseException], BaseException, TracebackType]]: + return exception[0] is not None and exception[1] is not None and exception[2] is not None + + class BasePartialProcessor(ABC): """ Abstract class for batch processors. @@ -68,10 +73,11 @@ class BasePartialProcessor(ABC): lambda_context: LambdaContext - def __init__(self): + def __init__(self, logger: logging.Logger | None = None): self.success_messages: list[BatchEventTypes] = [] self.fail_messages: list[BatchEventTypes] = [] self.exceptions: list[ExceptionInfo] = [] + self.logger = logger @abstractmethod def _prepare(self): @@ -237,6 +243,13 @@ def failure_handler(self, record, exception: ExceptionInfo) -> FailureResponse: exception_string = f"{exception[0]}:{exception[1]}" entry = ("fail", exception_string, record) logger.debug(f"Record processing exception: {exception_string}") + + if self.logger is not None and _has_traceback(exception): + self.logger.warning( + "Record processing exception; skipping this record", + exc_info=exception, + ) + self.exceptions.append(exception) self.fail_messages.append(record) return entry @@ -250,6 +263,7 @@ def __init__( event_type: EventType, model: BatchTypeModels | None = None, raise_on_entire_batch_failure: bool = True, + logger: logging.Logger | None = None, ): """Process batch and partially report failed items @@ -262,6 +276,8 @@ def __init__( raise_on_entire_batch_failure: bool Raise an exception when the entire batch has failed processing. When set to False, partial failures are reported in the response + logger: logging.Logger | None + Optional Logger instance to output warnings with tracebacks for failed records. Exceptions ---------- @@ -285,7 +301,7 @@ def __init__( EventType.Kafka: KafkaEventRecord, } - super().__init__() + super().__init__(logger=logger) def response(self) -> PartialItemFailureResponse: """Batch items that failed processing, if any""" diff --git a/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py b/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py index 2e680e2f04e..88a6c3dfe37 100644 --- a/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py +++ b/aws_lambda_powertools/utilities/batch/sqs_fifo_partial_processor.py @@ -66,7 +66,12 @@ def lambda_handler(event, context: LambdaContext): None, ) - def __init__(self, model: BatchSqsTypeModel | None = None, skip_group_on_error: bool = False): + def __init__( + self, + model: BatchSqsTypeModel | None = None, + skip_group_on_error: bool = False, + logger: logging.Logger | None = None, + ): """ Initialize the SqsFifoProcessor. @@ -77,12 +82,14 @@ def __init__(self, model: BatchSqsTypeModel | None = None, skip_group_on_error: skip_group_on_error: bool Determines whether to exclusively skip messages from the MessageGroupID that encountered processing failures Default is False. + logger: logging.Logger | None + Optional Logger instance to output warnings with tracebacks for failed records. """ self._skip_group_on_error: bool = skip_group_on_error self._current_group_id = None self._failed_group_ids: set[str] = set() - super().__init__(EventType.SQS, model) + super().__init__(EventType.SQS, model, logger=logger) def _process_record(self, record): self._current_group_id = record.get("attributes", {}).get("MessageGroupId") diff --git a/tests/functional/batch/required_dependencies/test_utilities_batch.py b/tests/functional/batch/required_dependencies/test_utilities_batch.py index 43c2aa16191..e8e544c127e 100644 --- a/tests/functional/batch/required_dependencies/test_utilities_batch.py +++ b/tests/functional/batch/required_dependencies/test_utilities_batch.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import logging import uuid from random import randint from typing import TYPE_CHECKING, Any @@ -861,3 +862,76 @@ async def simple_async_handler(record: SQSRecord): # THEN record is processed successfully using asyncio.run() assert result == {"batchItemFailures": []} assert result == {"batchItemFailures": []} + + +def test_batch_processor_logs_exception_with_injected_logger(sqs_event_factory, caplog): + fail_record = sqs_event_factory("fail") + success_record = sqs_event_factory("success") + + def handler(record): + if "fail" in record["body"]: + raise ValueError("intentional failure") + return record["body"] + + test_logger = logging.getLogger("test_logger") + processor = BatchProcessor(event_type=EventType.SQS, logger=test_logger) + + with caplog.at_level(logging.WARNING, logger="test_logger"): + process_partial_response( + event={"Records": [fail_record, success_record]}, + record_handler=handler, + processor=processor, + ) + + warning_records = [r for r in caplog.records if r.levelno == logging.WARNING] + assert len(warning_records) == 1, f"Expected 1 WARNING log, got {len(warning_records)}" + assert "intentional failure" in warning_records[0].getMessage() or warning_records[0].exc_info is not None + assert warning_records[0].exc_info is not None, "Expected exc_info (traceback) in log record" + assert warning_records[0].exc_info[0] is ValueError + + +def test_batch_processor_does_not_log_without_injected_logger(sqs_event_factory, caplog): + fail_record = sqs_event_factory("fail") + + def handler(record): + raise ValueError("intentional failure") + + processor = BatchProcessor(event_type=EventType.SQS, raise_on_entire_batch_failure=False, logger=None) + + with caplog.at_level(logging.WARNING, logger="aws_lambda_powertools.utilities.batch.base"): + process_partial_response( + event={"Records": [fail_record]}, + record_handler=handler, + processor=processor, + ) + + warning_records = [r for r in caplog.records if r.levelno == logging.WARNING] + assert len(warning_records) == 0, "Expected no WARNING logs when logger is None" + + +def test_sqs_fifo_circuit_breaker_does_not_log(sqs_event_fifo_factory, caplog): + failing_record = sqs_event_fifo_factory("fail", "group-1") + short_circuited_record = sqs_event_fifo_factory("would-succeed", "group-1") + + def handler(record): + if "fail" in record["body"]: + raise ValueError("first record failure") + return record["body"] + + test_logger = logging.getLogger("test_logger") + processor = SqsFifoPartialProcessor(logger=test_logger) + processor.raise_on_entire_batch_failure = False + + with caplog.at_level(logging.WARNING, logger="test_logger"): + process_partial_response( + event={"Records": [failing_record, short_circuited_record]}, + record_handler=handler, + processor=processor, + ) + + warning_records = [r for r in caplog.records if r.levelno == logging.WARNING] + assert len(warning_records) == 1, ( + f"Expected exactly 1 WARNING (real exception only), got {len(warning_records)}: " + + str([r.getMessage() for r in warning_records]) + ) + assert warning_records[0].exc_info[0] is ValueError From 7634b2fd807246e10f5044393b1851dd3abb90a1 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 22 Jun 2026 10:42:53 +0100 Subject: [PATCH 07/76] refactor(event_handler): promote HttpResolver to stable (#8289) * refactor: promote HttpResolver to stable * refactor: promote HttpResolver to stable --- .../event_handler/__init__.py | 3 ++- .../event_handler/http_resolver.py | 20 ++++++------------- docs/core/event_handler/api_gateway.md | 2 +- docs/includes/_http_resolver_local.md | 8 ++------ .../src/http_resolver_basic.py | 4 ++-- .../src/http_resolver_exception_handling.py | 4 ++-- .../src/http_resolver_validation_swagger.py | 4 ++-- .../_pydantic/test_http_resolver_pydantic.py | 4 ---- .../test_http_resolver.py | 6 +----- 9 files changed, 18 insertions(+), 37 deletions(-) diff --git a/aws_lambda_powertools/event_handler/__init__.py b/aws_lambda_powertools/event_handler/__init__.py index 98433b2e29b..2e4c008ec63 100644 --- a/aws_lambda_powertools/event_handler/__init__.py +++ b/aws_lambda_powertools/event_handler/__init__.py @@ -18,7 +18,7 @@ ) from aws_lambda_powertools.event_handler.depends import DependencyResolutionError, Depends from aws_lambda_powertools.event_handler.events_appsync.appsync_events import AppSyncEventsResolver -from aws_lambda_powertools.event_handler.http_resolver import HttpResolverLocal +from aws_lambda_powertools.event_handler.http_resolver import HttpResolver, HttpResolverLocal from aws_lambda_powertools.event_handler.lambda_function_url import ( LambdaFunctionUrlResolver, ) @@ -39,6 +39,7 @@ "CORSConfig", "Depends", "DependencyResolutionError", + "HttpResolver", "HttpResolverLocal", "LambdaFunctionUrlResolver", "Request", diff --git a/aws_lambda_powertools/event_handler/http_resolver.py b/aws_lambda_powertools/event_handler/http_resolver.py index 6ec0b064974..7206dbe6f1c 100644 --- a/aws_lambda_powertools/event_handler/http_resolver.py +++ b/aws_lambda_powertools/event_handler/http_resolver.py @@ -1,7 +1,6 @@ from __future__ import annotations import base64 -import warnings from typing import TYPE_CHECKING, Any, Callable from urllib.parse import parse_qs @@ -162,21 +161,16 @@ def get_remaining_time_in_millis(self) -> int: # pragma: no cover class HttpResolverLocal(ApiGatewayResolver): """ - ASGI-compatible HTTP resolver for local development and testing. + ASGI-compatible HTTP resolver. - This resolver is designed specifically for local development workflows. - It allows you to run your Powertools application locally with any ASGI server + It allows you to run your Powertools application with any ASGI server (uvicorn, hypercorn, daphne, etc.) while maintaining full compatibility with Lambda. The same code works in both environments - locally via ASGI and in Lambda via the handler. + If your Lambda is behind Lambda Web Adapter or any other HTTP proxy, it works seamlessly. Supports both sync and async route handlers. - WARNING - ------- - This is intended for local development and testing only. - The API may change in future releases. Do not use in production environments. - Example ------- ```python @@ -210,11 +204,6 @@ def __init__( strip_prefixes: list[str | Any] | None = None, enable_validation: bool = False, ): - warnings.warn( - "HttpResolverLocal is intended for local development and testing only. " - "The API may change in future releases. Do not use in production environments.", - stacklevel=2, - ) super().__init__( proxy_type=ProxyEventType.APIGatewayProxyEvent, # Use REST API format internally cors=cors, @@ -351,3 +340,6 @@ async def _send_response(self, send: Callable, response: dict) -> None: "body": body_bytes, }, ) + + +HttpResolver = HttpResolverLocal diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index c4508976157..67bb07a25cc 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -64,7 +64,7 @@ By default, we will use `APIGatewayRestResolver` throughout the documentation. Y | **[`ALBResolver`](#application-load-balancer)** | Amazon Application Load Balancer (ALB) | | **[`LambdaFunctionUrlResolver`](#lambda-function-url)** | AWS Lambda Function URL | | **[`VPCLatticeResolver`](#vpc-lattice)** | Amazon VPC Lattice | -| **[`HttpResolverLocal`](#http-resolver-local)** | Local development with ASGI servers | +| **[`HttpResolverLocal`](#http-resolver-local)** | ASGI-compatible resolver | #### Response auto-serialization diff --git a/docs/includes/_http_resolver_local.md b/docs/includes/_http_resolver_local.md index a9789a54746..496b42eb4f2 100644 --- a/docs/includes/_http_resolver_local.md +++ b/docs/includes/_http_resolver_local.md @@ -1,11 +1,7 @@ -#### Http Resolver (Local Development) +#### Http Resolver (ASGI) -???+ warning "Local Development Only" - `HttpResolverLocal` is intended for local development and testing only. - The API may change in future releases. **Do not use in production environments.** - -When developing locally, you can use `HttpResolverLocal` to run your API with any ASGI server like [uvicorn](https://www.uvicorn.org/){target="_blank"}. It implements the [ASGI specification](https://asgi.readthedocs.io/){target="_blank"}, is lightweight with no external dependencies, and the same code works on any compute platform, including Lambda. +`HttpResolver` is an ASGI-compatible resolver that lets you run your Powertools application with any ASGI server like [uvicorn](https://www.uvicorn.org/){target="_blank"}. It implements the [ASGI specification](https://asgi.readthedocs.io/){target="_blank"}, is lightweight with no external dependencies, and works seamlessly with Lambda or any environment that speaks HTTP. If your Lambda is behind [Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter){target="_blank"} or any other HTTP proxy that speaks the HTTP protocol, it works seamlessly. diff --git a/examples/event_handler_rest/src/http_resolver_basic.py b/examples/event_handler_rest/src/http_resolver_basic.py index 63d291c8e47..7f6aaadc57d 100644 --- a/examples/event_handler_rest/src/http_resolver_basic.py +++ b/examples/event_handler_rest/src/http_resolver_basic.py @@ -1,6 +1,6 @@ -from aws_lambda_powertools.event_handler import HttpResolverLocal +from aws_lambda_powertools.event_handler import HttpResolver -app = HttpResolverLocal() +app = HttpResolver() @app.get("/hello/") diff --git a/examples/event_handler_rest/src/http_resolver_exception_handling.py b/examples/event_handler_rest/src/http_resolver_exception_handling.py index 787687e6248..7a952812017 100644 --- a/examples/event_handler_rest/src/http_resolver_exception_handling.py +++ b/examples/event_handler_rest/src/http_resolver_exception_handling.py @@ -1,6 +1,6 @@ -from aws_lambda_powertools.event_handler import HttpResolverLocal, Response +from aws_lambda_powertools.event_handler import HttpResolver, Response -app = HttpResolverLocal() +app = HttpResolver() class NotFoundError(Exception): diff --git a/examples/event_handler_rest/src/http_resolver_validation_swagger.py b/examples/event_handler_rest/src/http_resolver_validation_swagger.py index 2c694c87bcc..d35e7964b9e 100644 --- a/examples/event_handler_rest/src/http_resolver_validation_swagger.py +++ b/examples/event_handler_rest/src/http_resolver_validation_swagger.py @@ -1,6 +1,6 @@ from pydantic import BaseModel -from aws_lambda_powertools.event_handler import HttpResolverLocal +from aws_lambda_powertools.event_handler import HttpResolver class User(BaseModel): @@ -8,7 +8,7 @@ class User(BaseModel): age: int -app = HttpResolverLocal(enable_validation=True) +app = HttpResolver(enable_validation=True) app.enable_swagger( title="My API", diff --git a/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py b/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py index 7cab58a1b70..e088527e359 100644 --- a/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py +++ b/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py @@ -13,10 +13,6 @@ from aws_lambda_powertools.event_handler.http_resolver import MockLambdaContext from aws_lambda_powertools.event_handler.openapi.params import Query -# Suppress warning for all tests -pytestmark = pytest.mark.filterwarnings("ignore:HttpResolverLocal is intended for local development") - - # ============================================================================= # ASGI Test Helpers # ============================================================================= diff --git a/tests/functional/event_handler/required_dependencies/test_http_resolver.py b/tests/functional/event_handler/required_dependencies/test_http_resolver.py index ada85cf59fc..4665812e64a 100644 --- a/tests/functional/event_handler/required_dependencies/test_http_resolver.py +++ b/tests/functional/event_handler/required_dependencies/test_http_resolver.py @@ -1,4 +1,4 @@ -"""Tests for HttpResolverLocal - ASGI-compatible HTTP resolver for local development.""" +"""Tests for HttpResolverLocal - ASGI-compatible HTTP resolver.""" from __future__ import annotations @@ -11,10 +11,6 @@ from aws_lambda_powertools.event_handler import HttpResolverLocal, Response from aws_lambda_powertools.event_handler.http_resolver import MockLambdaContext -# Suppress warning for all tests -pytestmark = pytest.mark.filterwarnings("ignore:HttpResolverLocal is intended for local development") - - # ============================================================================= # ASGI Test Helpers # ============================================================================= From ef6198012a8395ceac460cdd7df4abaff3147340 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 16:24:04 +0200 Subject: [PATCH 08/76] chore(deps): bump pydantic-settings from 2.14.1 to 2.14.2 (#8299) Bumps [pydantic-settings](https://github.com/pydantic/pydantic-settings) from 2.14.1 to 2.14.2. - [Release notes](https://github.com/pydantic/pydantic-settings/releases) - [Commits](https://github.com/pydantic/pydantic-settings/compare/v2.14.1...v2.14.2) --- updated-dependencies: - dependency-name: pydantic-settings dependency-version: 2.14.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index d0fd79c14bd..610925587c7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1093,7 +1093,6 @@ description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" groups = ["main", "dev"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -1180,6 +1179,7 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] +markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1577,6 +1577,7 @@ files = [ {file = "cryptography-48.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6184ca7b174f28d7c703f1290d4b297217c45355f77a98f67e9b7f14549ac54a"}, {file = "cryptography-48.0.1.tar.gz", hash = "sha256:266f4ee051abb2f725b74ef8072b521ce1feacf685a3364fa6a6b45548db791a"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\""} [package.dependencies] cffi = {version = ">=2.0.0", markers = "platform_python_implementation != \"PyPy\""} @@ -3424,11 +3425,11 @@ description = "C parser in Python" optional = false python-versions = ">=3.10" groups = ["main", "dev"] -markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"" files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] +markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""} [[package]] name = "pydantic" @@ -3589,15 +3590,15 @@ typing-extensions = ">=4.14.1" [[package]] name = "pydantic-settings" -version = "2.14.1" +version = "2.14.2" description = "Settings management using Pydantic" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"all\"" files = [ - {file = "pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de"}, - {file = "pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa"}, + {file = "pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440"}, + {file = "pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f"}, ] [package.dependencies] From 5b7cbd3148126a70b853db4aec7fad4be5da7346 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:12:30 +0100 Subject: [PATCH 09/76] chore(deps): bump ujson from 5.12.1 to 5.13.0 (#8298) Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.12.1 to 5.13.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.12.1...5.13.0) --- updated-dependencies: - dependency-name: ujson dependency-version: 5.13.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 174 ++++++++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 79 deletions(-) diff --git a/poetry.lock b/poetry.lock index 610925587c7..6b3b292b8f6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4850,89 +4850,105 @@ typing-extensions = ">=4.12.0" [[package]] name = "ujson" -version = "5.12.1" +version = "5.13.0" description = "Ultra fast JSON encoder and decoder for Python" -optional = true +optional = false python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"datadog\"" files = [ - {file = "ujson-5.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:71bdb5d10c6d7e710cfa78e743d9fb79a37c7c66fa916cd287bffbaa520f5abe"}, - {file = "ujson-5.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:558673c6c3a2309775683ca96d5f1e4cd99889f71b1ba5cb6be8aa37ae67f9e0"}, - {file = "ujson-5.12.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4b0c9f6a56aa94bb98b403e1f57a866f0b43abaa89757b24d4a4b3cd8643ced"}, - {file = "ujson-5.12.1-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:7bba5ab7965619db7d6f5503133b8e2d8bfce9bb6754224ca64d19261cc52f7c"}, - {file = "ujson-5.12.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:191d2077fd53441599a2efd3dcc205b9cc5f3a4d685a76e9f73f4b6c19aee0c9"}, - {file = "ujson-5.12.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d90d27953716ef206c42f166932b3dbb264dc638bbf32acae81b216ae35f566d"}, - {file = "ujson-5.12.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b6afa86c117b66034004ee83c5149c6dccf7cb88941f9d3a1640c7076577f2d4"}, - {file = "ujson-5.12.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9523d67d45334f9a1d62e423bd72be62b58d2289a50420ffffa9363763eab73f"}, - {file = "ujson-5.12.1-cp310-cp310-win32.whl", hash = "sha256:757f2026bef09d231d63a2250a2c7ad21ea1c9cb1ded6480659d202c4e2ef09e"}, - {file = "ujson-5.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:7e31afad20cd6837a5ac6965d95b44b0ff06e42a82b01a8d3dc606a07f0b7a2a"}, - {file = "ujson-5.12.1-cp310-cp310-win_arm64.whl", hash = "sha256:80f58ae2be100da0f525330ee274accd8892d1c125fea75076f60539d9a5f9cd"}, - {file = "ujson-5.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26dcb43869057373048cbd2678293c5b0f962d5774cc76fc9488564a209bcbf2"}, - {file = "ujson-5.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bca3f04b2f590a8211acdc3ca06649b65a7ed1e999437dccf095310be9d3ba4e"}, - {file = "ujson-5.12.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29d1d64ed2c3c17666f4f0e15462800f3477255dc53667ad5d099277866c5666"}, - {file = "ujson-5.12.1-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:2cfbd6b0c677d5d053964b8f98d8bb1af10c591c8c24454bcd40006ac8ba18db"}, - {file = "ujson-5.12.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f75caed5b6d1fc271bb720a780c4199914267f7b865f9bf17826c4feccea582c"}, - {file = "ujson-5.12.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b21b4c680594c8686bcd4cdda0fd3ea2567b9d42bcf1d1e3d92d39bcdb02e8f1"}, - {file = "ujson-5.12.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:50d07e79ec70d32b4fbe18ab706ed0b172be08710d5901b9d067d7951bfaa164"}, - {file = "ujson-5.12.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:080bc65ac7c0a6314d45d55b6171d3a48b1aeaf89895654d625b291cfe46309f"}, - {file = "ujson-5.12.1-cp311-cp311-win32.whl", hash = "sha256:251ba8229e19b4b0b3efb5e7e3ddfa67c5c466aa492707bc3f6568bf714604dc"}, - {file = "ujson-5.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:46315b82505c99101dcab3bd979f15fecfde85c02df7efbb4e428fa357665290"}, - {file = "ujson-5.12.1-cp311-cp311-win_arm64.whl", hash = "sha256:12e99e49c62322ed0394c914aff15403ba7ede0b74f05a0faa4ec12c7d17a139"}, - {file = "ujson-5.12.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:10f44bd08ae52ee23ca6e8b472692e5da1768af2d53ff1bad6f40b532e0bc7ee"}, - {file = "ujson-5.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cc6ea753b7303fa5629fa9ac9257ea4b001c4d72583b2bb36ff1855a07db49f"}, - {file = "ujson-5.12.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:289f13095764d03734adfa10107da9b530ceb64dc1b02a5f507588d978d5b7df"}, - {file = "ujson-5.12.1-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:427893168d074e59214b0ee058337c57f5bb80175cdd5b4799a9c931aae22022"}, - {file = "ujson-5.12.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7a81724d5d90a2da7155d15d8b156ce57eaed7cdd622df813f36a8e612fd4c8"}, - {file = "ujson-5.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3a6efff7dc6515416366819de4a1bc449b77107c5b48508b101fd40f7f8bec08"}, - {file = "ujson-5.12.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77a71fe53427a0cf49d56eafd801d9f7e203b784b7f99cc717783fd6f6f7b732"}, - {file = "ujson-5.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ea3bed53d2ea8e5642e814a9e41f3e29420a8067874ba03ace8c0462e160490c"}, - {file = "ujson-5.12.1-cp312-cp312-win32.whl", hash = "sha256:758e5c8fbe4e6d483041e03b307b01fb5d2f2dd4452d4d4b927ab902e188939e"}, - {file = "ujson-5.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:f6074d3d3267ba1914c624b6e1fa3d8152648ff36b0ab77ddf83b92db488c30d"}, - {file = "ujson-5.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:7642a41520ac1b2bc25ea282b66b8da522cc43424442e6fb5e039be4d4f96530"}, - {file = "ujson-5.12.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c4bdc052a5d097f0a2e56d93aed97355f9f7a62ef9baa4f8517e43245434af9c"}, - {file = "ujson-5.12.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5dc91fa06ea35920b704fd9d70871897680145998071cfbf5ee3e19f2c9fc242"}, - {file = "ujson-5.12.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5db0849c0e3da54822a5834f2dc51d7c51072d7f7d665014ee34600dc10889b"}, - {file = "ujson-5.12.1-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:949cb4863a5d4847edeb47c5364b334e8cadf23a7cbdaa547d86098a4b093106"}, - {file = "ujson-5.12.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8aa731138d6dfca4ab84501b72384e6c544bfb48cb87a0dd4d304df3246cac25"}, - {file = "ujson-5.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:727e983ef27892d86ee2d28fd517eeb02b2c1165aafcbe929dce988aeee81bfe"}, - {file = "ujson-5.12.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d57d731ecf492d3d011e65369f8330654f0875b19f646be5270d478e843d3b81"}, - {file = "ujson-5.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a09636220f26c66f80c6c6283023cb53120e843825f890be92696cd1aa43f39"}, - {file = "ujson-5.12.1-cp313-cp313-win32.whl", hash = "sha256:ee83fbac03a0896faf190177c938f94eb610b798d495a19d50997242c4eca685"}, - {file = "ujson-5.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:e08d9e096c416ddc34519241f97c201258b42639f2012d9547d8ae32921800dd"}, - {file = "ujson-5.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:963287e4b1bc463735c4056968a2dfa59bb831b6daba68bddd14f451191fe9e5"}, - {file = "ujson-5.12.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6f19e9a407a24230df0cc1ec1c0f5999872ba526b14a780f80ad6479f5eed9bc"}, - {file = "ujson-5.12.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8b657e870c77aaacdeea86cfad3e6d2ef9b52517e45988c9c367f7ee764fe4dd"}, - {file = "ujson-5.12.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:984b5a99d1e0a037c2046c3c4b34cec832565d62d5017be0a035bf3cbfab72dc"}, - {file = "ujson-5.12.1-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:f48ef8a16f1d85bd7982beac7adfd3fb704058631db84c1c61c8a1b7072b1508"}, - {file = "ujson-5.12.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f39ba3b65cc637b59731532f7e7c807786bff1d0332ab2d5b96a04d2584d78f"}, - {file = "ujson-5.12.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:07f307780f85b49cba93f291718421b6f5f3b627a323b431fad937a18f6587cb"}, - {file = "ujson-5.12.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:1c335caea51c31494e514b82d50763b9792d3960d2c7d9fdb6b6fb8ed50ebdd0"}, - {file = "ujson-5.12.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:19ea07e29a45d199f926aadf93a9974128438c01b83141fba32477c0ee604b33"}, - {file = "ujson-5.12.1-cp314-cp314-win32.whl", hash = "sha256:c8e626b6bc9bdd2e8f7393b7d99f3daa2ca4022e6203662e70de7bb3604b21b9"}, - {file = "ujson-5.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:c6d3bdd020333688ee60559437021ed68a98a28fdd609b5af16de5dd58f90cba"}, - {file = "ujson-5.12.1-cp314-cp314-win_arm64.whl", hash = "sha256:e3c9c894971f4ada3ded16a804ed4640e1f2b3e5239beaeec7c48296f39f4232"}, - {file = "ujson-5.12.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:49dd9c378e1c8e676785ff2b62cb490074229f15ab54abf45b623713cb2c36b5"}, - {file = "ujson-5.12.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6d8827904358d7da59ccf2e1fd8de59e78248036d17fecc0462e62c6721f1102"}, - {file = "ujson-5.12.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc26caebea90425662ef0b979f945f6ac832651881107d6ec9a3c4d4a4ba929c"}, - {file = "ujson-5.12.1-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:45022aae09ac3d45bda6fbfc631088d1aff9a0465542d40bd6d295ced378c430"}, - {file = "ujson-5.12.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b22aa0f644516d3d5b29464949e4b23fe784f84b4a1030ab9ac3cb42aaedabb1"}, - {file = "ujson-5.12.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7dc5cf44ea42365cd1b66e6ed3fc6ca040c86587b024a6659b98e99d31cff2cd"}, - {file = "ujson-5.12.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8df5d984ff4ac1ef292d70f30da03417038a7e1e0bc272d28ca9d34f02f41682"}, - {file = "ujson-5.12.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:485f0182a0c0b54c304061cdc826d8343ce595c4055f7a24e72772a8520e5f7b"}, - {file = "ujson-5.12.1-cp314-cp314t-win32.whl", hash = "sha256:4e12ca368b397aed7fa1eec534ea1ba8d94977b376f9df3e93ae1acfd004ec40"}, - {file = "ujson-5.12.1-cp314-cp314t-win_amd64.whl", hash = "sha256:cec6b9b539539affc1f01a795c99574592a635ce22331b64f2b42e0af570659e"}, - {file = "ujson-5.12.1-cp314-cp314t-win_arm64.whl", hash = "sha256:696224d4cfb8883fa5c0285dff31e5ce924704dd9ccd38e9ea8b5bf4a42b12fc"}, - {file = "ujson-5.12.1-graalpy312-graalpy250_312_native-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2c419bf42ae40963fc27f70c59e24e9a97f5cf168dbce2c572f3c0ce3595912"}, - {file = "ujson-5.12.1-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0be2b4f2f547b9f0f3d902640e410e5a2fc851576cbe033c88445a23e3e7aef1"}, - {file = "ujson-5.12.1-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:4ea0c490c702c20495e97345acfcf0c2f3153e658ef537ff111929c48b89e10a"}, - {file = "ujson-5.12.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3e30fa6bc7156ed709e13f8b52e917db08fbfd611ba61346b62630974ec0ba8e"}, - {file = "ujson-5.12.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f67c5f0d64eba0fbbd6d2d6a79b0c43c5bc06f27564378fd5d716e0d40360068"}, - {file = "ujson-5.12.1-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8416bb724db9accfa97bdb77245952494b1800c23e42defd46afb5c661c9af19"}, - {file = "ujson-5.12.1-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:66005b49c753a1b9f2f8853919dc58e1e6bd66846ea341a33afa76c6d7602485"}, - {file = "ujson-5.12.1-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bdc6b277dcd27663f7fb76b6a5088424c66e0407c23e9884f80cd733f7d71b19"}, - {file = "ujson-5.12.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:7957b64583793042521f7f7c71c01626b3d32a17528eaab980eb8cdc3d4eec68"}, - {file = "ujson-5.12.1.tar.gz", hash = "sha256:5b7e96406c301a1366534479a7352ec40ec68bb327c0c119091635acd5925e35"}, + {file = "ujson-5.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:770643b4752266c5a466149848b78c3874940926a4ecef304f518b2b6cdb432f"}, + {file = "ujson-5.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8e8c1203cb1a27720debc334f840a9170da741503522f86999710cb4738fbe3"}, + {file = "ujson-5.13.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:65c1813fdd742fe3c249d9c417fa490e5b54e8a91bf343a88486ec50d175c444"}, + {file = "ujson-5.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5aa9bf16f0131812720dd4ae70bc1a0cf68f79e93c07c66100d328e75944b567"}, + {file = "ujson-5.13.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82c17b904c03c2b9629486ec91a8fa46a15f10d03504284f54ed7257a917d9f1"}, + {file = "ujson-5.13.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0b5f6983b2469db00e540b68fa8297b7a0ccd0d5173c60cc3e84f336b09395f"}, + {file = "ujson-5.13.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b877fe7926107d25d54b655c5b8dd94b294b22c157233163ad29fdb54ac10cf4"}, + {file = "ujson-5.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f3cae1c811e787b9500e2830af8632dcb32a78dea5baf15aac51d681c59a59dd"}, + {file = "ujson-5.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:820b78a6a183ab6591b2ea888020032ef0fe328d852af9a5c8d8084ababb2218"}, + {file = "ujson-5.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1209c985d1f4c2ae085ced7325509650cdb3533bb7294558dd1f26d48377942"}, + {file = "ujson-5.13.0-cp310-cp310-win32.whl", hash = "sha256:326553ae6c063c8246974906a6c137a0780fe46d143abebc52cd2cadda0f1814"}, + {file = "ujson-5.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:0354d6b50b0d153ed7c629845b18a953d0c727b7e768fd94a94e0602abfa1f29"}, + {file = "ujson-5.13.0-cp310-cp310-win_arm64.whl", hash = "sha256:7b4a05f61a96553995da6a4d502e07bc8aa5d07a90031df006239c6b00ce1c83"}, + {file = "ujson-5.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b7badefa73f96bad9e295ea22bd06967b851c8aad68c74196437e3584f25de5"}, + {file = "ujson-5.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:09effd42924a80df20a63b31a1ede905e66b0ce24aafe7a4cbedb05c783f8bb3"}, + {file = "ujson-5.13.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:89d0bfc986d02b4ce76b00e0f560bc8d30dfe8c05a1bfd8529e085eb6c1a77d9"}, + {file = "ujson-5.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cdd9618e07b3b142a02f0ab8227fd52453688b8e8e60ac0511f13a25fa8009db"}, + {file = "ujson-5.13.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0806683e8171ec06817e6af22f14ba0cd2f16def8a2ffb22a28a10615249355d"}, + {file = "ujson-5.13.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1cf46c79498c81f088cad4165b1669a78bba7bfbeb778c7cc1aff316e062b0d"}, + {file = "ujson-5.13.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2282039eb26f08ed1a1381360395f8a310f39a45ef7314cb0f258a7d2917ea3"}, + {file = "ujson-5.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c75eb7fac0fe92925b959cf2fa18f88d9fb76b10781fd2a6ccb895d5fb89171"}, + {file = "ujson-5.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:12078e81def2790140583abefc1b979f3c77be15d53c524bf0e232f669822052"}, + {file = "ujson-5.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e12192a37c6c0e476554b62647acdf6139a47b6f13d8bad8dd2316763c4cee12"}, + {file = "ujson-5.13.0-cp311-cp311-win32.whl", hash = "sha256:ae53b3f046529c193d533ca8111492330b204d6007611cdfa20e8b764c7c1389"}, + {file = "ujson-5.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:2275bbaaea3eddd2e8ec0863e28a420f5f520b14a760fc3f1e49fd07a974448c"}, + {file = "ujson-5.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:32a59e7151fe2fec8fdf9a565ee66fcf87918d48827e21cdab5e15ff9f274b78"}, + {file = "ujson-5.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bf81570ac056cb058f9117b52ca5dd800bfe9381d0076d0bb30a08a54591d654"}, + {file = "ujson-5.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7edf16359c52ed53406e216565d83e6b98c23c3cb9a0a01673f2493f8fb15edf"}, + {file = "ujson-5.13.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:24539618fb3243cfdf27dab9a850acab80798a01501e9586b61fb9ecd016a891"}, + {file = "ujson-5.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fdde6341d213b29f413b5fa9fad1392d5408074c75f0900ed949e97e546fa5df"}, + {file = "ujson-5.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:229faf041ef249ee3fd57bac1cedb123d2718ab63f6ccd50eca95ea902eb0dca"}, + {file = "ujson-5.13.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d02f31c2f59cc6a1c2c3633b377701fc2d8e876cc01950735d7a01132ccc233"}, + {file = "ujson-5.13.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea7204e9fa7538bfbb1396e1ee8c2bbcd3818b3633ef5bb14d4fdea52994d14d"}, + {file = "ujson-5.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c5a2478a3a1fa4421f7e035b87194eea0cf44c7971a3f32ad1b42a0dfd63c03"}, + {file = "ujson-5.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b535e0970c96957e999cfe5ec89361f0e8d0bb987fb5d5144f6f495cb3ed9e19"}, + {file = "ujson-5.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d0ad1207694988498fca7e0bb28eba7564fa33261d2f9fdf66a3aaab376b803"}, + {file = "ujson-5.13.0-cp312-cp312-win32.whl", hash = "sha256:d6bc9fa43a49e403c68c7eb164eef0feee9dd29474a7c6e0d3b6267025371990"}, + {file = "ujson-5.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:6692d49ff970aaa5008f4a6fe06974bc91fd957bf13173f765e46d8ba44906ea"}, + {file = "ujson-5.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:5737ffe0740a788b0e6255f0ffb281db49305fd6e6a587be44c73d9e92b554c4"}, + {file = "ujson-5.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46998fc8d11aec34a20e2010905e7059732a3d192d9a3c3fe4f9ffd146c87ec8"}, + {file = "ujson-5.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ee03ce288ba25b05cf0de87203165642277a25caa4f00a437e13152e5214e310"}, + {file = "ujson-5.13.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:cdf33b588a81b05d0b585c66f83050c49cb670623424d10e4d1ad37ba2f7eed9"}, + {file = "ujson-5.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4cabd73c114ce93c21d7db2e2d8e16217fd8a5b2b3ec754629eebef5c262d47f"}, + {file = "ujson-5.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ffc61fc756a64f4d169a78cc638d769e3c324f45fc51997626abf4e5e5dd6460"}, + {file = "ujson-5.13.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c00323c13a35822c9a67a26c0b2a0787510bf1ef490922b58009b362d1a3e21"}, + {file = "ujson-5.13.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:496e662a6b46d5f936d77fb68259cece19213bb2301ddd520dbd75ac7c90c5f4"}, + {file = "ujson-5.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7fd41b86444df14f8b4b7afaaa9f27bacfbf8c18380872317aeab6cd125dcede"}, + {file = "ujson-5.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bf3c2c4ea55d4187903fcdc689a9bf5b0fc72d8c0eaff39db18c1f337c8832c1"}, + {file = "ujson-5.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b6eca7751d61045a9b1e7f9a8c97ac24b164f085b60bef1c4668654bb2338011"}, + {file = "ujson-5.13.0-cp313-cp313-win32.whl", hash = "sha256:b63d3820f978bc8e98cc3f1fe26a33b0d2ea237733a23fe5e9cb5d51f466bd97"}, + {file = "ujson-5.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:17a59d5cf23ef98f7c9314524976b4b288374d83200add01d953024fb06404f9"}, + {file = "ujson-5.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:b49516fbe803ff30d6caa9ccc3799ec7f968992747ce3099eae4758928577b53"}, + {file = "ujson-5.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:cc9dfd41fed397ab03bb9d9fe1cbd83301211c772a17536033ce7d68877ac82b"}, + {file = "ujson-5.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ca7ef2fa6c408a7c0f558e4d33d93b32ddc35ed6d3cfc505747931a64b7465d5"}, + {file = "ujson-5.13.0-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:a554b2e5bee85030369514cef8b0b913cebe1a4c2c0c13541966d50bcba22b1a"}, + {file = "ujson-5.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ea939ff629ab03ae970d03eca6d1febd8ed55ba38ca44aec64ce997537cd3fa0"}, + {file = "ujson-5.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b98bf2faa5e37ecfe752226ea08290031e375a0c43d425a0b955fb3e702a2a71"}, + {file = "ujson-5.13.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a4b92344b16e414aeb609e57f62c466500e53c94f1698f5b149dc0b7223ec3e"}, + {file = "ujson-5.13.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7df805aad707507a1fa165fb716218ca3a89f142125dc4b23c9fcc08fa402d97"}, + {file = "ujson-5.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7576bdbef327c3528f011002a2d74486f6fe4e33289bdb7a042b7f1a6e9d8285"}, + {file = "ujson-5.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6eee5d7cce3f32a468905f9ff61807a60287a90258d849460f6fa826e810870d"}, + {file = "ujson-5.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:144e9d8a454cfa727e0f755e1863738ed68068583bda5463052cb446835bd56c"}, + {file = "ujson-5.13.0-cp314-cp314-win32.whl", hash = "sha256:576f35c35b918d67d41b933878062ec0a5c9f4d1e9e14e04aeef35384963feae"}, + {file = "ujson-5.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:d5e206e9f849ead27e51ef8da44e52b38da7c6dbd929a7340ab44533edcda8d7"}, + {file = "ujson-5.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:dc470179775468f9a007d3a6a2734624248c94bf47c6645e808c7e50a5070d1a"}, + {file = "ujson-5.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:69b4e36bb7d5f413ba8c00c8006b2ec627cc5ace97301462f6aadb66ec9d2979"}, + {file = "ujson-5.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8b644d50f66de5490c1823c7176618cead5e8e8a88cba9f40a6308ca52e79267"}, + {file = "ujson-5.13.0-cp314-cp314t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:15107aaa4f559d55201165ec32abb35c283a861be1fa67229578cb7d93fcd93a"}, + {file = "ujson-5.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6e343c5f0c058523f1edbf6ae4eceb4e0d934205a53bbdd8d9a945c83324662a"}, + {file = "ujson-5.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:02200035bc80e830f076ffc1b329a94c295aee6d9de8c9043647cb9a7bd4f76f"}, + {file = "ujson-5.13.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d7f19b81b73ff28f5c5022ee794f94122bfcda07a76423078e349465d71223a1"}, + {file = "ujson-5.13.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:82e1393e6dbe3c95fdfc95c6c528890e191351a1f024ef51126cf1f22543af52"}, + {file = "ujson-5.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38afcf994b28ed85ea2420e2a8d79a37d0a77348b3daf53850c16edda66f942d"}, + {file = "ujson-5.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1bdf2518971586f2b413156c49d9dd8b56cc990a8647081e1bd00af60564d469"}, + {file = "ujson-5.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:751ad01042472f1c7c02f5c597c7aee79834e82a6cc384ca302173bbc8e8deb8"}, + {file = "ujson-5.13.0-cp314-cp314t-win32.whl", hash = "sha256:74f3dd61aeb01b7b2a6754e400224e819279041b3867935a55ccf57fb86a43b2"}, + {file = "ujson-5.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:5c31317d5e4504dae8f98795358b6082fc0ef96e7394806db0a76a4a8717f446"}, + {file = "ujson-5.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aefd3c9c95f9b62348956396ff7b31818476f8f54dc4a4e64cbd4f0491db6fca"}, + {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3e074a1f7778d58aa3b3056bab7b6251aabb3f381808018ca2b7fb8dbdeef7ab"}, + {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8bb53ef95d35875262b8d0aa28506ca612ddd07058bee2a90f609938e69dc801"}, + {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fb296a0aa480ab88d895ddaa90372604c08ccc72323f02590612c775426ab413"}, + {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2862f81af44b3a7e74c5d80caa118d736be1991ce6f1d5c723716fa403060cc6"}, + {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c16e07581172f08585b409246f4535dab13ee85af0e3d3cfa8684b653ca44fa8"}, + {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:9bd0f2dd05937c3b089af316884de18c6f6182ddb8ffce597d2e7c7a9ba9f447"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:96e7e019b097b4b25fccddadb369d13f412c13695fcf0680b6bf906376156151"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:7892ea6dd85ede6d30fbbd22af1239b9d81dabdf9b7a8f10ca6d4464d4d9b8ab"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:e1842e10adc8f0db0d3e8aa3a1f8b05ce0456b39e180c8553d7f36dd0bf24b6b"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8bbb1f5ab810954fb307b6c5e68af58210c31da8569f9e6498a3958c1859e72"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3f6d55c68985654a84a9b47ac51f2655adac4fd264e4189f832960c2270dcf70"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b266f182d4bce74a6a9e1f86988485e8cd422efdcc7c3f537e00cc956f52678"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfaa8302eb9bb7f5e231f256caf83040760585e32751d19155c0f0c0225f8de1"}, + {file = "ujson-5.13.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:43dee3081b00fe447c5b9e2fe7ebfd57f7bcc5dd25b8a439c26c8c174dd581be"}, + {file = "ujson-5.13.0.tar.gz", hash = "sha256:d62e3d7625384c08082abad81a077af587fdef2761bb14c3822f4234b8d07d75"}, ] [[package]] From e2aa10b35f561fdcbbebff295c7a2e3c6f6481c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:15:40 +0100 Subject: [PATCH 10/76] chore(deps-dev): bump the dev-dependencies group across 1 directory with 3 updates (#8293) Bumps the dev-dependencies group with 3 updates in the / directory: [coverage](https://github.com/coveragepy/coveragepy), [pytest](https://github.com/pytest-dev/pytest) and [ruff](https://github.com/astral-sh/ruff). Updates `coverage` from 7.14.1 to 7.14.3 - [Release notes](https://github.com/coveragepy/coveragepy/releases) - [Changelog](https://github.com/coveragepy/coveragepy/blob/main/CHANGES.rst) - [Commits](https://github.com/coveragepy/coveragepy/compare/7.14.1...7.14.3) Updates `pytest` from 9.1.0 to 9.1.1 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/9.1.0...9.1.1) Updates `ruff` from 0.15.17 to 0.15.19 - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.15.17...0.15.19) --- updated-dependencies: - dependency-name: coverage dependency-version: 7.14.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: pytest dependency-version: 9.1.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: ruff dependency-version: 0.15.18 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 245 +++++++++++++++++++++++-------------------------- pyproject.toml | 2 +- 2 files changed, 116 insertions(+), 131 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6b3b292b8f6..4c06fed7558 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1399,118 +1399,103 @@ typeguard = "2.13.3" [[package]] name = "coverage" -version = "7.14.1" +version = "7.14.3" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "coverage-7.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3e3680291c4a1d0dadfa84a2c459576a4af5133abb617905714339a0c73138cf"}, - {file = "coverage-7.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5274669f37f2343635a347b91a60777621341ab3378e9c6ac9335eee704bddf"}, - {file = "coverage-7.14.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cfe5a5fec635799ef33428f1e5e61bafa45a92a96190ba731561ba558ccc214d"}, - {file = "coverage-7.14.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62a9f70b52e0b5a95cfef4a5c5641b06983cadc5e538a3feeb5c00211f523ac2"}, - {file = "coverage-7.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c18ebc343e15be53049b3a2dce38fe82d58f37e20ab9094b3a39c0aa4f6bb47"}, - {file = "coverage-7.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b84ffdf877644e7096aa936991efeed873f7f3df57b9cd001312b7668ab08550"}, - {file = "coverage-7.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e854312c4103f2ad4c0dc023b69b77ebfd2c89db5f86c4c94dc2353f9a92167e"}, - {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c643734307300234fafa36bf2a040a7235f8f177ea1fd6ec1423aea6fb7b929f"}, - {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:84ac9499e48700399a5dd0ea7085b5091961fec52c68d66b4ec0d3cf7f4441b1"}, - {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7f02d09f70776579b926d889a4c9c235070a1f47c40458aeaca563fae5acfdb5"}, - {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ce66d8e46da2bb5ee313a745cbd2e391d319176c1f7a9451bfcd3a2fb920859b"}, - {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c912c259304cfb5ee584481cfb7ce1ff932b4d61e6c9140b8f19cb7b5ed82332"}, - {file = "coverage-7.14.1-cp310-cp310-win32.whl", hash = "sha256:1238cb94638e610e972c60dac68e813f868dc7d6e982535270558443058d9d59"}, - {file = "coverage-7.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:fc459e5d73be2d6332fcfe8dbf3d8994671fe33c700f4565988ecfa511547253"}, - {file = "coverage-7.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:478b5bcd63c2e1357c5c7e16c070690df7b07f676b1c114d7b93e533c664309f"}, - {file = "coverage-7.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a24a81f9715ee42ef59a316cc11611c98fe23920f7c81861315c9f3ff4a230f4"}, - {file = "coverage-7.14.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:196a13319ad88d6d8ef5ab489ec4f44ddde2143c0c7d5b27786f6c3ffd56a7e1"}, - {file = "coverage-7.14.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d452fd08b5c72c5167c93e6867b5c08500bd40f2a21e1e854a500550b6cc36f"}, - {file = "coverage-7.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23bf7fa51ac02e07fc7c96849b82946da47ae862dc8f86d183b2a4864fc38129"}, - {file = "coverage-7.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcaa50684dcaadfa599ac48f81103c756d791cfd85c97203d2217c593d48b860"}, - {file = "coverage-7.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4ea1c034f95c9b056e856b794630b17f9fa3d57e4800ff1e503d3be0f9c9078c"}, - {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c7e057326434e441306226fbeb5d1aaf14a2637efe97ba668306635835f32ad7"}, - {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59baf88468dbc8d63b1887afd92bda52e40bb1561696e5819670601403810cec"}, - {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d75f892b3ab73ba11cab5442cce7b3e168fd64162b16f0e1e0d09c508edef"}, - {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3a56abc20a472baf0304c455721bc601477440d28ecfde8a03dde79ede07e0df"}, - {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a3cb83d1552c0cd1b4906655b6a33fd4a8473229633a901c6b73bf86914dee9"}, - {file = "coverage-7.14.1-cp311-cp311-win32.whl", hash = "sha256:10274a1fbeb8ec5d72966e17bb198a3104257aca4ac09d98667c5f8aca8c8548"}, - {file = "coverage-7.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:87ebdf787d4888e3f3f2d523eadc6e18c6d18c6d0eb173801a189641627fb37e"}, - {file = "coverage-7.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:dd34767fa19848d35659ffc0a75314f58c7af3f1cd87ec521e8292a1238398a3"}, - {file = "coverage-7.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a06c76364a9360e33d6d23769aefdf7f66f38e2ffb60ceb1baaa4989d83b695c"}, - {file = "coverage-7.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fad54e871165f6ec2f536063ac74c3104508a12963e64072ba44bd822de52b0c"}, - {file = "coverage-7.14.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:84b535f00655ecafe1d929d1fb00ed5d6fa3051ea643ab2c161a3887b86f294b"}, - {file = "coverage-7.14.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b6b0853b895fe0e98cbfc580d1ec3393d9302b4b1e96a77b3f5c91fdab899e6"}, - {file = "coverage-7.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:442cc9c952b2df400cda54bb04ab87330cf2cd08a8692cbbea36773531eb6f37"}, - {file = "coverage-7.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8270544c361ed405a27a060dbc9ed2c124b084d96dfdc2d9a2510482aef981ad"}, - {file = "coverage-7.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:48b283b1dd6372e8de2a7a9a4c4d5dc06f4d4fd209b876f3c88a7a205a0c8f84"}, - {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5b0c99ba93a07d56f6df340bb79be53202a082b2fdb81bfe6190b741a3470d54"}, - {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e471bc5769ff073b058cfadb0d736b56ce067c8560eabeb0da88462df98c23e7"}, - {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f497a1ea81d4cd7c10ddcaa685135b9aabd291af3d55775a9ddf3cb7a364cdd9"}, - {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2222be86d0b54f5dd5a38f45f17f315f737245e857bf0bdedc70734f84a13c02"}, - {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:85e85586565842f6932abebd4c18bcb1074223dc0b3576e7d173ca710622813a"}, - {file = "coverage-7.14.1-cp312-cp312-win32.whl", hash = "sha256:4a28fd227808366b196a75476dced2eb35b351d6766ba9c858dc93319e87f4f1"}, - {file = "coverage-7.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:54acdb6674a4661768d7bf7db32dfb9f46ab1d764f8aba6df75ce1a6a088724e"}, - {file = "coverage-7.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:99cd41ff91afd94896fea3bc002706b6ae4ce95727d06e4a0f39c0a8d8bd8b1a"}, - {file = "coverage-7.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:be9f2c802dcfce3f71298303aa5dad0dce440a76c52f2f60dacd8656dab78793"}, - {file = "coverage-7.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6223a72fd0e4c7156353ec0f08a5f93623e1d3034d0e2683b9bb8ea674131b1d"}, - {file = "coverage-7.14.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7279d2110a28cebc738b6459ecda2771735a4c18465fbbd36b3288fe5ed92247"}, - {file = "coverage-7.14.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9eeb3fcbc13ba40dfbdb22d01d196a28e9cef9ed4c29b60061a1e0e823a9929d"}, - {file = "coverage-7.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f0cfc27c539f07cf5c0a4cfe211d0b6cae039f8f40526dbaa71944e64b50a7b"}, - {file = "coverage-7.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:221c70f316241a78e77e607c227cefc8808d4e08f28d99c04f35694690e940be"}, - {file = "coverage-7.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da028256b04ec30e5e0114b6f76172938c313991f0a2d3d894271315cf5d5e43"}, - {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76a085d7005236a767e3426148b2c407e53ad61695c562f8a81da2d373324901"}, - {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b553d04b5e778a8e56d57eb134aff42a92718ecba45e79c4764ecfa40efd92ff"}, - {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:46f714d2fb8ae2f4f29f23ada7f1e79b759fff5a70f94a1dac23af204c3ec9e4"}, - {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1896f5e19ff3f0431c7ce2172adc54890fd97f86b59ced8ca1649145d9ffe35d"}, - {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:62fd185ef9df3c33d1c8178c5af105f762afbad96038de9a4ae100aa6297ca33"}, - {file = "coverage-7.14.1-cp313-cp313-win32.whl", hash = "sha256:ab4af6352741a604c431c6072fce5bee33bf0f20dc7a56618d6bf6bb89e9810c"}, - {file = "coverage-7.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:7af486dabe8954d03b087f0021540897afe084f04e16ff5579e08cc46f871416"}, - {file = "coverage-7.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:2224f89ffd0c5605ccce1ed7a584da162bc7c55f601ab1c946bc9de31a486b42"}, - {file = "coverage-7.14.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de286598cc65d2b489411174b1faec2f5a7775fb3201fd925db2a76b4030f37d"}, - {file = "coverage-7.14.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:042c46ded7c288aeb07cf14a28b6c1e10b78fcba40171c3fa1e939377eeef0b5"}, - {file = "coverage-7.14.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f4ddbe407477f04c45115d1a4e5bc480f753553b534d338d4c3358b1cdd0ea52"}, - {file = "coverage-7.14.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d13e6725992e2d2fd7d81d4f5241952d13740121dfd501da09201be39b2c003a"}, - {file = "coverage-7.14.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f747dc8edcfe740130f28f32f3995e955494285717e86ee25af51db2219df08a"}, - {file = "coverage-7.14.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced2f09ef276fd58611a1ef502164ad266d2b75174e5a40cabbdb4033f9f6cf2"}, - {file = "coverage-7.14.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b84800013769a78ccb9ef4659402e26d06867e337b61ec365f77ad008adea80e"}, - {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ea8cd6ca0ee9f616aaef3afc6882e32c2cbf18b00d96313ffd76af650574034d"}, - {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:aa5e304a873fabddc11e484e9b6b738bd38bd7bed17b09aa84eecf5332e8b8bb"}, - {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5a1c5215be81035e629d5bc756650634d0bf31991038db7a0eccb90f025ce16d"}, - {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:79058c47dae6788504b5effb319961bcd72d7240551464b91d474bc0ed186d69"}, - {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:370c5afae3fa0658e11694a32b24c2778f6bc2d17718121f94ee185e69f26b54"}, - {file = "coverage-7.14.1-cp313-cp313t-win32.whl", hash = "sha256:3758dd0a7f1fa57365ef2e781df0f0731d38b6e3772259d13dae4bd8a958d4b1"}, - {file = "coverage-7.14.1-cp313-cp313t-win_amd64.whl", hash = "sha256:6ff665fb023a77386fe11685190cee1f60a7d635994a30d9b0a061533d470fce"}, - {file = "coverage-7.14.1-cp313-cp313t-win_arm64.whl", hash = "sha256:17a5a241e5997621a956a7f402a7433ef4221e5152809b785bec79e2323799f1"}, - {file = "coverage-7.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d5ed429d0b8edaac649e889b4ffcedb6c80b06629a3f93050e3dddfb99235bee"}, - {file = "coverage-7.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8011224a62280e50dab346960c03cf47aca1a1e09e608c0fb33fd6e0cc8e9500"}, - {file = "coverage-7.14.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:12c42ec1e14f553c4f817e989365982e646e27211f10a0f717855b94a79c8906"}, - {file = "coverage-7.14.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06144cd511cf2624873a035c5069cf297144f6e77a73ee3d7a55b605ec5efb42"}, - {file = "coverage-7.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a311d8e1da24be5c1ccf85cbfb06315dbaa1703d5a1eab3f6432c72b837917c8"}, - {file = "coverage-7.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c79cead5b5bc584d9c71451cb984d0e3a84e0c0937379c8efcbf27c8d661b851"}, - {file = "coverage-7.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dcbf65f1f66a26cdd88c35cf68fb4729c5d1cd2e88added72420541dfb212034"}, - {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fd86572566fb40189a8260446158235159bc7a82dfbc87a3b39cf4fb57fcec1c"}, - {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:7771b601718fdde84832c3a434ca9bbf4ae9adbc49d84198b4110700c3c77c36"}, - {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:39b21e212c55af06fa375e3dbf90a8a8e38792f3a910c580066d23563830ddd5"}, - {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f2302660e32562a532b442480121aef8aa61a5bdb20b30bf0adab29f10a5a4b4"}, - {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:03a6f93c1ec3b7f2e77b5dbcc5573a2c21f12529a5c6bbe0f16f72303cc2fa4d"}, - {file = "coverage-7.14.1-cp314-cp314-win32.whl", hash = "sha256:8a3ce026d73290f42f08dafecbd82c193a74df280461fbf97300fec51fd133ee"}, - {file = "coverage-7.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:114c95ef29302423b87d159075805f4ab973254a2638a5d7d046c94887cc87d7"}, - {file = "coverage-7.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:a07891c3f4805442b31b71e84ba3cf29ed1aa9a428284e06deeb4b23e5b46343"}, - {file = "coverage-7.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1101a5ebb083aecb625ebb6209d4105b58f647b093cb2dc8122d7b33f743cfe1"}, - {file = "coverage-7.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:851b9e1e4e8a4608e77c79714b2e77c0970d2ed7202a05e92ae407817481887b"}, - {file = "coverage-7.14.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d5b89cdfb2ee051b71e8c3c70bd81a9eff81100f736a269136fe1a68efe00474"}, - {file = "coverage-7.14.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0177614a0370f227888b4e436a7c55686d6a9f90eb1ade2b624ba685a1686e86"}, - {file = "coverage-7.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d69af5dea2de76fc485a83032a630523f985198b7e25be901ec60181587b01e"}, - {file = "coverage-7.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:35ab22d91de736e8966b980dc355cbcdd2c6dbbcfe275f9a2991bc8a91b3df65"}, - {file = "coverage-7.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:357d4e32935c36588aaba057d734fa32428c360c9fc2e4442afbf1b646beee6e"}, - {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:51bd64741cc6fa065abd300ede1afe5a5291ece9c31da8b24884deda48bcc3f8"}, - {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9132cd363a68a4c3daa7c8704a654b1e39d3360f6f5b8ddd470608a945236c07"}, - {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07c6290b1697b862c0478eab545eec949a0d0e4d6d03497f446d706da3b4f2de"}, - {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5ea0c297e27133853b4d8a3eb799bff5a2dbd9f2f41537a240d337ac9b4df890"}, - {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:01b7733daad0237daa01ef80fe2dfceffc911e6a17fa7b55d14aa8214eaaaecd"}, - {file = "coverage-7.14.1-cp314-cp314t-win32.whl", hash = "sha256:6adc5a36984624a70bf11d7184e20fa0a49aa7c47ffab43804106a1a695ea22e"}, - {file = "coverage-7.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ddf799247318f34dbcd2efa8c95a8d0642674e926bb1774cf9b63dfd2a389d1c"}, - {file = "coverage-7.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:145986fe66647eb489f18d9a997567a3fd358584c4b5a808769113abc07466af"}, - {file = "coverage-7.14.1-py3-none-any.whl", hash = "sha256:a252f21c27e38347e60111a3266b03827422a7d5525951aceee313aa68bab1d2"}, - {file = "coverage-7.14.1.tar.gz", hash = "sha256:30c08f7d90415aa98b3c990385dea2939b0da55f38515e5b369b83655f8523be"}, + {file = "coverage-7.14.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:360bec1f58e7243e3405d3bdf7a1a8115aa9b448d54dc7cd6f7b7e0e9406b62e"}, + {file = "coverage-7.14.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed68faa5e85de2f3e400bc3f122e5c82735a58c8bb24b9f63a2215954ba17b2d"}, + {file = "coverage-7.14.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:830c1fca669c572dec37ce9c838224ee45aac5be0f6961edf871e82e49d6537c"}, + {file = "coverage-7.14.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a64caee2193563601dbaaa55fe2dcf597debef04a2f8f1fa8a07aa4bb7ac7a1e"}, + {file = "coverage-7.14.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0096fd7559178f0cc9cf088f2dbd2a02ef85bacaa69732c633517286b4494610"}, + {file = "coverage-7.14.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6197e5a00183c11a8ce7c6abd18be1a9189fd8399084ffc95196f4f0db4f2137"}, + {file = "coverage-7.14.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7dfe427045520d6abca33687dfef767b4f635015893a1816c5decb12eb72ce18"}, + {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9a3f142070eb7b82fc4085a55d887396f9c4e21250bccebe2ba22502c45b9647"}, + {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64b2055bb6e0dc945af35cdeceb3633e6ed9273475ef3af85592410fd6803803"}, + {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1551b4caac3e3ec9f2bfcec6bf3776e01c0edbdd2e240431a50ca1a1aac72c27"}, + {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:583d50d59142f8549470bd6390471d0fe8b8c8d69d6a0f28ac71e05380cef640"}, + {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0bb8a6bc7015efdf8a928753b25da1b9ca2d6f24ef04d2ee0688e486f32aae7"}, + {file = "coverage-7.14.3-cp310-cp310-win32.whl", hash = "sha256:d48400185564042287dc487c1f016a3397f18ab4f4c5d5ec36edc218f7ffa35b"}, + {file = "coverage-7.14.3-cp310-cp310-win_amd64.whl", hash = "sha256:eadea7aba74e40adee867a8c0eec17b820b061d308a4b014f7a0e118c2b0aa61"}, + {file = "coverage-7.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e574801e1d643561594aa021206c46d80b257e9853087090ba97bed8b0a509d3"}, + {file = "coverage-7.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f82b6bb7d75a2613e85d07cefa3a8c973d0544a8993337f6e2728e4a1e94c305"}, + {file = "coverage-7.14.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a2335ea5fed26af2e831094964fa3f8fae60b45f7e37fcc2d3b615b2add3ad87"}, + {file = "coverage-7.14.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fbb8c3a98e779013786ae01d229662aeacbc77100efbd3f2f245219ace5af700"}, + {file = "coverage-7.14.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac082660de8f429ba0ea363595abb838998570b9a7546777c60f413ab902bbde"}, + {file = "coverage-7.14.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ac012839ff7e396030f1e94e10553a431d14e4de2ab65cb3acb72bbd5628ca2"}, + {file = "coverage-7.14.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5952f8c1bda2a5347154450379316e6dfa4d934d62ca35f6784451e6f55074fb"}, + {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8cf0f2509acb4619e2471a1951089054dd58ebea7a912066d2ea56dd4c24ca4a"}, + {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2e41fd3aab806770008279a93879b0924b16247e09ab537c043d08bbca53b4ab"}, + {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f0a47095963cfe054e0df178daca95aec21e680d6076da807c3add28dfe920f7"}, + {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:a090cbf9521e78ffdb2fcf448b72902afe9f5923ff6a12d5c0d0120200348af9"}, + {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d310baf69a4fbe8a098ce727e4808a34866ac718a6f759ae659cbd3221358bc"}, + {file = "coverage-7.14.3-cp311-cp311-win32.whl", hash = "sha256:74fdd718d88fe144f4579b8747873a07ec3f04cb837d5faec5a25d9e22fa31a8"}, + {file = "coverage-7.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:cc96aa922e21d4bc5d5ed3c915cef27dfcbc13686f47d5e378d647fbfba655a2"}, + {file = "coverage-7.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:c66f9f9d4f1e9712eb9b1de5310f881d4e2188cfcba5065e1a8490f38687f2c4"}, + {file = "coverage-7.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3d74ff26299c4879ce3a4d826f9d3d4d556fd285fde7bbce3c0ef5a8ab1cec24"}, + {file = "coverage-7.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:96150a9cf3468ea20f0bc5d0e21b3df8972c31480ef90fa7614b773cc6429665"}, + {file = "coverage-7.14.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:27d07a46500ba23515b838dbcf52512026af04090755cf6cc64166d88c9b9a1a"}, + {file = "coverage-7.14.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:621e13c6108234d7960aaf5762ab5c3c00f33c30c15af06dcbff0c73bf112727"}, + {file = "coverage-7.14.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b60ca6d8af70473491a15a343cbabab2e8f9ea66a4376e81c7aa24876a6f977"}, + {file = "coverage-7.14.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c90a7cdd5e380e1ce02f19792e2ac2fbfbf177e35a27e69fd3e873b30d895c0c"}, + {file = "coverage-7.14.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5d788e5fd55347eef06ca0732c77d04a264de67e8ff24631270cdff3767a60cf"}, + {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62c7f79db2851c95ef020e5d28b97afde3daf9f7febcd35b53e05638f729063f"}, + {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:90f7608aeb5d9b60b523b9fb2a4ee1973867cc4865a3f26fe6c7577073b70205"}, + {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1e3b91f9c4740aeb571ecf82e5e8d8e4ab62d34fcb5a5d4e5baa38c6f7d2857c"}, + {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c946099774a7699de03cbd0ff0a64e21aed4525eed9d959adde4afe6d15758ef"}, + {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:16b206e521feb8b7133a45754643dead0538489cf8b783b90cf5f4e3299625fd"}, + {file = "coverage-7.14.3-cp312-cp312-win32.whl", hash = "sha256:ea3169c7116eb6cdf7608c6c7da9ecfcb3da40688e3a510fac2d1d2bafd6dc35"}, + {file = "coverage-7.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:7ea52fc08f007bcc494d4bb3df3851e95843d881860ba38fe2c64dc100db5e7d"}, + {file = "coverage-7.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:8cec0ad652ec57790970d817490105bd917d783c2f7b38d6b58a0ca312e1a336"}, + {file = "coverage-7.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:47968988b367990ae4ab17523790c38cd125e02c6bfd379b6022be2d40bdc38c"}, + {file = "coverage-7.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0ee68f5c34812780f3a7063382c0a9fcbb99985b7ddcdcaa626e4f3fb2e0783a"}, + {file = "coverage-7.14.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fa9e5c6857a7e80fa22ace5cf3550ae392bbfc322f1d8dd2d2d5a8be38cec027"}, + {file = "coverage-7.14.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:98a0859b0e98e43e1178a9402e19c8127766b14f7109a374d976e5a62c0e5c73"}, + {file = "coverage-7.14.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69918344541ed9c8368566c2adc03c0e33d4550d7faa87d1b35e49b6a3286ea9"}, + {file = "coverage-7.14.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b7f300ac92cd4b570724c8ffbbd0c130fee298d2447f41d5a3abf58976fae1de"}, + {file = "coverage-7.14.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11a7ec9f97ab950f4c5af62229befc7faf208fdbc0116d3902d7e306cf2c5abd"}, + {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a571bd889cd36c5922ce8e42e059f9d37d02301531d11374afa4c87a578625d5"}, + {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de76caefc8deabb0dd1678b6a980be97d14c8d87e213ac194dbf8b09e96d63fb"}, + {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d20a15c622194234161535459affa8f7905830391c9ccfa060d495dbfe3a1c7f"}, + {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b488bd4b23397db62e7a9459129d01ff06a846582a732efd24834b24a6ada498"}, + {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a3693b4153394d265f44fb855fdc80e72403024d4d6f91c4871b334d028e4e0"}, + {file = "coverage-7.14.3-cp313-cp313-win32.whl", hash = "sha256:338b19131ab1a6b767b462bfcbaa692e7ae22f24463e39d49b02a83410ff6b37"}, + {file = "coverage-7.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:b3d77f7f196abdef7e01415de1bce09f216189e83e58159cfeef2b92d0464994"}, + {file = "coverage-7.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:e6230e688c7c3e65cedd41a774eb4ec221adc6bfee13768231015b702d5e4150"}, + {file = "coverage-7.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:605ab2b566a22bd94834529d66d295c364aba84afd3e5498285c7a524017b1fc"}, + {file = "coverage-7.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a3c2134809e80fac091bfed18a6991b5a5eb5df5ae32b17ac4f4f99864b73dd7"}, + {file = "coverage-7.14.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c02efd507227bde9969cab0db8f48890eb3b5dcad6afac57a4792df4133543ce"}, + {file = "coverage-7.14.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1bb93c2aa61d2a5b38f1526546d95cf4132cb681e541a337bf8dfd092be816e5"}, + {file = "coverage-7.14.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f502e948e03e866538048bba081c075caaa62e5bda6ea5b7432e45f587eb462a"}, + {file = "coverage-7.14.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9973ef2463f8e6cfb61a6324126bb3e17d67a85f22f58d856e583ea2e3ca6501"}, + {file = "coverage-7.14.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9be4e7d4c5ca0427889f8f9d614bd630c2be741b1de7699bca3b2b6c0e41003e"}, + {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a574912f3bde4b0619f6e97d01aa590b70998859244793769eb3a6df78ee56d3"}, + {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:e343fb086c9cd780b38622fea7c369acd64c1a0724312149b5d769c387a2b1f5"}, + {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:3c68df8e61f1e09633fefc7538297145623957a048534368c9d212782aa5e845"}, + {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3e5b550a128419373c2f6cec28a244207013ef15f5cbcff6a5ca09d1dfaaf027"}, + {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2bfc4dd0a912329eccc7484a7d0b2a38032b38c40663b1e1ac595f10c457954b"}, + {file = "coverage-7.14.3-cp314-cp314-win32.whl", hash = "sha256:0423d64c013057a06e70f070f073cec4b0cbc7d2b27f3c7007292f2ff1d52965"}, + {file = "coverage-7.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:92c22e19ce64ca3f2ad751f16f14df1468b4c231bd6af97185063a9c292a0cb3"}, + {file = "coverage-7.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:41de778bd41780586e2b04912079c73089ab5d839624e28db3bdb26de638da92"}, + {file = "coverage-7.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8427f370ca67db4c975d2a26acfc0e5783ca0b52444dbc50278ace0f35445949"}, + {file = "coverage-7.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d8e88f335544a47e22ae2e45b344772925ec65166555c958720d5ed971880891"}, + {file = "coverage-7.14.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:beaab199b9e5ceaf5a225e16a9d4df136f2a1eae0a5c20de1e277c8a5225f388"}, + {file = "coverage-7.14.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3ff255799f5a1676c71c1c32ec01fd043aa09d57b3d95764b24992757184784"}, + {file = "coverage-7.14.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:878832eaac515b62decfa76965aed558775f86bf1fc8cca76993c0c84ae31aed"}, + {file = "coverage-7.14.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:611e62cb9386096d81b63e0a05330750268617231e7bd598e1fe77482a2c58a5"}, + {file = "coverage-7.14.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:02c41de2a88011b893050fc9830267d927a50a215f7ad5ec17349db7090ccf26"}, + {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:526ce9721116af23b1065089f0b75046fe521e7772ab94b641cd66b7a0421889"}, + {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e4ed44705ca4bead6fc977a8b741f2145608289b33c8a9b42a95d0f15aedbf4d"}, + {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2415902f385a23dcc4ccd26e0ba803249a169af6a930c003a4c715eeb9a5444e"}, + {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b75ee850fc2d7c831e883220c445b035f2224de2ba6103f1e56dbd237ab913f7"}, + {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dc9b4e35e7c3920e925ba7f14886fd5fbe481232754624e832ddba66c7535635"}, + {file = "coverage-7.14.3-cp314-cp314t-win32.whl", hash = "sha256:7b27c822a8161afbe48e99f1adfb098d270ae7e0f7d7b0555ce110529bdb69cc"}, + {file = "coverage-7.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:39e1dbbb6ff2c338e0196a482558a792a1de3aa64261196f5cdb3da016ad9cda"}, + {file = "coverage-7.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:68520c90babfa2d560eca6d497921ed3a4f469623bd709733124491b2aa8ef3f"}, + {file = "coverage-7.14.3-py3-none-any.whl", hash = "sha256:fb7e18afb6e903c1a92401a2f0501ac277dca527bb9ca6fe1f691a8a0026a0e8"}, + {file = "coverage-7.14.3.tar.gz", hash = "sha256:1a7563a443f3d53fdeb040ec8c9f7466aed7ca3dc5891aa09d3ca3625fa4387f"}, ] [package.dependencies] @@ -3649,14 +3634,14 @@ extra = ["pygments (>=2.19.1)"] [[package]] name = "pytest" -version = "9.1.0" +version = "9.1.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pytest-9.1.0-py3-none-any.whl", hash = "sha256:8ebb0e7888bdf2bdfc602ec51f8f62d50200af37356c74e503c79a94f5c81f32"}, - {file = "pytest-9.1.0.tar.gz", hash = "sha256:41dd9148c08072446394cefd3d79701701335a9f4cae69ba92e39f6c7f5c061c"}, + {file = "pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c"}, + {file = "pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313"}, ] [package.dependencies] @@ -4335,30 +4320,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.17" +version = "0.15.19" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ruff-0.15.17-py3-none-linux_armv6l.whl", hash = "sha256:d9feddb927fc68bd295f5eebc587a7e42cfaf9b65f60ca4a2386febff575da8f"}, - {file = "ruff-0.15.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:25805a226d741c47d274a35ad5c10a7dde175fcddfa511d7cf3da0a21eb3eab7"}, - {file = "ruff-0.15.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f6ad73b14c2d18a3bf8ad7cb6974294d7f613a7898604826058e6ac64918ef4d"}, - {file = "ruff-0.15.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ba0c1e4f95bcb3869d0d30cbd5917071ef2e28665abfec970cdab0492c713ed"}, - {file = "ruff-0.15.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81647960f10bff57d2e51cadd0c3950fe598400c852863a038720ef5b8cca91e"}, - {file = "ruff-0.15.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e01a84ddbc8c16c23055ba3924476850f1bbc1917cebbb9376665a63e74260d"}, - {file = "ruff-0.15.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fe9f653152f8f294f9f7e03bf3a453d8b4a27f7a59c78c8666167f2b17b96c"}, - {file = "ruff-0.15.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c0fe88a7676e7a05b73174d4d4a59cb2ac21ff8263583f87a81a6018475a978"}, - {file = "ruff-0.15.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecfc3c7878fff94633ab0348524e093f9ce3243080416dd7d14f8ba400174719"}, - {file = "ruff-0.15.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b8461180b22420b1bdc289909410930761629fddf2a5aaf60fae1ab26cedc4c4"}, - {file = "ruff-0.15.17-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6eccbe50a038b503e7140b441aa9c7fc8c1f36edf23ebef9f4165c2f28f568b7"}, - {file = "ruff-0.15.17-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:382fc0521025f5a8ad447d8bdd523545d0d7646adb718eb1c2dac5065ec27c0f"}, - {file = "ruff-0.15.17-py3-none-musllinux_1_2_i686.whl", hash = "sha256:456d41fcd1b2777ad63f09a6e7121d43f7b688bbc76a800c10f7f8fb1f912c3f"}, - {file = "ruff-0.15.17-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b1a04bcc94ae6194e9db05d16ad31f298a7194bfbcb08258bbe589cee1d587b8"}, - {file = "ruff-0.15.17-py3-none-win32.whl", hash = "sha256:596065960ab1ff593f744220c9fe6580eda00a95003cffa9f4048bb5b1bf0392"}, - {file = "ruff-0.15.17-py3-none-win_amd64.whl", hash = "sha256:6769e5fa1710b179b92e0bfa5a51735b35baea9013dadb06d5f44cbcf9547084"}, - {file = "ruff-0.15.17-py3-none-win_arm64.whl", hash = "sha256:f3be1fbb34bcdfd146240d8fb92a709d4c2c8191348580a3c044ec60fa0b4456"}, - {file = "ruff-0.15.17.tar.gz", hash = "sha256:2ec446937fd16c8c4de2674a209cc5af64d9c6f17d21fbf1151054fa0bcf5219"}, + {file = "ruff-0.15.19-py3-none-linux_armv6l.whl", hash = "sha256:922d1eb283161564759bd49f507e91dc6112c15da8bd5b84ed714e086243cf86"}, + {file = "ruff-0.15.19-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4d190d8f62a0b94aba8f721116538a9ee29b1e74d26650846ba9b99f0ae21c40"}, + {file = "ruff-0.15.19-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5a2c86ba6870dd415a9d9eb8be94d7924ebec6a26ffc7958ec7ca29d4bff967d"}, + {file = "ruff-0.15.19-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b432bc087264aea70fd25ac198918b70bd9e2aa0db4297b0bb91bbfbbc63ce"}, + {file = "ruff-0.15.19-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8530a09d03b3a8c994f8b559a7dcdabc690bcd3f78ef276c38c83166798ebf56"}, + {file = "ruff-0.15.19-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87bf21fb3875fe69f0eacc825411657e2e85589cce633c35c0adf1113649c62b"}, + {file = "ruff-0.15.19-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9b229cb3ef56ecc2c1c8ebeca64b7a7740ccaef40a9eb097e78dde5a8560b83"}, + {file = "ruff-0.15.19-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c754515be7b76afe6e7e62df7776709571bcfc1631183828afcf3bafa869e3"}, + {file = "ruff-0.15.19-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a498f82e0f4d8904c4e0aea5139cdfac1f39d19a3c51d491292f63a36e83b2e"}, + {file = "ruff-0.15.19-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d48caa34488fb521fd0ef4aea2b0e8fe758298df044138f0d67b687a6a0d07ed"}, + {file = "ruff-0.15.19-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4171b6613effa9363cd46dd4f75bd1827b6d1b946b5e278ed0c600d305379445"}, + {file = "ruff-0.15.19-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:27c15b2a241dd4d995557949a094fe78b8ad99122a38ccae1595849bcc947b3f"}, + {file = "ruff-0.15.19-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ed03b7862d68f0a8771d50ee129980cbf1b113f96e250b73954bc292f689e0bb"}, + {file = "ruff-0.15.19-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:08143f0685ae278b30727ea72e90c61e5bd9c31b91aac4f5bb989538f73d24b8"}, + {file = "ruff-0.15.19-py3-none-win32.whl", hash = "sha256:8f47f0f92952af2557212bb10cf3e695cd4cf28b2c6e42cdb18ec6c9ebfa19da"}, + {file = "ruff-0.15.19-py3-none-win_amd64.whl", hash = "sha256:efeca47ee3f9d4a7162655a3b8e6ee4a878646044233978d4d2c1ff8cdd914f0"}, + {file = "ruff-0.15.19-py3-none-win_arm64.whl", hash = "sha256:6c6b607466e47349332eb1d9be52fb1467423fc07c217341af41cd0f3f0573be"}, + {file = "ruff-0.15.19.tar.gz", hash = "sha256:edc27f7172a93b32b102687009d6a588508815072141543ae603a8b9b0823063"}, ] [[package]] @@ -5232,4 +5217,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "8488be13a2ba128328fae0a536084af7a459cc9dd4eb79fb00006f60052d4839" +content-hash = "9f01df9bb0aee394e4821f5d66548c584c22fbbc3d12af9bc3cca7e32a835537" diff --git a/pyproject.toml b/pyproject.toml index 0e06b7efaa3..ea2a9c38b61 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -116,7 +116,7 @@ types-python-dateutil = "^2.8.19.6" aws-cdk-aws-appsync-alpha = "^2.59.0a0" httpx = ">=0.23.3,<0.29.0" sentry-sdk = ">=1.22.2,<3.0.0" -ruff = ">=0.5.1,<0.15.18" +ruff = ">=0.5.1,<0.15.20" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.9" types-redis = "^4.6.0.7" From e6f0e63c6ca45afe1e9b282e744403c3777fbb10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:18:14 +0100 Subject: [PATCH 11/76] chore(deps): bump the github-actions group with 2 updates (#8292) Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter). Updates `actions/checkout` from 6.0.3 to 7.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) Updates `release-drafter/release-drafter` from 7.3.1 to 7.4.0 - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/693d20e7c1ce1a81d3a41962f85914253b518449...ed4bc48ec97379be2258e7b7ac2624a3e26ab809) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: release-drafter/release-drafter dependency-version: 7.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .github/workflows/bootstrap_region.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/ossf_scorecard.yml | 2 +- .github/workflows/pre-release.yml | 10 +++++----- .github/workflows/publish_v3_layer.yml | 4 ++-- .github/workflows/quality_check.yml | 2 +- .github/workflows/quality_check_docs.yml | 2 +- .github/workflows/quality_code_cdk_constructor.yml | 2 +- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release-v3.yml | 14 +++++++------- .../workflows/reusable_deploy_v3_layer_stack.yml | 2 +- .github/workflows/reusable_deploy_v3_sar.yml | 2 +- .github/workflows/reusable_publish_changelog.yml | 2 +- .github/workflows/reusable_publish_docs.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- .github/workflows/secure_workflows.yml | 2 +- 17 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index 2f095a63a51..c464909367b 100644 --- a/.github/workflows/bootstrap_region.yml +++ b/.github/workflows/bootstrap_region.yml @@ -44,7 +44,7 @@ jobs: environment: layer-${{ inputs.environment }} steps: - name: checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ github.sha }} - name: Setup Node.js diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a0ae48f9f6a..252d7d2ca98 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index f91282cb627..4d0770f3a4a 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -20,6 +20,6 @@ jobs: pull-requests: write steps: - name: 'Checkout Repository' - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: 'Dependency Review' uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index d986af34dd3..cb8c8880690 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -22,7 +22,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index f4fd53b8a23..776cb86673c 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -59,7 +59,7 @@ jobs: artifact_name: ${{ steps.seal_source_code.outputs.artifact_name }} RELEASE_VERSION: ${{ steps.release_version.outputs.RELEASE_VERSION }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -99,7 +99,7 @@ jobs: contents: read steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -140,7 +140,7 @@ jobs: attestation_hashes: ${{ steps.encoded_hash.outputs.attestation_hashes }} steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -209,7 +209,7 @@ jobs: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} steps: # NOTE: we need actions/checkout in order to use our local actions (e.g., ./.github/actions) - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -233,7 +233,7 @@ jobs: runs-on: ubuntu-latest steps: # NOTE: we need actions/checkout to authenticate and configure git first - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} diff --git a/.github/workflows/publish_v3_layer.yml b/.github/workflows/publish_v3_layer.yml index e61462b572c..c73de63808d 100644 --- a/.github/workflows/publish_v3_layer.yml +++ b/.github/workflows/publish_v3_layer.yml @@ -108,7 +108,7 @@ jobs: working-directory: ./layer_v3 steps: - name: checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -264,7 +264,7 @@ jobs: pages: none steps: - name: Checkout repository # reusable workflows start clean, so we need to checkout again - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml index ce3f5612db1..938b44de268 100644 --- a/.github/workflows/quality_check.yml +++ b/.github/workflows/quality_check.yml @@ -52,7 +52,7 @@ jobs: permissions: contents: read # checkout code only steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install poetry run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/quality_check_docs.yml b/.github/workflows/quality_check_docs.yml index e5b67347dbd..af2648a67f5 100644 --- a/.github/workflows/quality_check_docs.yml +++ b/.github/workflows/quality_check_docs.yml @@ -35,7 +35,7 @@ jobs: permissions: contents: read # checkout code only steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: diff --git a/.github/workflows/quality_code_cdk_constructor.yml b/.github/workflows/quality_code_cdk_constructor.yml index e33106542c1..c7d6b308fe8 100644 --- a/.github/workflows/quality_code_cdk_constructor.yml +++ b/.github/workflows/quality_code_cdk_constructor.yml @@ -42,7 +42,7 @@ jobs: run: working-directory: ./layer_v3/layer_constructors steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install poetry run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 6ca115c2460..038ac4c9ad7 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -27,4 +27,4 @@ jobs: permissions: contents: write # create release in draft mode steps: - - uses: release-drafter/release-drafter@693d20e7c1ce1a81d3a41962f85914253b518449 # v7.3.1 + - uses: release-drafter/release-drafter@ed4bc48ec97379be2258e7b7ac2624a3e26ab809 # v7.4.0 diff --git a/.github/workflows/release-v3.yml b/.github/workflows/release-v3.yml index 9eaf910682e..7bbeae80402 100644 --- a/.github/workflows/release-v3.yml +++ b/.github/workflows/release-v3.yml @@ -89,7 +89,7 @@ jobs: RELEASE_VERSION="${RELEASE_TAG_VERSION:1}" echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "$GITHUB_OUTPUT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -124,7 +124,7 @@ jobs: contents: read steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -165,7 +165,7 @@ jobs: attestation_hashes: ${{ steps.encoded_hash.outputs.attestation_hashes }} steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -234,7 +234,7 @@ jobs: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} steps: # NOTE: we need actions/checkout in order to use our local actions (e.g., ./.github/actions) - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -268,7 +268,7 @@ jobs: contents: write steps: # NOTE: we need actions/checkout to authenticate and configure git first - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -312,7 +312,7 @@ jobs: runs-on: ubuntu-latest steps: # NOTE: we need actions/checkout to authenticate and configure git first - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} @@ -368,7 +368,7 @@ jobs: env: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} - name: Restore sealed source code diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index dc5adefb695..01cd7048f22 100644 --- a/.github/workflows/reusable_deploy_v3_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v3_layer_stack.yml @@ -142,7 +142,7 @@ jobs: has_arm64_support: "true" steps: - name: checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} diff --git a/.github/workflows/reusable_deploy_v3_sar.yml b/.github/workflows/reusable_deploy_v3_sar.yml index 6420bc080ae..988acca3e7d 100644 --- a/.github/workflows/reusable_deploy_v3_sar.yml +++ b/.github/workflows/reusable_deploy_v3_sar.yml @@ -75,7 +75,7 @@ jobs: python-version: ["3.10","3.11","3.12","3.13","3.14"] steps: - name: checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ env.RELEASE_COMMIT }} diff --git a/.github/workflows/reusable_publish_changelog.yml b/.github/workflows/reusable_publish_changelog.yml index 2327e52fc5d..eb862970d4f 100644 --- a/.github/workflows/reusable_publish_changelog.yml +++ b/.github/workflows/reusable_publish_changelog.yml @@ -26,7 +26,7 @@ jobs: pull-requests: write # create PR steps: - name: Checkout repository # reusable workflows start clean, so we need to checkout again - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - name: "Generate latest changelog" diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 2ab38af74d0..474b0fb7e74 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -42,7 +42,7 @@ jobs: permissions: id-token: write # trade JWT token for AWS credentials in AWS Docs account steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 ref: ${{ inputs.git_ref }} diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 50047a884fe..6a2c4d4abec 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -52,7 +52,7 @@ jobs: if: ${{ github.actor != 'dependabot[bot]' && github.repository == 'aws-powertools/powertools-lambda-python' }} steps: - name: "Checkout" - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install poetry run: pipx install poetry - name: "Use Python" diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index eb3893183a0..766ac964c3d 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -30,7 +30,7 @@ jobs: contents: read # checkout code and subsequently GitHub action workflows steps: - name: Checkout code - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Ensure 3rd party workflows have SHA pinned uses: zgosalvez/github-actions-ensure-sha-pinned-actions@ca46236c6ce584ae24bc6283ba8dcf4b3ec8a066 # v5.0.4 with: From b58376cdc1e17fba2bb9787d560e36a9998ba903 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:19:46 +0100 Subject: [PATCH 12/76] chore(deps-dev): bump aws-cdk from 2.1127.0 to 2.1128.1 in the aws-cdk group (#8290) chore(deps-dev): bump aws-cdk in the aws-cdk group Bumps the aws-cdk group with 1 update: [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `aws-cdk` from 2.1127.0 to 2.1128.1 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1128.1/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1128.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ae5bec54f57..23e2c4a7e90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,13 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1127.0" + "aws-cdk": "^2.1128.1" } }, "node_modules/aws-cdk": { - "version": "2.1127.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1127.0.tgz", - "integrity": "sha512-/6pUD6+cp3ObwItYEHXF+O+cUCtsKmCoeerCXA/xAfELAAJbdlu36Zx+LJZGbF32aO4xdk3zlH3F7rY657js3g==", + "version": "2.1128.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1128.1.tgz", + "integrity": "sha512-y9OHn5/BOcIiq409vPvpypMIr7/8M1ScFe8IkFMSCN1/GI/5c73fQ4pfzNq+VDkj86T5zxs7BQ1qU2lQQytdXA==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 199876efbd7..1c550b6bddb 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1127.0" + "aws-cdk": "^2.1128.1" } } From ea8f79ec016a586c8e4bdf1320d015c2e58e63c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:28:36 +0100 Subject: [PATCH 13/76] chore(deps-dev): bump aws-cdk-lib from 2.259.0 to 2.260.0 (#8294) Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.259.0 to 2.260.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.259.0...v2.260.0) --- updated-dependencies: - dependency-name: aws-cdk-lib dependency-version: 2.260.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4c06fed7558..4c05289136d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -285,14 +285,14 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.259.0" +version = "2.260.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.259.0-py3-none-any.whl", hash = "sha256:4ea916f3673bd372d5e5a7bf84eb5bfb20c171b74a02c14ec8af2620441457a3"}, - {file = "aws_cdk_lib-2.259.0.tar.gz", hash = "sha256:5481f23b51dd771146c747d54e5d442f25a346a78c60077bd21b7d968af898e7"}, + {file = "aws_cdk_lib-2.260.0-py3-none-any.whl", hash = "sha256:41363a6fd72261ce64055b6c90538cf9b9ee2854faca7d2c56316656214f56ea"}, + {file = "aws_cdk_lib-2.260.0.tar.gz", hash = "sha256:94412d6539b543e898aa3a408a39c4d68be06c992938f8191d12f6ab44e546df"}, ] [package.dependencies] @@ -4837,9 +4837,10 @@ typing-extensions = ">=4.12.0" name = "ujson" version = "5.13.0" description = "Ultra fast JSON encoder and decoder for Python" -optional = false +optional = true python-versions = ">=3.10" groups = ["main"] +markers = "extra == \"datadog\"" files = [ {file = "ujson-5.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:770643b4752266c5a466149848b78c3874940926a4ecef304f518b2b6cdb432f"}, {file = "ujson-5.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8e8c1203cb1a27720debc334f840a9170da741503522f86999710cb4738fbe3"}, From 697c8d1740adf4fd59ea18c59b33e47972e40923 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:00:13 +0100 Subject: [PATCH 14/76] chore(ci): layer docs update (#8303) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> --- CHANGELOG.md | 36 ++- docs/includes/_layer_homepage_arm64.md | 290 ++++++++--------- docs/includes/_layer_homepage_x86.md | 300 +++++++++--------- examples/build_recipes/cdk/basic/app.py | 2 +- .../stacks/powertools_cdk_stack.py | 2 +- .../build_recipes/sam/multi-env/template.yaml | 2 +- .../sam/with-layers/template.yaml | 4 +- examples/homepage/install/arm64/amplify.txt | 4 +- examples/homepage/install/arm64/cdk_arm64.py | 2 +- .../homepage/install/arm64/pulumi_arm64.py | 2 +- examples/homepage/install/arm64/sam.yaml | 2 +- .../homepage/install/arm64/serverless.yml | 2 +- examples/homepage/install/arm64/terraform.tf | 2 +- examples/homepage/install/x86_64/amplify.txt | 4 +- examples/homepage/install/x86_64/cdk_x86.py | 2 +- .../homepage/install/x86_64/pulumi_x86.py | 2 +- examples/homepage/install/x86_64/sam.yaml | 2 +- .../homepage/install/x86_64/serverless.yml | 2 +- examples/homepage/install/x86_64/terraform.tf | 2 +- examples/logger/sam/template.yaml | 2 +- examples/metrics/sam/template.yaml | 2 +- examples/metrics_datadog/sam/template.yaml | 2 +- examples/tracer/sam/template.yaml | 2 +- 23 files changed, 353 insertions(+), 319 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2dc360bea2..8573c373338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,48 @@ # Unreleased + +## [v3.30.0] - 2026-06-24 +## Maintenance + +* version bump +* **deps-dev:** bump aws-cdk-lib from 2.259.0 to 2.260.0 ([#8294](https://github.com/aws-powertools/powertools-lambda-python/issues/8294)) + + ## [v3.29.0] - 2026-05-04 ## Bug Fixes * **event_handler:** prevent deadlock when async middleware raises before calling next() ([#8196](https://github.com/aws-powertools/powertools-lambda-python/issues/8196)) +* **event_handler:** fix ALB resolver returns when response body is None ([#8194](https://github.com/aws-powertools/powertools-lambda-python/issues/8194)) +* **idempotency:** resolve tech debt issues with falsy responses and Redis persistency ([#8176](https://github.com/aws-powertools/powertools-lambda-python/issues/8176)) +* **parser:** type hints should reflect primitive types support ([#8175](https://github.com/aws-powertools/powertools-lambda-python/issues/8175)) + +## Code Refactoring + +* **event_handler:** extract async logic to a separated file ([#8138](https://github.com/aws-powertools/powertools-lambda-python/issues/8138)) + +## Documentation + +* add lambda templates content ([#8159](https://github.com/aws-powertools/powertools-lambda-python/issues/8159)) + +## Features + +* add AsyncMiddlewareFrame support ([#8158](https://github.com/aws-powertools/powertools-lambda-python/issues/8158)) +* **event-handler:** add _registered_api_adapter_async() internal building block ([#8157](https://github.com/aws-powertools/powertools-lambda-python/issues/8157)) +* **event_handler:** adding resolve async public API ([#8171](https://github.com/aws-powertools/powertools-lambda-python/issues/8171)) +* **event_handler:** adding resolve async internal ([#8170](https://github.com/aws-powertools/powertools-lambda-python/issues/8170)) +* **openapi:** add compute_field support ([#8188](https://github.com/aws-powertools/powertools-lambda-python/issues/8188)) ## Maintenance * version bump +* update aws-encryption-sdk allowed versions ([#8191](https://github.com/aws-powertools/powertools-lambda-python/issues/8191)) +* **deps:** batch dependency updates ([#8184](https://github.com/aws-powertools/powertools-lambda-python/issues/8184)) +* **deps:** bump gitpython from 3.1.44 to 3.1.47 in /docs ([#8172](https://github.com/aws-powertools/powertools-lambda-python/issues/8172)) +* **deps:** batch update dependencies ([#8168](https://github.com/aws-powertools/powertools-lambda-python/issues/8168)) +* **deps:** update requests requirement from >=2.32.0 to >=2.33.1 in /examples/event_handler_graphql/src ([#8189](https://github.com/aws-powertools/powertools-lambda-python/issues/8189)) +* **deps-dev:** bump gitpython from 3.1.44 to 3.1.47 ([#8173](https://github.com/aws-powertools/powertools-lambda-python/issues/8173)) @@ -7666,7 +7699,8 @@ * Merge pull request [#5](https://github.com/aws-powertools/powertools-lambda-python/issues/5) from jfuss/feat/python38 -[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.29.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.30.0...HEAD +[v3.30.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.29.0...v3.30.0 [v3.29.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.28.0...v3.29.0 [v3.28.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.27.0...v3.28.0 [v3.27.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.26.0...v3.27.0 diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index e40a04078ec..a9aea03c29d 100644 --- a/docs/includes/_layer_homepage_arm64.md +++ b/docs/includes/_layer_homepage_arm64.md @@ -6,168 +6,168 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 907788332f7..811cd17eee4 100644 --- a/docs/includes/_layer_homepage_x86.md +++ b/docs/includes/_layer_homepage_x86.md @@ -5,173 +5,173 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:33**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | diff --git a/examples/build_recipes/cdk/basic/app.py b/examples/build_recipes/cdk/basic/app.py index 6268d8e49c0..121701664ce 100644 --- a/examples/build_recipes/cdk/basic/app.py +++ b/examples/build_recipes/cdk/basic/app.py @@ -24,7 +24,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34", ) # Lambda Function diff --git a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py index 3c7a480adbe..02624fd0138 100644 --- a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py +++ b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py @@ -47,7 +47,7 @@ def _create_powertools_layer(self) -> _lambda.ILayerVersion: return _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34", ) def _create_dynamodb_table(self) -> dynamodb.Table: diff --git a/examples/build_recipes/sam/multi-env/template.yaml b/examples/build_recipes/sam/multi-env/template.yaml index 8babe94f382..6276d0b740f 100644 --- a/examples/build_recipes/sam/multi-env/template.yaml +++ b/examples/build_recipes/sam/multi-env/template.yaml @@ -61,7 +61,7 @@ Resources: CodeUri: src/ Handler: app.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34 - !Ref DependenciesLayer Events: ApiEvent: diff --git a/examples/build_recipes/sam/with-layers/template.yaml b/examples/build_recipes/sam/with-layers/template.yaml index fc9803b5a8a..38a33639ad2 100644 --- a/examples/build_recipes/sam/with-layers/template.yaml +++ b/examples/build_recipes/sam/with-layers/template.yaml @@ -31,7 +31,7 @@ Resources: CodeUri: src/app/ Handler: app_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34 - !Ref DependenciesLayer Events: ApiEvent: @@ -50,7 +50,7 @@ Resources: CodeUri: src/worker/ Handler: worker_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34 - !Ref DependenciesLayer Events: SQSEvent: diff --git a/examples/homepage/install/arm64/amplify.txt b/examples/homepage/install/arm64/amplify.txt index 8aadd5ecbba..c15899b82ee 100644 --- a/examples/homepage/install/arm64/amplify.txt +++ b/examples/homepage/install/arm64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/arm64/cdk_arm64.py b/examples/homepage/install/arm64/cdk_arm64.py index 2b7d084a199..62626fe010c 100644 --- a/examples/homepage/install/arm64/cdk_arm64.py +++ b/examples/homepage/install/arm64/cdk_arm64.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/arm64/pulumi_arm64.py b/examples/homepage/install/arm64/pulumi_arm64.py index 1659d2362ad..a5fcc1c6159 100644 --- a/examples/homepage/install/arm64/pulumi_arm64.py +++ b/examples/homepage/install/arm64/pulumi_arm64.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/arm64/sam.yaml b/examples/homepage/install/arm64/sam.yaml index 8d77abd0e02..ad4527209a9 100644 --- a/examples/homepage/install/arm64/sam.yaml +++ b/examples/homepage/install/arm64/sam.yaml @@ -9,4 +9,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 diff --git a/examples/homepage/install/arm64/serverless.yml b/examples/homepage/install/arm64/serverless.yml index c3812016a42..0bf70b1edf3 100644 --- a/examples/homepage/install/arm64/serverless.yml +++ b/examples/homepage/install/arm64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 diff --git a/examples/homepage/install/arm64/terraform.tf b/examples/homepage/install/arm64/terraform.tf index dc46db6df87..3f09dd9c1c5 100644 --- a/examples/homepage/install/arm64/terraform.tf +++ b/examples/homepage/install/arm64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") diff --git a/examples/homepage/install/x86_64/amplify.txt b/examples/homepage/install/x86_64/amplify.txt index 9a1223e9280..e0a543f96f9 100644 --- a/examples/homepage/install/x86_64/amplify.txt +++ b/examples/homepage/install/x86_64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/x86_64/cdk_x86.py b/examples/homepage/install/x86_64/cdk_x86.py index 30d82a497dd..29e67578591 100644 --- a/examples/homepage/install/x86_64/cdk_x86.py +++ b/examples/homepage/install/x86_64/cdk_x86.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/x86_64/pulumi_x86.py b/examples/homepage/install/x86_64/pulumi_x86.py index 1130c67b644..3d3e4a6f650 100644 --- a/examples/homepage/install/x86_64/pulumi_x86.py +++ b/examples/homepage/install/x86_64/pulumi_x86.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml index d6beb66ea52..1a2dc187a10 100644 --- a/examples/homepage/install/x86_64/sam.yaml +++ b/examples/homepage/install/x86_64/sam.yaml @@ -8,4 +8,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml index 56deaf1b0fa..92ce1c2c434 100644 --- a/examples/homepage/install/x86_64/serverless.yml +++ b/examples/homepage/install/x86_64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf index 56e73fe45b6..27433e192a6 100644 --- a/examples/homepage/install/x86_64/terraform.tf +++ b/examples/homepage/install/x86_64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 092fb4166d3..87387aff1fe 100644 --- a/examples/logger/sam/template.yaml +++ b/examples/logger/sam/template.yaml @@ -14,7 +14,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index dc7d0258fee..21e08387e5d 100644 --- a/examples/metrics/sam/template.yaml +++ b/examples/metrics/sam/template.yaml @@ -16,7 +16,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 Resources: CaptureLambdaHandlerExample: diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml index d43669484f8..cf6ac73c17b 100644 --- a/examples/metrics_datadog/sam/template.yaml +++ b/examples/metrics_datadog/sam/template.yaml @@ -20,7 +20,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 # Find the latest Layer version in the Datadog official documentation # Datadog SDK diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml index 465ac3e2507..4140c75ece6 100644 --- a/examples/tracer/sam/template.yaml +++ b/examples/tracer/sam/template.yaml @@ -13,7 +13,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 Resources: CaptureLambdaHandlerExample: From 01e1e88443919cf1cad7388fb52c4ded671d9151 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:03:47 +0100 Subject: [PATCH 15/76] chore(ci): bump version to 3.30.0 (#8302) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Leandro Damascena --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index 242e0b4ae14..4f56571437c 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "3.29.0" +VERSION = "3.30.0" diff --git a/pyproject.toml b/pyproject.toml index ea2a9c38b61..c7360276ba9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "3.29.0" +version = "3.30.0" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From e7e67454788bb42441a80ab611c48c016c11082f Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 25 Jun 2026 16:53:17 +0100 Subject: [PATCH 16/76] feat: adding circuit breaker feature (#8266) * feat: adding circuit breaker feature * feat: adding circuit breaker feature * feat: adding circuit breaker feature * addressing bugs * addressing bugs * addressing bugs * addressing bugs --- aws_lambda_powertools/shared/constants.py | 3 + .../circuit_breaker_alpha/__init__.py | 35 + .../utilities/circuit_breaker_alpha/base.py | 248 +++++++ .../circuit_breaker_alpha/circuit_breaker.py | 119 ++++ .../utilities/circuit_breaker_alpha/config.py | 128 ++++ .../circuit_breaker_alpha/exceptions.py | 77 +++ .../persistence/__init__.py | 15 + .../circuit_breaker_alpha/persistence/base.py | 291 +++++++++ .../persistence/dynamodb.py | 252 ++++++++ .../persistence/record.py | 63 ++ .../utilities/circuit_breaker_alpha/states.py | 126 ++++ .../circuit_breaker_alpha/circuit_breaker.md | 2 + docs/api_doc/circuit_breaker_alpha/config.md | 2 + .../circuit_breaker_alpha/exceptions.md | 2 + .../circuit_breaker_alpha/persistence.md | 2 + docs/api_doc/circuit_breaker_alpha/states.md | 2 + docs/utilities/circuit_breaker.md | 227 +++++++ .../getting_started_with_circuit_breaker.py | 29 + .../src/working_with_callback.py | 44 ++ .../src/working_with_metrics.py | 45 ++ .../src/working_without_callback.py | 44 ++ .../circuit_breaker_alpha/templates/sam.yaml | 33 + mkdocs.yml | 8 + .../circuit_breaker_alpha/__init__.py | 0 .../circuit_breaker_alpha/conftest.py | 103 +++ .../test_circuit_breaker.py | 604 ++++++++++++++++++ .../test_dynamodb_persistence.py | 270 ++++++++ tests/unit/circuit_breaker_alpha/__init__.py | 0 .../test_config_and_states.py | 93 +++ 29 files changed, 2867 insertions(+) create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/circuit_breaker.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/exceptions.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py create mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/states.py create mode 100644 docs/api_doc/circuit_breaker_alpha/circuit_breaker.md create mode 100644 docs/api_doc/circuit_breaker_alpha/config.md create mode 100644 docs/api_doc/circuit_breaker_alpha/exceptions.md create mode 100644 docs/api_doc/circuit_breaker_alpha/persistence.md create mode 100644 docs/api_doc/circuit_breaker_alpha/states.md create mode 100644 docs/utilities/circuit_breaker.md create mode 100644 examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py create mode 100644 examples/circuit_breaker_alpha/src/working_with_callback.py create mode 100644 examples/circuit_breaker_alpha/src/working_with_metrics.py create mode 100644 examples/circuit_breaker_alpha/src/working_without_callback.py create mode 100644 examples/circuit_breaker_alpha/templates/sam.yaml create mode 100644 tests/functional/circuit_breaker_alpha/__init__.py create mode 100644 tests/functional/circuit_breaker_alpha/conftest.py create mode 100644 tests/functional/circuit_breaker_alpha/test_circuit_breaker.py create mode 100644 tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py create mode 100644 tests/unit/circuit_breaker_alpha/__init__.py create mode 100644 tests/unit/circuit_breaker_alpha/test_config_and_states.py diff --git a/aws_lambda_powertools/shared/constants.py b/aws_lambda_powertools/shared/constants.py index bc19ff13b30..6c808d38758 100644 --- a/aws_lambda_powertools/shared/constants.py +++ b/aws_lambda_powertools/shared/constants.py @@ -76,3 +76,6 @@ # Idempotency constants IDEMPOTENCY_DISABLED_ENV: str = "POWERTOOLS_IDEMPOTENCY_DISABLED" + +# Circuit breaker constants +CIRCUIT_BREAKER_DISABLED_ENV: str = "POWERTOOLS_CIRCUIT_BREAKER_DISABLED" diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py new file mode 100644 index 00000000000..e931245f9d0 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py @@ -0,0 +1,35 @@ +""" +Circuit Breaker utility for protecting unhealthy downstream dependencies. + +!!! warning "Alpha / experimental" + This utility is published under the `_alpha` namespace while we collect + feedback. The public API may change in a backwards-incompatible way before it + is promoted to GA. Pin your version and follow the tracking discussion before + relying on it in production. +""" + +from aws_lambda_powertools.utilities.circuit_breaker_alpha.circuit_breaker import circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import ( + CircuitBreakerConfigError, + CircuitBreakerError, + CircuitBreakerOpenError, + CircuitBreakerPersistenceError, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import ( + CircuitInfo, + CircuitState, + CircuitTransition, +) + +__all__ = ( + "circuit_breaker", + "CircuitBreakerConfig", + "CircuitInfo", + "CircuitState", + "CircuitTransition", + "CircuitBreakerError", + "CircuitBreakerOpenError", + "CircuitBreakerConfigError", + "CircuitBreakerPersistenceError", +) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py new file mode 100644 index 00000000000..b4f66b98dc8 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py @@ -0,0 +1,248 @@ +""" +Orchestrator for the Circuit Breaker utility. + +:class:`CircuitBreakerHandler` owns the state machine and the per-environment failure +counter; the persistence layer owns the shared truth. This split keeps the healthy +path write-free: failures are counted locally and only persisted on a state transition. +""" + +from __future__ import annotations + +import datetime +import logging +import uuid +from typing import TYPE_CHECKING, Any + +from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerOpenError +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState, CircuitTransition + +if TYPE_CHECKING: + from collections.abc import Callable + + from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig + from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( + CircuitBreakerPersistenceLayer, + ) + from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo + +logger = logging.getLogger(__name__) + +# Per-environment, per-circuit consecutive counters. Module-level so they survive across +# invocations within the same execution environment, the same way idempotency caches do. +_LOCAL_FAILURES: dict[str, int] = {} +_LOCAL_SUCCESSES: dict[str, int] = {} + +# Tracks the last state this environment observed from the store, per circuit. Used to +# detect transitions back to CLOSED that happened externally (another env tripped and +# recovered), so stale local failure streaks can be invalidated. +_LAST_OBSERVED_STATE: dict[str, CircuitState] = {} + +# Stable per-environment identifier used to claim the half-open probe lock. +_ENVIRONMENT_ID = uuid.uuid4().hex + + +class CircuitBreakerHandler: + """ + Drive a single protected call through the circuit breaker state machine. + + A new handler is created per invocation by the decorator. It reads the shared state, + routes the call (run, short-circuit, or probe), and records the outcome. + + Parameters + ---------- + function : Callable + The protected function. + name : str + Circuit name. + config : CircuitBreakerConfig + Circuit configuration. + persistence_store : CircuitBreakerPersistenceLayer + Shared state store. + on_circuit_open : Callable | None + Callback invoked with the protected call's own ``*args``/``**kwargs`` plus a + trailing ``circuit`` keyword argument when the circuit is open. If ``None``, an + open circuit raises :class:`CircuitBreakerOpenError`. + function_args : tuple + Positional arguments the protected function was called with. + function_kwargs : dict + Keyword arguments the protected function was called with. + """ + + def __init__( + self, + function: Callable, + name: str, + config: CircuitBreakerConfig, + persistence_store: CircuitBreakerPersistenceLayer, + on_circuit_open: Callable | None = None, + on_transition: Callable | None = None, + function_args: tuple | None = None, + function_kwargs: dict | None = None, + ): + self.function = function + self.name = name + self.config = config + self.on_circuit_open = on_circuit_open + self.on_transition = on_transition + self.fn_args = function_args or () + self.fn_kwargs = function_kwargs or {} + + persistence_store.configure(config=config, circuit_name=name) + self.persistence_store = persistence_store + + def handle(self) -> Any: + """ + Evaluate the circuit and route the call. + + Returns + ------- + Any + The protected function's result when the call runs, or the + ``on_circuit_open`` callback's return value when the circuit is open. + + Raises + ------ + CircuitBreakerOpenError + If the circuit is open and no callback is registered. + """ + record = self.persistence_store.get_state(self.name) + + if record.state == CircuitState.CLOSED: + # If we previously observed a non-CLOSED state and the circuit is now back to + # CLOSED, another environment completed the recovery cycle. Reset local counters + # so a stale partial failure streak doesn't immediately re-trip the circuit. + prev = _LAST_OBSERVED_STATE.get(self.name) + if prev is not None and prev != CircuitState.CLOSED: + _LOCAL_FAILURES[self.name] = 0 + _LAST_OBSERVED_STATE[self.name] = CircuitState.CLOSED + return self._call_closed() + + if record.state == CircuitState.OPEN: + _LAST_OBSERVED_STATE[self.name] = CircuitState.OPEN + # ``opened_at`` may legitimately be 0 (epoch); treat only None as missing. + opened_at = record.opened_at if record.opened_at is not None else self._now() + if self._now() >= opened_at + self.config.recovery_timeout: + # Recovery window elapsed: try to become the single prober. + if self.persistence_store.try_acquire_half_open(self.name, _ENVIRONMENT_ID, opened_at): + self._notify(CircuitState.OPEN, CircuitState.HALF_OPEN, opened_at=opened_at) + return self._call_probe() + return self._open_response(record.to_circuit_info()) + + # HALF_OPEN: only the environment that owns the probe lock runs. + _LAST_OBSERVED_STATE[self.name] = CircuitState.HALF_OPEN + if record.half_open_owner == _ENVIRONMENT_ID: + return self._call_probe() + + # If the probe lease has expired (owner recycled mid-probe), take over. + if record.probe_lease_expiry is not None and self._now() >= record.probe_lease_expiry: + logger.debug("Circuit '%s' probe lease expired; attempting takeover.", self.name) + if self.persistence_store.try_acquire_half_open(self.name, _ENVIRONMENT_ID, record.opened_at or 0): + return self._call_probe() + + return self._open_response(record.to_circuit_info()) + + def _call_closed(self) -> Any: + """Run the protected call while the circuit is closed, tracking failures.""" + try: + result = self.function(*self.fn_args, **self.fn_kwargs) + except Exception as exc: + if not self.config.counts_as_failure(exc): + raise + failures = _LOCAL_FAILURES.get(self.name, 0) + 1 + _LOCAL_FAILURES[self.name] = failures + if failures >= self.config.failure_threshold: + logger.debug("Circuit '%s' tripping CLOSED to OPEN after %d failures.", self.name, failures) + opened_at = self._now() + self._safe_persist( + self.persistence_store.save_open, + self.name, + failure_count=failures, + opened_at=opened_at, + ) + _LOCAL_FAILURES[self.name] = 0 + self._notify(CircuitState.CLOSED, CircuitState.OPEN, opened_at=opened_at) + raise + else: + _LOCAL_FAILURES[self.name] = 0 + return result + + def _call_probe(self) -> Any: + """Run a probe during half-open, closing or reopening based on the outcome.""" + try: + result = self.function(*self.fn_args, **self.fn_kwargs) + except Exception as exc: + if not self.config.counts_as_failure(exc): + raise + logger.debug("Circuit '%s' probe failed; reopening.", self.name) + opened_at = self._now() + self._safe_persist(self.persistence_store.save_reopen, self.name, opened_at=opened_at) + _LOCAL_SUCCESSES[self.name] = 0 + self._notify(CircuitState.HALF_OPEN, CircuitState.OPEN, opened_at=opened_at) + raise + else: + successes = _LOCAL_SUCCESSES.get(self.name, 0) + 1 + _LOCAL_SUCCESSES[self.name] = successes + if successes >= self.config.success_threshold: + logger.debug("Circuit '%s' closing after %d probe successes.", self.name, successes) + self._safe_persist(self.persistence_store.save_closed, self.name) + _LOCAL_SUCCESSES[self.name] = 0 + _LOCAL_FAILURES[self.name] = 0 + self._notify(CircuitState.HALF_OPEN, CircuitState.CLOSED) + return result + + def _safe_persist(self, fn: Callable, *args: Any, **kwargs: Any) -> None: + """ + Call a persistence write, swallowing and logging failures. + + State-transition writes must never mask the downstream's real result or replace + the downstream's real exception. This mirrors the fail-open read policy in the + persistence layer. + """ + try: + fn(*args, **kwargs) + except Exception: + logger.warning( + "Circuit '%s': persistence write (%s) failed; the transition may be delayed but the " + "downstream result is preserved.", + self.name, + getattr(fn, "__name__", repr(fn)), + exc_info=True, + ) + + def _open_response(self, circuit: CircuitInfo) -> Any: + """Produce the response for an open circuit: callback result or raise.""" + if self.on_circuit_open is not None: + # Forward the protected call's arguments unchanged: positional stay positional, + # keyword stay keyword. The circuit snapshot is passed as a keyword argument so + # it never collides with positionalized kwargs nor depends on dict ordering. + return self.on_circuit_open(*self.fn_args, **self.fn_kwargs, circuit=circuit) + raise CircuitBreakerOpenError( + f"Circuit '{self.name}' is open.", + circuit=circuit, + ) + + def _notify(self, from_state: CircuitState, to_state: CircuitState, opened_at: int | None = None) -> None: + """ + Fire the ``on_transition`` hook for a state change. + + Called only on real transitions, never on the hot path. Any exception the hook + raises is swallowed and logged: observability must never break the protected call. + """ + if self.on_transition is None: + return + try: + self.on_transition( + CircuitTransition( + circuit_name=self.name, + from_state=from_state, + to_state=to_state, + opened_at=opened_at, + ), + ) + except Exception: + logger.warning("on_transition hook for circuit '%s' raised; ignoring.", self.name, exc_info=True) + + @staticmethod + def _now() -> int: + """Current unix timestamp in seconds.""" + return int(datetime.datetime.now().timestamp()) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/circuit_breaker.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/circuit_breaker.py new file mode 100644 index 00000000000..de4e66b0680 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/circuit_breaker.py @@ -0,0 +1,119 @@ +""" +Primary interface for the Circuit Breaker utility. +""" + +from __future__ import annotations + +import functools +import logging +import os +import warnings +from typing import TYPE_CHECKING, Any + +from aws_lambda_powertools.shared import constants +from aws_lambda_powertools.shared.functions import strtobool +from aws_lambda_powertools.utilities.circuit_breaker_alpha.base import CircuitBreakerHandler +from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig +from aws_lambda_powertools.warnings import PowertoolsUserWarning + +if TYPE_CHECKING: + from collections.abc import Callable + + from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( + CircuitBreakerPersistenceLayer, + ) + +logger = logging.getLogger(__name__) + + +def circuit_breaker( + name: str, + persistence_store: CircuitBreakerPersistenceLayer, + on_circuit_open: Callable | None = None, + on_transition: Callable | None = None, + config: CircuitBreakerConfig | None = None, +) -> Callable: + """ + Protect a function that calls an unhealthy-prone downstream with a circuit breaker. + + Wrap the function that makes the downstream call, not the whole Lambda handler, so a + tripped circuit reflects one dependency rather than unrelated handler logic. + + When the circuit is open the protected function is not called. Instead, if an + ``on_circuit_open`` callback is registered it runs and its return value becomes the + call's result; otherwise :class:`CircuitBreakerOpenError` is raised. + + Parameters + ---------- + name : str + Unique circuit name. Each name is an independent circuit; a function calling + several backends should use one circuit per backend. + persistence_store : CircuitBreakerPersistenceLayer + Shared state store (for example ``CircuitBreakerDynamoDBPersistence``). + on_circuit_open : Callable | None + Called when the circuit is open, with the protected function's own arguments + (positional stay positional, keyword stay keyword) plus a trailing ``circuit`` + keyword argument carrying a ``CircuitInfo``. Its return value becomes the call's + result. If ``None``, an open circuit raises ``CircuitBreakerOpenError``. + on_transition : Callable | None + Called with a single ``CircuitTransition`` argument whenever the circuit changes + state (open, probe, close, reopen). Fires only on transitions, never on the + per-invocation hot path, so it is a safe place to emit a CloudWatch metric. Any + exception it raises is swallowed and logged so observability never breaks the + protected call. + config : CircuitBreakerConfig | None + Tunables. Defaults to ``CircuitBreakerConfig()`` when omitted. + + Returns + ------- + Callable + The decorated function. + + Example + ------- + **Protect a payment backend, buffering rejected requests** + + from aws_lambda_powertools.utilities.circuit_breaker_alpha import circuit_breaker, CircuitInfo + from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, + ) + + persistence = CircuitBreakerDynamoDBPersistence(table_name="CircuitBreakerState") + + def buffer(order: dict, circuit: CircuitInfo): + sqs.send_message(QueueUrl=url, MessageBody=json.dumps(order)) + + @circuit_breaker(name="payment-backend", persistence_store=persistence, on_circuit_open=buffer) + def charge(order: dict) -> dict: + return payment_api.charge(order) + """ + config = config or CircuitBreakerConfig() + + def decorator(function: Callable) -> Callable: + @functools.wraps(function) + def wrapper(*args, **kwargs) -> Any: + # Skip the circuit entirely when disabled (development only). + if strtobool(os.getenv(constants.CIRCUIT_BREAKER_DISABLED_ENV, "false")): + warnings.warn( + message="Disabling the circuit breaker is intended for development environments only " + "and should not be used in production.", + category=PowertoolsUserWarning, + stacklevel=2, + ) + return function(*args, **kwargs) + + handler = CircuitBreakerHandler( + function=function, + name=name, + config=config, + persistence_store=persistence_store, + on_circuit_open=on_circuit_open, + on_transition=on_transition, + function_args=args, + function_kwargs=kwargs, + ) + return handler.handle() + + return wrapper + + return decorator diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py new file mode 100644 index 00000000000..9425e90ab38 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py @@ -0,0 +1,128 @@ +""" +Configuration for the Circuit Breaker utility. +""" + +from __future__ import annotations + +from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerConfigError + + +class CircuitBreakerConfig: + """ + Tunables for a circuit breaker. + + All values have sensible defaults, so ``CircuitBreakerConfig()`` is a valid + production configuration. Pass an instance to ``@circuit_breaker(config=...)`` to + override them. + + Parameters + ---------- + failure_threshold : int + Number of *consecutive* failures that trips a closed circuit to open. Defaults to 5. + recovery_timeout : int + Seconds the circuit stays open before allowing a half-open probe. Defaults to 30. + success_threshold : int + Number of *consecutive* probe successes required to close a half-open circuit. + Defaults to 3. + handled_exceptions : tuple[type[Exception], ...] | None + Allowlist: only these exception types count as failures; anything else + propagates without affecting the circuit. Mutually exclusive with + ``ignored_exceptions``. Defaults to ``None`` (treated as ``(Exception,)``). + ignored_exceptions : tuple[type[Exception], ...] | None + Denylist: every exception counts as a failure *except* these. Mutually + exclusive with ``handled_exceptions``. Defaults to ``None``. + local_cache_max_age : int + Seconds a circuit's state is cached in the execution environment before a + read-through to the store. Matches the Parameters utility default. Defaults to 5. + + Raises + ------ + CircuitBreakerConfigError + If both ``handled_exceptions`` and ``ignored_exceptions`` are provided, or a + numeric tunable is not a positive integer. + + Example + ------- + **Only count timeouts and connection errors as failures** + + config = CircuitBreakerConfig( + failure_threshold=5, + recovery_timeout=30, + handled_exceptions=(TimeoutError, ConnectionError), + ) + """ + + def __init__( + self, + failure_threshold: int = 5, + recovery_timeout: int = 30, + success_threshold: int = 3, + handled_exceptions: tuple[type[Exception], ...] | None = None, + ignored_exceptions: tuple[type[Exception], ...] | None = None, + local_cache_max_age: int = 5, + ): + self._validate( + failure_threshold=failure_threshold, + recovery_timeout=recovery_timeout, + success_threshold=success_threshold, + handled_exceptions=handled_exceptions, + ignored_exceptions=ignored_exceptions, + local_cache_max_age=local_cache_max_age, + ) + + self.failure_threshold = failure_threshold + self.recovery_timeout = recovery_timeout + self.success_threshold = success_threshold + self.handled_exceptions = handled_exceptions + self.ignored_exceptions = ignored_exceptions + self.local_cache_max_age = local_cache_max_age + + @staticmethod + def _validate( + failure_threshold: int, + recovery_timeout: int, + success_threshold: int, + handled_exceptions: tuple[type[Exception], ...] | None, + ignored_exceptions: tuple[type[Exception], ...] | None, + local_cache_max_age: int, + ) -> None: + if handled_exceptions and ignored_exceptions: + raise CircuitBreakerConfigError( + "handled_exceptions and ignored_exceptions are mutually exclusive; pass only one.", + ) + + # Thresholds and timeouts must be strictly positive; cache age may be 0 (always read through). + for field, value in ( + ("failure_threshold", failure_threshold), + ("recovery_timeout", recovery_timeout), + ("success_threshold", success_threshold), + ): + if not isinstance(value, int) or value <= 0: + raise CircuitBreakerConfigError(f"{field} must be a positive integer, got {value!r}.") + + if not isinstance(local_cache_max_age, int) or local_cache_max_age < 0: + raise CircuitBreakerConfigError( + f"local_cache_max_age must be a non-negative integer, got {local_cache_max_age!r}.", + ) + + def counts_as_failure(self, exception: Exception) -> bool: + """ + Decide whether an exception raised by the protected call counts as a circuit failure. + + Parameters + ---------- + exception : Exception + The exception raised by the protected function. + + Returns + ------- + bool + ``True`` if the exception should increment the failure counter, ``False`` if + it should propagate without affecting the circuit. + """ + if self.handled_exceptions is not None: + return isinstance(exception, self.handled_exceptions) + if self.ignored_exceptions is not None: + return not isinstance(exception, self.ignored_exceptions) + # Default: any exception counts as a failure. + return True diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/exceptions.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/exceptions.py new file mode 100644 index 00000000000..cf3c350fc83 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/exceptions.py @@ -0,0 +1,77 @@ +""" +Circuit Breaker exceptions. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo + + +class CircuitBreakerError(Exception): + """ + Base error class. + + Overrides message/details formatting so the printed exception stays readable. + See https://github.com/aws-powertools/powertools-lambda-python/issues/1772 + """ + + def __init__(self, *args: str | Exception | None): + self.message = str(args[0]) if args else "" + self.details = "".join(str(arg) for arg in args[1:]) if args[1:] else None + + def __str__(self): + """Return all arguments formatted, or the original message.""" + if self.message and self.details: + return f"{self.message} - ({self.details})" + return self.message + + +class CircuitBreakerOpenError(CircuitBreakerError): + """ + Raised when the circuit is open and no ``on_circuit_open`` callback is registered. + + The rejected request never reached the downstream. The circuit snapshot is attached + so the caller can decide how to respond. + + Parameters + ---------- + *args : str | Exception | None + Standard error message/details. + circuit : CircuitInfo | None + Snapshot of the circuit at rejection time. + + Example + ------- + **Handling an open circuit when no callback is registered** + + try: + charge(order) + except CircuitBreakerOpenError as exc: + logger.warning("rejected by circuit %s", exc.circuit.name) + return {"statusCode": 202} + """ + + def __init__(self, *args: str | Exception | None, circuit: CircuitInfo | None = None): + self.circuit = circuit + super().__init__(*args) + + +class CircuitBreakerConfigError(CircuitBreakerError): + """ + Raised when ``CircuitBreakerConfig`` is built with an unsupported combination of + options (for example, both ``handled_exceptions`` and ``ignored_exceptions``). + """ + + +class CircuitBreakerPersistenceError(CircuitBreakerError): + """ + Raised by a persistence backend for an unrecoverable store error on a *write* path + (persisting a state transition), where there is no safe local fallback. + + Reads never raise this: ``get_state`` fails open (treats the circuit as closed) and + only logs, so a degraded store can never become the outage the breaker is meant to + prevent. Custom backends may raise this from their write primitives. + """ diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py new file mode 100644 index 00000000000..18704bff793 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py @@ -0,0 +1,15 @@ +""" +Persistence layers for the Circuit Breaker utility. +""" + +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import CircuitBreakerPersistenceLayer +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.dynamodb import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord + +__all__ = ( + "CircuitBreakerPersistenceLayer", + "CircuitBreakerDynamoDBPersistence", + "CircuitStateRecord", +) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py new file mode 100644 index 00000000000..f1dee4c745f --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py @@ -0,0 +1,291 @@ +""" +Abstract persistence layer for the Circuit Breaker utility. + +Concrete backends (DynamoDB, cache) subclass :class:`CircuitBreakerPersistenceLayer` +and implement the small set of store primitives. The base class owns the local +read-through cache and the fail-open policy so every backend behaves identically. +""" + +from __future__ import annotations + +import datetime +import logging +from abc import ABC, abstractmethod +from typing import TYPE_CHECKING + +from aws_lambda_powertools.shared.cache_dict import LRUDict +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState + +if TYPE_CHECKING: + from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig + +logger = logging.getLogger(__name__) + +# Circuit names are static in user code, so a handful of circuits per environment is the +# norm. This cap only guards the pathological case of dynamically generated names. +LOCAL_CACHE_MAX_ITEMS = 1024 + +# Slack added on top of a recovery cycle when computing the durable store TTL. The item +# must outlive any in-flight recovery window so a live circuit is never reaped mid-cycle, +# while an abandoned circuit (no traffic, no further writes) still self-cleans soon after. +PERSISTED_STATE_TTL_BUFFER = 3600 + + +class CircuitBreakerExistingLockError(Exception): + """Internal signal that a conditional half-open probe write lost the race.""" + + +class CircuitBreakerPersistenceLayer(ABC): + """ + Abstract base class for circuit breaker persistence layers. + + Owns the per-environment read cache and the fail-open behavior. Subclasses + implement :meth:`_get_record`, :meth:`_put_record`, and :meth:`_update_record` + for a specific store. + + A persistence layer is keyed by **circuit name**, not by a payload hash, which is + the main reason it does not reuse the Idempotency persistence layer. + """ + + def __init__(self) -> None: + """Initialize defaults; real configuration happens in :meth:`configure`.""" + self.circuit_name: str = "" + self.local_cache_max_age: int = 5 + self.recovery_timeout: int = 30 + # Maps circuit name -> the unix timestamp the locally cached record goes stale. + # Kept separate from the record's durable ``expiry_timestamp`` (the store TTL) so + # the short in-memory freshness window is never mistaken for the long store TTL. + self._cache: LRUDict = LRUDict(max_items=LOCAL_CACHE_MAX_ITEMS) + + def configure(self, config: CircuitBreakerConfig, circuit_name: str) -> None: + """ + Bind the layer to a circuit and its configuration. + + Called once per invocation by the handler; the assignments are cheap and the + same persistence instance is reused across invocations within an environment. + + Parameters + ---------- + config : CircuitBreakerConfig + Configuration providing the local cache TTL and recovery timeout. + circuit_name : str + The circuit this layer instance serves. + """ + self.circuit_name = circuit_name + self.local_cache_max_age = config.local_cache_max_age + self.recovery_timeout = config.recovery_timeout + + # ------------------------------------------------------------------ cache + + def _cache_key(self, name: str) -> str: + return name + + def _durable_ttl(self) -> int: + """ + Compute the store TTL stamped on a persisted record. + + Sized to outlive a full recovery window so a live circuit is never reaped + mid-cycle, while an abandoned circuit (no further writes) self-cleans soon after. + """ + return int(datetime.datetime.now().timestamp()) + self.recovery_timeout + PERSISTED_STATE_TTL_BUFFER + + def _save_to_cache(self, record: CircuitStateRecord) -> None: + """Cache a record locally with a short in-memory freshness window.""" + local_expiry = int(datetime.datetime.now().timestamp()) + self.local_cache_max_age + self._cache[self._cache_key(record.name)] = (local_expiry, record) + + def _retrieve_from_cache(self, name: str) -> CircuitStateRecord | None: + """Return a cached record if present and still within its local freshness window.""" + cached = self._cache.get(self._cache_key(name)) + if cached is None: + return None + + local_expiry, record = cached + if int(datetime.datetime.now().timestamp()) >= local_expiry: + del self._cache[self._cache_key(name)] + return None + + return record + + # ------------------------------------------------------------- public API + + def get_state(self, name: str) -> CircuitStateRecord: + """ + Return the current circuit state, reading the store only on a cache miss. + + A cache miss (cold start or expired local entry) forces a read-through before + the caller routes the request, so a freshly started environment never assumes a + circuit is closed without checking. + + Fail-open: if the store read itself raises, the circuit is treated as + ``CLOSED``. A circuit breaker must never become the outage it is meant to + prevent. + + Parameters + ---------- + name : str + Circuit name. + + Returns + ------- + CircuitStateRecord + The current record, a synthesized closed record if none exists yet, or a + synthesized closed record if the store could not be reached. + """ + cached = self._retrieve_from_cache(name) + if cached is not None: + return cached + + try: + record = self._get_record(name) + except Exception: + # Fail open without caching, so the next invocation retries the store rather + # than serving a synthesized CLOSED for the whole local cache window. + logger.warning( + "Failed to read circuit state for '%s'; failing open (treating as CLOSED).", + name, + exc_info=True, + ) + return CircuitStateRecord(name=name, state=CircuitState.CLOSED) + + # A missing record is the expected cold-start case, not a failure: treat it as a + # closed circuit and cache it like any other read. + if record is None: + record = CircuitStateRecord(name=name, state=CircuitState.CLOSED) + + self._save_to_cache(record) + return record + + def save_open(self, name: str, failure_count: int, opened_at: int) -> None: + """ + Persist a CLOSED to OPEN transition. + + Parameters + ---------- + name : str + Circuit name. + failure_count : int + Consecutive failures that tripped the circuit. + opened_at : int + Unix timestamp the circuit opened; anchors the recovery timeout. + """ + record = CircuitStateRecord( + name=name, + state=CircuitState.OPEN, + failure_count=failure_count, + opened_at=opened_at, + expiry_timestamp=self._durable_ttl(), + ) + self._put_record(record) + self._save_to_cache(record) + + def try_acquire_half_open(self, name: str, owner: str, opened_at: int) -> bool: + """ + Atomically elect a single environment to run the half-open probe. + + The conditional write succeeds only when the circuit is OPEN with no existing + lock owner AND the ``opened_at`` matches what the caller observed (guards against + stale eventually-consistent reads). A lease expiry is stamped so that if the + winning environment is recycled before completing the probe, others can take over + once the lease lapses. + + Parameters + ---------- + name : str + Circuit name. + owner : str + Identifier of the environment attempting the probe. + opened_at : int + The ``opened_at`` the caller observed, kept stable across the transition. + + Returns + ------- + bool + ``True`` if this environment won the probe lock, ``False`` if another + environment already holds it. + """ + # Lease = recovery_timeout gives the probe a full cycle to complete. + probe_lease_expiry = int(datetime.datetime.now().timestamp()) + self.recovery_timeout + record = CircuitStateRecord( + name=name, + state=CircuitState.HALF_OPEN, + opened_at=opened_at, + half_open_owner=owner, + probe_lease_expiry=probe_lease_expiry, + expiry_timestamp=self._durable_ttl(), + ) + try: + self._put_record(record, condition="half_open", expected_opened_at=opened_at) + except CircuitBreakerExistingLockError: + return False + self._save_to_cache(record) + return True + + def save_closed(self, name: str) -> None: + """Persist a transition back to CLOSED and reset counters.""" + record = CircuitStateRecord( + name=name, + state=CircuitState.CLOSED, + failure_count=0, + expiry_timestamp=self._durable_ttl(), + ) + self._update_record(record) + self._save_to_cache(record) + + def save_reopen(self, name: str, opened_at: int) -> None: + """ + Persist a HALF_OPEN to OPEN transition after a failed probe. + + If this write fails the stored row stays in HALF_OPEN, but it does not strand the + circuit: the probe lease expiry still applies, so once it lapses another + environment wins the next election and drives the transition. + """ + record = CircuitStateRecord( + name=name, + state=CircuitState.OPEN, + opened_at=opened_at, + expiry_timestamp=self._durable_ttl(), + ) + self._update_record(record) + self._save_to_cache(record) + + # --------------------------------------------------------- backend hooks + + @abstractmethod + def _get_record(self, name: str) -> CircuitStateRecord | None: + """ + Fetch a circuit record from the store, or ``None`` if no record exists for ``name``. + """ + raise NotImplementedError + + @abstractmethod + def _put_record( + self, + record: CircuitStateRecord, + condition: str | None = None, + expected_opened_at: int | None = None, + ) -> None: + """ + Write a circuit record. + + Parameters + ---------- + record : CircuitStateRecord + Record to write. + condition : str | None + When ``"half_open"``, the write must be conditional so only one + environment wins the probe lock; on a lost race the backend raises + :class:`CircuitBreakerExistingLockError`. + expected_opened_at : int | None + When set alongside ``condition="half_open"``, the write additionally + requires that the stored ``opened_at`` matches this value. This closes + a race where an eventually-consistent read could let a stale environment + win an election immediately after a failed probe reopened the circuit. + """ + raise NotImplementedError + + @abstractmethod + def _update_record(self, record: CircuitStateRecord) -> None: + """Update an existing circuit record (unconditional state change).""" + raise NotImplementedError diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py new file mode 100644 index 00000000000..386de753839 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py @@ -0,0 +1,252 @@ +""" +DynamoDB persistence backend for the Circuit Breaker utility. +""" + +from __future__ import annotations + +import datetime +import logging +from typing import TYPE_CHECKING + +import boto3 +from boto3.dynamodb.types import TypeDeserializer +from botocore.exceptions import ClientError + +from aws_lambda_powertools.shared import user_agent +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( + CircuitBreakerExistingLockError, + CircuitBreakerPersistenceLayer, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState + +if TYPE_CHECKING: + from botocore.config import Config + from mypy_boto3_dynamodb.client import DynamoDBClient + +logger = logging.getLogger(__name__) + + +class CircuitBreakerDynamoDBPersistence(CircuitBreakerPersistenceLayer): + """ + Store circuit state in an Amazon DynamoDB table, one item per circuit. + + The class name is prefixed with ``CircuitBreaker`` so a function using both the + Idempotency and Circuit Breaker utilities can import both persistence layers + without an alias. + + Parameters + ---------- + table_name : str + Name of the DynamoDB table that stores circuit state. + key_attr : str + Partition key attribute holding the circuit name. Defaults to ``"id"``. + state_attr : str + Attribute holding the circuit state. Defaults to ``"state"``. + failure_count_attr : str + Attribute holding the consecutive failure count. Defaults to ``"failure_count"``. + opened_at_attr : str + Attribute holding the open timestamp. Defaults to ``"opened_at"``. + half_open_owner_attr : str + Attribute holding the half-open probe lock owner. Defaults to ``"half_open_owner"``. + probe_lease_expiry_attr : str + Attribute holding the probe lease expiry timestamp. Defaults to ``"probe_lease_expiry"``. + expiry_attr : str + TTL attribute. Defaults to ``"expiration"``. + boto_config : botocore.config.Config, optional + Botocore configuration used when creating the client. + boto3_session : boto3.session.Session, optional + Session used to create the client. + boto3_client : DynamoDBClient, optional + Pre-built client; ``boto3_session`` and ``boto_config`` are ignored if given. + + Example + ------- + **Create a DynamoDB-backed circuit breaker store** + + from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, + ) + + persistence = CircuitBreakerDynamoDBPersistence(table_name="CircuitBreakerState") + """ + + def __init__( + self, + table_name: str, + key_attr: str = "id", + state_attr: str = "state", + failure_count_attr: str = "failure_count", + opened_at_attr: str = "opened_at", + half_open_owner_attr: str = "half_open_owner", + probe_lease_expiry_attr: str = "probe_lease_expiry", + expiry_attr: str = "expiration", + boto_config: Config | None = None, + boto3_session: boto3.session.Session | None = None, + boto3_client: DynamoDBClient | None = None, + ): + if boto3_client is None: + boto3_session = boto3_session or boto3.session.Session() + boto3_client = boto3_session.client("dynamodb", config=boto_config) + self.client = boto3_client + + user_agent.register_feature_to_client(client=self.client, feature="circuit_breaker") + + self.table_name = table_name + self.key_attr = key_attr + self.state_attr = state_attr + self.failure_count_attr = failure_count_attr + self.opened_at_attr = opened_at_attr + self.half_open_owner_attr = half_open_owner_attr + self.probe_lease_expiry_attr = probe_lease_expiry_attr + self.expiry_attr = expiry_attr + + self._deserializer = TypeDeserializer() + + super().__init__() + + def _item_to_record(self, item: dict) -> CircuitStateRecord: + """Translate a raw DynamoDB item into a :class:`CircuitStateRecord`.""" + data = self._deserializer.deserialize({"M": item}) + opened_at = data.get(self.opened_at_attr) + probe_lease_expiry = data.get(self.probe_lease_expiry_attr) + return CircuitStateRecord( + name=data[self.key_attr], + state=CircuitState(data[self.state_attr]), + failure_count=int(data.get(self.failure_count_attr, 0)), + opened_at=int(opened_at) if opened_at is not None else None, + half_open_owner=data.get(self.half_open_owner_attr), + probe_lease_expiry=int(probe_lease_expiry) if probe_lease_expiry is not None else None, + expiry_timestamp=data.get(self.expiry_attr), + ) + + @staticmethod + def _n(value: int | str) -> dict: + """Wrap a value as a DynamoDB number attribute.""" + return {"N": str(value)} + + @staticmethod + def _s(value: str) -> dict: + """Wrap a value as a DynamoDB string attribute.""" + return {"S": value} + + def _record_to_item(self, record: CircuitStateRecord) -> dict: + """Translate a :class:`CircuitStateRecord` into a DynamoDB item.""" + item: dict = { + self.key_attr: self._s(record.name), + self.state_attr: self._s(str(record.state)), + self.failure_count_attr: self._n(record.failure_count), + } + if record.opened_at is not None: + item[self.opened_at_attr] = self._n(record.opened_at) + if record.half_open_owner is not None: + item[self.half_open_owner_attr] = self._s(record.half_open_owner) + if record.probe_lease_expiry is not None: + item[self.probe_lease_expiry_attr] = self._n(record.probe_lease_expiry) + if record.expiry_timestamp is not None: + item[self.expiry_attr] = self._n(record.expiry_timestamp) + return item + + def _get_record(self, name: str) -> CircuitStateRecord | None: + # Eventually consistent on purpose: matches the local cache's stale tolerance + # and halves the read cost on the hot path. + response = self.client.get_item( + TableName=self.table_name, + Key={self.key_attr: self._s(name)}, + ConsistentRead=False, + ) + item = response.get("Item") + if item is None: + return None + return self._item_to_record(item) + + def _build_half_open_condition(self, expected_opened_at: int | None = None) -> dict: + """Build the conditional expression kwargs for a half-open probe election.""" + condition_parts = [ + "(#state = :open AND attribute_not_exists(#half_open_owner))", + "(#state = :half_open AND #probe_lease_expiry <= :now)", + ] + expression_attr_names: dict = { + "#state": self.state_attr, + "#half_open_owner": self.half_open_owner_attr, + "#probe_lease_expiry": self.probe_lease_expiry_attr, + } + expression_values: dict = { + ":open": self._s(str(CircuitState.OPEN)), + ":half_open": self._s(str(CircuitState.HALF_OPEN)), + ":now": self._n(int(datetime.datetime.now().timestamp())), + } + + if expected_opened_at is not None: + condition_parts[0] = ( + "(#state = :open AND attribute_not_exists(#half_open_owner) AND #opened_at = :expected_opened_at)" + ) + expression_attr_names["#opened_at"] = self.opened_at_attr + expression_values[":expected_opened_at"] = self._n(expected_opened_at) + + return { + "ConditionExpression": " OR ".join(condition_parts), + "ExpressionAttributeNames": expression_attr_names, + "ExpressionAttributeValues": expression_values, + } + + def _put_record( + self, + record: CircuitStateRecord, + condition: str | None = None, + expected_opened_at: int | None = None, + ) -> None: + item = self._record_to_item(record) + + put_kwargs: dict = {"TableName": self.table_name, "Item": item} + + if condition == "half_open": + put_kwargs.update(self._build_half_open_condition(expected_opened_at)) + + try: + self.client.put_item(**put_kwargs) + except ClientError as exc: + if exc.response.get("Error", {}).get("Code") == "ConditionalCheckFailedException": + raise CircuitBreakerExistingLockError from exc + raise + + def _build_update_query(self, record: CircuitStateRecord) -> dict: + """Build the update_item kwargs for an unconditional state change.""" + update_expression = "SET #state = :state, #failure_count = :failure_count" + expression_attr_names = { + "#state": self.state_attr, + "#failure_count": self.failure_count_attr, + } + expression_attr_values: dict = { + ":state": self._s(str(record.state)), + ":failure_count": self._n(record.failure_count), + } + + if record.expiry_timestamp is not None: + update_expression += ", #expiration = :expiration" + expression_attr_names["#expiration"] = self.expiry_attr + expression_attr_values[":expiration"] = self._n(record.expiry_timestamp) + + # Clear the half-open owner lock and probe lease on every state change out of + # HALF_OPEN, whether the probe closed the circuit (opened_at is None) or reopened + # it (opened_at set). Otherwise the stale owner/lease makes the next probe + # election's condition fail forever, stranding the circuit. + expression_attr_names["#opened_at"] = self.opened_at_attr + expression_attr_names["#half_open_owner"] = self.half_open_owner_attr + expression_attr_names["#probe_lease_expiry"] = self.probe_lease_expiry_attr + if record.opened_at is not None: + update_expression += ", #opened_at = :opened_at REMOVE #half_open_owner, #probe_lease_expiry" + expression_attr_values[":opened_at"] = self._n(record.opened_at) + else: + update_expression += " REMOVE #opened_at, #half_open_owner, #probe_lease_expiry" + + return { + "TableName": self.table_name, + "Key": {self.key_attr: self._s(record.name)}, + "UpdateExpression": update_expression, + "ExpressionAttributeNames": expression_attr_names, + "ExpressionAttributeValues": expression_attr_values, + } + + def _update_record(self, record: CircuitStateRecord) -> None: + self.client.update_item(**self._build_update_query(record)) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py new file mode 100644 index 00000000000..71086c3c1a7 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py @@ -0,0 +1,63 @@ +""" +Internal record type for circuit state held in a persistence store. +""" + +from __future__ import annotations + +from dataclasses import dataclass + +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo, CircuitState + + +@dataclass +class CircuitStateRecord: + """ + The persisted state of a single circuit. + + One record exists per circuit name. This is the utility's internal representation; + user code never sees it directly, only the ``CircuitInfo`` produced by + :meth:`to_circuit_info`. + + Parameters + ---------- + name : str + Circuit name, used as the partition key in the store. + state : CircuitState + Current circuit state. + failure_count : int + Consecutive failures recorded by the environment that last wrote the record. + opened_at : int | None + Unix timestamp (seconds) the circuit opened. Anchors the recovery timeout; + ``None`` while closed. + half_open_owner : str | None + Identifier of the execution environment that won the half-open probe lock, if any. + expiry_timestamp : int | None + Unix timestamp (seconds) for the store's TTL attribute. + """ + + name: str + state: CircuitState + failure_count: int = 0 + opened_at: int | None = None + half_open_owner: str | None = None + probe_lease_expiry: int | None = None + expiry_timestamp: int | None = None + + def to_circuit_info(self) -> CircuitInfo: + """ + Project this record to the public ``CircuitInfo`` handed to user code. + + Strips internal fields (``half_open_owner``, ``expiry_timestamp``) so no + persistence detail leaks across the public boundary. + + Returns + ------- + CircuitInfo + Public snapshot of the circuit. + """ + return CircuitInfo( + name=self.name, + state=self.state, + failure_count=self.failure_count, + opened_at=self.opened_at, + ) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/states.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/states.py new file mode 100644 index 00000000000..cc041e17a36 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/states.py @@ -0,0 +1,126 @@ +""" +Public state types for the Circuit Breaker utility. + +These are the only circuit-breaker types handed to user code (callbacks and the +``CircuitInfo`` attached to ``CircuitBreakerOpenError``). They deliberately expose no +persistence internals. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum + + +class CircuitState(str, Enum): + """ + The state of a circuit. + + Subclasses ``str`` so the value serializes directly to a persistence store as a + plain string (e.g. DynamoDB) and compares equal to its string form. + + Attributes + ---------- + CLOSED : str + Normal operation. Requests reach the downstream and failures are counted. + OPEN : str + The downstream is considered unhealthy. The protected call is skipped. + HALF_OPEN : str + Recovery is being tested. A limited number of probe requests are allowed + through to decide whether the circuit should close again. + """ + + CLOSED = "CLOSED" + OPEN = "OPEN" + HALF_OPEN = "HALF_OPEN" + + def __str__(self) -> str: + """Return the bare value (e.g. ``"OPEN"``) rather than ``CircuitState.OPEN``.""" + return self.value + + +@dataclass(frozen=True) +class CircuitInfo: + """ + Immutable snapshot of a circuit, passed to user code. + + This is the public boundary of the utility: it is the single argument (alongside + the payload) handed to an ``on_circuit_open`` callback, and it is attached to + ``CircuitBreakerOpenError`` so a caller can inspect why the circuit rejected the + request. No persistence details (probe lock, TTL) are exposed. + + Parameters + ---------- + name : str + The circuit name, as given to the ``@circuit_breaker`` decorator. + state : CircuitState + The circuit state at the moment the request was evaluated. + failure_count : int + A point-in-time snapshot of the *consecutive* failures the environment that + last wrote the record had counted, captured at the moment of a state + transition. It is **not** a running total of failures across the fleet: the + failure counter lives in memory per execution environment (so the healthy path + stays write-free), and only the tripping environment's count is persisted when + the circuit opens. It is ``0`` in states reached without a fresh trip (for + example ``HALF_OPEN``, or ``OPEN`` re-entered after a failed probe). For failure + *volume*, emit a CloudWatch metric from your own code or an ``on_transition`` + hook rather than reading this field. + opened_at : int | None + Unix timestamp (seconds) at which the circuit opened, or ``None`` while the + circuit is closed. Drives the recovery timeout. + + Example + ------- + **Inspecting circuit details inside a callback** + + def on_open(payload: dict, circuit: CircuitInfo): + logger.warning("circuit %s open since %s", circuit.name, circuit.opened_at) + return {"statusCode": 503} + """ + + name: str + state: CircuitState + failure_count: int + opened_at: int | None = None + + +@dataclass(frozen=True) +class CircuitTransition: + """ + Immutable description of a circuit state change, passed to an ``on_transition`` hook. + + The hook fires only on the rare state transitions a circuit makes (open, probe, + close, reopen), never on the per-invocation hot path, so emitting a metric from it + does not undermine the write-free healthy path. + + Parameters + ---------- + circuit_name : str + The circuit name, as given to the ``@circuit_breaker`` decorator. + from_state : CircuitState + The state the circuit was in before the transition. + to_state : CircuitState + The state the circuit moved to. + opened_at : int | None + Unix timestamp (seconds) the circuit opened, when relevant to the new state. + + Example + ------- + **Emit a CloudWatch metric per transition** + + from aws_lambda_powertools.metrics import MetricUnit, single_metric + + def emit(transition: CircuitTransition) -> None: + with single_metric( + namespace="MyApp", + name=f"Circuit{transition.to_state}", + unit=MetricUnit.Count, + value=1, + ) as metric: + metric.add_dimension(name="circuit", value=transition.circuit_name) + """ + + circuit_name: str + from_state: CircuitState + to_state: CircuitState + opened_at: int | None = None diff --git a/docs/api_doc/circuit_breaker_alpha/circuit_breaker.md b/docs/api_doc/circuit_breaker_alpha/circuit_breaker.md new file mode 100644 index 00000000000..824b40225bc --- /dev/null +++ b/docs/api_doc/circuit_breaker_alpha/circuit_breaker.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker_alpha.circuit_breaker diff --git a/docs/api_doc/circuit_breaker_alpha/config.md b/docs/api_doc/circuit_breaker_alpha/config.md new file mode 100644 index 00000000000..20b548082c1 --- /dev/null +++ b/docs/api_doc/circuit_breaker_alpha/config.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker_alpha.config diff --git a/docs/api_doc/circuit_breaker_alpha/exceptions.md b/docs/api_doc/circuit_breaker_alpha/exceptions.md new file mode 100644 index 00000000000..283374e42e5 --- /dev/null +++ b/docs/api_doc/circuit_breaker_alpha/exceptions.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions diff --git a/docs/api_doc/circuit_breaker_alpha/persistence.md b/docs/api_doc/circuit_breaker_alpha/persistence.md new file mode 100644 index 00000000000..f865dfd10f0 --- /dev/null +++ b/docs/api_doc/circuit_breaker_alpha/persistence.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence diff --git a/docs/api_doc/circuit_breaker_alpha/states.md b/docs/api_doc/circuit_breaker_alpha/states.md new file mode 100644 index 00000000000..c6f232a0e28 --- /dev/null +++ b/docs/api_doc/circuit_breaker_alpha/states.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker_alpha.states diff --git a/docs/utilities/circuit_breaker.md b/docs/utilities/circuit_breaker.md new file mode 100644 index 00000000000..5087e24310b --- /dev/null +++ b/docs/utilities/circuit_breaker.md @@ -0,0 +1,227 @@ +--- +title: Circuit Breaker +description: Utility +--- + + + +!!! warning "Alpha / experimental" + This utility ships under the **`circuit_breaker_alpha`** namespace while we collect + feedback. The public API may change in a backwards-incompatible way before it is + promoted to GA, at which point the import path becomes `circuit_breaker`. Pin your + Powertools version and follow the tracking discussion before relying on it in + production. + +The circuit breaker utility stops sending traffic to an unhealthy downstream dependency, giving it room to recover while you decide what happens to the rejected requests. + +## Key features + +* Stops calling an unhealthy downstream after a configurable number of consecutive failures +* Hands rejected requests to an `on_circuit_open` callback so you decide what happens next (buffer, drop, return a cached value) +* Tests recovery with an explicit half-open probe rather than blindly retrying everything at once +* Shares circuit state across execution environments via Amazon DynamoDB +* Keeps the healthy path write-free: failures are counted in memory and only persisted on a state transition + +## Terminology + +**Circuit** is a named guard around a single downstream dependency. Each `name` is an independent circuit. + +**State** is the circuit's current mode: `CLOSED` (healthy), `OPEN` (downstream considered unhealthy, calls skipped), or `HALF_OPEN` (testing recovery). + +**Persistence layer** is the shared storage that holds each circuit's state so every execution environment agrees on whether a circuit is open. + +**Recovery timeout** is how long a circuit stays open before allowing a half-open probe. + +
+```mermaid +stateDiagram-v2 + [*] --> CLOSED + CLOSED --> OPEN: N consecutive failures + OPEN --> HALF_OPEN: recovery timeout elapsed + HALF_OPEN --> CLOSED: probe succeeds + HALF_OPEN --> OPEN: probe fails +``` + +Circuit breaker state transitions +
+ +## Getting started + +We use Amazon DynamoDB as the persistence layer in this documentation. + +### IAM Permissions + +When using Amazon DynamoDB as the persistence layer, you will need the following IAM permissions: + +| IAM Permission | Operation | +| ------------------------------------ | ------------------------------------------------------- | +| **`dynamodb:GetItem`**{: .copyMe} | Read shared circuit state | +| **`dynamodb:PutItem`**{: .copyMe} | Persist an opened circuit and elect the half-open probe | +| **`dynamodb:UpdateItem`**{: .copyMe} | Close or reopen a circuit after a probe | + +### Required resources + +To start, you'll need: + + + +
+* **Persistent storage** + + --- + + [Amazon DynamoDB](#dynamodb-table) + +* **AWS Lambda function** + + --- + + With permissions to read and write your persistent storage + +
+ + + +#### DynamoDB table + +Unless you're looking to [customize each attribute](#customizing-the-dynamodb-table), you only need the following: + +| Configuration | Value | Notes | +| ------------------ | ------------ | ------------------------------------------------------------ | +| Partition key | `id` | Holds the circuit name | +| TTL attribute name | `expiration` | Using AWS Console? This is configurable after table creation | + +You **can** use a single DynamoDB table for all your circuits. + +##### DynamoDB IaC example + +=== "AWS Serverless Application Model (SAM) example" + + ```yaml hl_lines="3-15 24-29 32-33" + --8<-- "examples/circuit_breaker_alpha/templates/sam.yaml" + ``` + +### Circuit breaker in action + +The common case is the `@circuit_breaker` decorator wrapping the function that makes the downstream call. With no `config`, sensible defaults apply (open after 5 consecutive failures, probe after 30 seconds, close after 3 probe successes, count any exception as a failure). + +=== "getting_started_with_circuit_breaker.py" + + ```python hl_lines="3-6 9 19 27" + --8<-- "examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py" + ``` + +!!! note "Wrap the downstream call, not the whole handler" + The circuit protects a single dependency. If you decorate a handler that parses the + event, validates, and calls two backends, a parsing bug would trip a circuit named + after a backend that is perfectly healthy. Decorate the handler directly only when + the handler **is** the downstream call (a thin pass-through). + +### What the decorated function returns + +There is no wrapper type to inspect. The contract is: + +| Circuit state | Result | +| ------------------------------------- | ---------------------------------------------------------------------- | +| **Closed** | The protected function's return value | +| **Open**, `on_circuit_open` set | Whatever the callback returns | +| **Open**, no callback | Raises `CircuitBreakerOpenError` (with the `CircuitInfo` attached) | + +## Handling an open circuit + +### With a callback + +Register an `on_circuit_open` callback to decide what happens to a rejected request. The callback receives the same arguments the protected function was called with (positional arguments stay positional, keyword arguments stay keyword), plus a trailing `circuit` keyword argument carrying a `CircuitInfo` snapshot. Its return value becomes the result of the call. + +=== "working_with_callback.py" + + ```python hl_lines="6 24-28 31-35" + --8<-- "examples/circuit_breaker_alpha/src/working_with_callback.py" + ``` + +!!! info "Why a callback instead of built-in S3/SQS sinks?" + A callback keeps you in control of where rejected requests go. You pick the + destination, the client, and the IAM, and you avoid coupling your function to a + sink the utility manages for you. + +### Without a callback + +If you don't register a callback, an open circuit raises `CircuitBreakerOpenError`. Catch it to decide how to respond. The exception carries a `circuit` attribute (`CircuitInfo`) so you can inspect why the circuit rejected the request. + +=== "working_without_callback.py" + + ```python hl_lines="5 16-22 38-43" + --8<-- "examples/circuit_breaker_alpha/src/working_without_callback.py" + ``` + +## Configuration + +All options live on `CircuitBreakerConfig`. Every value has a default, so `CircuitBreakerConfig()` is a valid production configuration. + +| Parameter | Default | Description | +| ------------------------- | ------- | ------------------------------------------------------------------------------------------------- | +| **`failure_threshold`** | `5` | Consecutive failures that trip a closed circuit to open | +| **`recovery_timeout`** | `30` | Seconds the circuit stays open before a half-open probe | +| **`success_threshold`** | `3` | Consecutive probe successes required to close a half-open circuit | +| **`handled_exceptions`** | `None` | Allowlist: only these exception types count as failures. Mutually exclusive with the denylist | +| **`ignored_exceptions`** | `None` | Denylist: every exception counts as a failure except these. Mutually exclusive with the allowlist | +| **`local_cache_max_age`** | `5` | Seconds a circuit's state is cached per environment before a read-through | + +### Choosing which exceptions count as a failure + +By default, **any exception** counts as a failure. But not every error means the downstream is unhealthy: a `400` is the caller's fault, a `503` is not. Scope it from either side: + +* **`handled_exceptions`** (allowlist): only these count. Everything else propagates without affecting the circuit. +* **`ignored_exceptions`** (denylist): everything counts except these. + +Passing both raises `CircuitBreakerConfigError`. An exception that doesn't count is re-raised to the caller untouched. + +## Advanced + +### How recovery works + +After `recovery_timeout` seconds, the circuit moves to `HALF_OPEN` and elects a **single** execution environment (via a conditional DynamoDB write) to run a probe. If `success_threshold` consecutive probes succeed, the circuit closes; a single failing probe reopens it. This stops a thundering herd of every environment hammering a recovering backend at once. + +### State coordination across environments + +The consecutive-failure counter lives in memory per execution environment, so a healthy circuit performs **no writes**. Only when an environment reaches `failure_threshold` does it persist `OPEN`. The shared state is cached locally for `local_cache_max_age` seconds to avoid a read per invocation. A cache miss (cold start or expired entry) forces a read-through before routing. + +!!! note "Fail-open by design" + If the utility cannot reach the persistence store when reading state, it treats the + circuit as **closed**. A circuit breaker should never become the outage it is meant to prevent. + +### Observability with metrics + +Register an `on_transition` hook to be notified whenever the circuit changes state (open, probe, close, reopen). The hook fires **only on transitions**, never on the per-invocation hot path, so it is a safe place to emit a CloudWatch metric without giving up the write-free healthy path. It receives a single `CircuitTransition` (`circuit_name`, `from_state`, `to_state`, `opened_at`). + +=== "working_with_metrics.py" + + ```python hl_lines="3 12-21 26" + --8<-- "examples/circuit_breaker_alpha/src/working_with_metrics.py" + ``` + +Any exception raised inside the hook is swallowed and logged, so a misbehaving metric call can never break the protected request. + +!!! warning "`failure_count` is a trip-time snapshot, not a running total" + The `failure_count` on `CircuitInfo` is the number of *consecutive* failures the + environment that tripped the circuit had counted at the moment it opened. Because the + failure counter lives in memory per execution environment (keeping the healthy path + write-free), it is **not** a fleet-wide total and reads `0` in states reached without a + fresh trip (such as `HALF_OPEN`). For failure **volume**, emit a metric from your own + code or the `on_transition` hook rather than reading this field. + +### Disabling the circuit breaker + +Set **`POWERTOOLS_CIRCUIT_BREAKER_DISABLED`**{: .copyMe} to a truthy value to bypass the circuit entirely and always call the protected function. This is intended for **development environments only** and emits a warning. + +### Customizing the DynamoDB table + +`CircuitBreakerDynamoDBPersistence` accepts attribute-name overrides (`key_attr`, `state_attr`, `failure_count_attr`, `opened_at_attr`, `half_open_owner_attr`, `expiry_attr`) and the usual boto3 escape hatches (`boto3_session`, `boto3_client`, `boto_config`) for reusing an existing table layout or client. + +## Testing your code + +When unit testing the function a circuit protects, set `POWERTOOLS_CIRCUIT_BREAKER_DISABLED=true` to bypass the circuit and persistence layer entirely, so your tests exercise the business logic without needing DynamoDB. + +```bash title="Disabling circuit breaker for tests" +POWERTOOLS_CIRCUIT_BREAKER_DISABLED=true python -m pytest +``` diff --git a/examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py b/examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py new file mode 100644 index 00000000000..ad9a4de1066 --- /dev/null +++ b/examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py @@ -0,0 +1,29 @@ +import os + +from aws_lambda_powertools.utilities.circuit_breaker_alpha import circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.typing import LambdaContext + +table = os.getenv("CIRCUIT_BREAKER_TABLE", "") +persistence = CircuitBreakerDynamoDBPersistence(table_name=table) + + +class PaymentBackend: + def charge(self, order: dict): ... + + +payment_api = PaymentBackend() + + +@circuit_breaker(name="payment-backend", persistence_store=persistence) +def charge(order: dict) -> dict: + return payment_api.charge(order) # the protected downstream call + + +def lambda_handler(event: dict, context: LambdaContext): + # Circuit closed -> charge() runs and returns the backend response. + # Circuit open -> charge() is skipped and CircuitBreakerOpenError is raised, + # because no on_circuit_open callback is registered. + return charge(event) diff --git a/examples/circuit_breaker_alpha/src/working_with_callback.py b/examples/circuit_breaker_alpha/src/working_with_callback.py new file mode 100644 index 00000000000..d2b97ad6ac5 --- /dev/null +++ b/examples/circuit_breaker_alpha/src/working_with_callback.py @@ -0,0 +1,44 @@ +import json +import os + +import boto3 + +from aws_lambda_powertools.utilities.circuit_breaker_alpha import CircuitInfo, circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.typing import LambdaContext + +table = os.getenv("CIRCUIT_BREAKER_TABLE", "") +queue_url = os.getenv("OVERFLOW_QUEUE_URL", "") +persistence = CircuitBreakerDynamoDBPersistence(table_name=table) +sqs = boto3.client("sqs") + + +class PaymentBackend: + def charge(self, order: dict): ... + + +payment_api = PaymentBackend() + + +def buffer_payload(order: dict, circuit: CircuitInfo) -> dict: + # Circuit is OPEN. The protected call never ran and the payload is yours to handle: + # buffer it, drop it, or return a cached value. Here we push it to an overflow queue. + sqs.send_message(QueueUrl=queue_url, MessageBody=json.dumps(order)) + return {"statusCode": 202, "circuit": circuit.name} + + +@circuit_breaker( + name="payment-backend", + persistence_store=persistence, + on_circuit_open=buffer_payload, +) +def charge(order: dict) -> dict: + return payment_api.charge(order) + + +def lambda_handler(event: dict, context: LambdaContext): + # Circuit closed -> returns the backend response. + # Circuit open -> buffer_payload(event, circuit) runs and its return value is returned. + return charge(event) diff --git a/examples/circuit_breaker_alpha/src/working_with_metrics.py b/examples/circuit_breaker_alpha/src/working_with_metrics.py new file mode 100644 index 00000000000..f37f1b68351 --- /dev/null +++ b/examples/circuit_breaker_alpha/src/working_with_metrics.py @@ -0,0 +1,45 @@ +import os + +from aws_lambda_powertools.metrics import MetricUnit, single_metric +from aws_lambda_powertools.utilities.circuit_breaker_alpha import ( + CircuitTransition, + circuit_breaker, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.typing import LambdaContext + +table = os.getenv("CIRCUIT_BREAKER_TABLE", "") +persistence = CircuitBreakerDynamoDBPersistence(table_name=table) + + +def emit_transition_metric(transition: CircuitTransition) -> None: + # Fires only when the circuit changes state, so this never runs on the hot path. + with single_metric( + namespace="MyApplication", + name=f"Circuit_{transition.to_state}", + unit=MetricUnit.Count, + value=1, + ) as metric: + metric.add_dimension(name="circuit", value=transition.circuit_name) + + +class PaymentBackend: + def charge(self, order: dict): ... + + +payment_api = PaymentBackend() + + +@circuit_breaker( + name="payment-backend", + persistence_store=persistence, + on_transition=emit_transition_metric, +) +def charge(order: dict) -> dict: + return payment_api.charge(order) + + +def lambda_handler(event: dict, context: LambdaContext): + return charge(event) diff --git a/examples/circuit_breaker_alpha/src/working_without_callback.py b/examples/circuit_breaker_alpha/src/working_without_callback.py new file mode 100644 index 00000000000..a5f166438c8 --- /dev/null +++ b/examples/circuit_breaker_alpha/src/working_without_callback.py @@ -0,0 +1,44 @@ +import os + +from aws_lambda_powertools.utilities.circuit_breaker_alpha import ( + CircuitBreakerConfig, + CircuitBreakerOpenError, + circuit_breaker, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.typing import LambdaContext + +table = os.getenv("CIRCUIT_BREAKER_TABLE", "") +persistence = CircuitBreakerDynamoDBPersistence(table_name=table) + +config = CircuitBreakerConfig( + failure_threshold=5, # consecutive failures before opening + recovery_timeout=30, # seconds in OPEN before a half-open probe + success_threshold=3, # consecutive probe successes before closing + # Only these exceptions count as a failure. A ValueError (caller's fault) is + # re-raised without affecting the circuit. + handled_exceptions=(TimeoutError, ConnectionError), +) + + +class PaymentBackend: + def charge(self, order: dict): ... + + +payment_api = PaymentBackend() + + +@circuit_breaker(name="payment-backend", persistence_store=persistence, config=config) +def charge(order: dict) -> dict: + return payment_api.charge(order) + + +def lambda_handler(event: dict, context: LambdaContext): + try: + return charge(event) + except CircuitBreakerOpenError as exc: + # No callback registered, so we decide what to do with the rejected request here. + circuit_name = exc.circuit.name if exc.circuit else "unknown" + return {"statusCode": 202, "circuit": circuit_name} diff --git a/examples/circuit_breaker_alpha/templates/sam.yaml b/examples/circuit_breaker_alpha/templates/sam.yaml new file mode 100644 index 00000000000..686a2caaecf --- /dev/null +++ b/examples/circuit_breaker_alpha/templates/sam.yaml @@ -0,0 +1,33 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + CircuitBreakerTable: + Type: AWS::DynamoDB::Table + Properties: + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + TimeToLiveSpecification: + AttributeName: expiration + Enabled: true + BillingMode: PAY_PER_REQUEST + + HelloWorldFunction: + Type: AWS::Serverless::Function + Properties: + Runtime: python3.12 + Handler: app.py + Policies: + - Statement: + - Sid: AllowDynamodbReadWrite + Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + - dynamodb:UpdateItem + Resource: !GetAtt CircuitBreakerTable.Arn + Environment: + Variables: + CIRCUIT_BREAKER_TABLE: !Ref CircuitBreakerTable diff --git a/mkdocs.yml b/mkdocs.yml index 6bea356bac6..265560a55d5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,6 +33,7 @@ nav: - utilities/data_classes.md - utilities/parser.md - utilities/idempotency.md + - utilities/circuit_breaker.md - utilities/data_masking.md - utilities/feature_flags.md - utilities/metadata.md @@ -105,6 +106,12 @@ nav: - Exceptions: api_doc/feature_flags/exceptions.md - Feature flags: api_doc/feature_flags/feature_flags.md - Schema: api_doc/feature_flags/schema.md + - Circuit Breaker (alpha): + - Circuit Breaker: api_doc/circuit_breaker_alpha/circuit_breaker.md + - Config: api_doc/circuit_breaker_alpha/config.md + - States: api_doc/circuit_breaker_alpha/states.md + - Exceptions: api_doc/circuit_breaker_alpha/exceptions.md + - Persistence: api_doc/circuit_breaker_alpha/persistence.md - Idempotency: - Base: api_doc/idempotency/base.md - Config: api_doc/idempotency/config.md @@ -248,6 +255,7 @@ plugins: - utilities/data_classes.md - utilities/parser.md - utilities/idempotency.md + - utilities/circuit_breaker.md - utilities/data_masking.md - utilities/feature_flags.md - utilities/metadata.md diff --git a/tests/functional/circuit_breaker_alpha/__init__.py b/tests/functional/circuit_breaker_alpha/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/functional/circuit_breaker_alpha/conftest.py b/tests/functional/circuit_breaker_alpha/conftest.py new file mode 100644 index 00000000000..e2c9fc4d0d8 --- /dev/null +++ b/tests/functional/circuit_breaker_alpha/conftest.py @@ -0,0 +1,103 @@ +from __future__ import annotations + +import pytest + +import aws_lambda_powertools.utilities.circuit_breaker_alpha.base as base_module +from aws_lambda_powertools.utilities.circuit_breaker_alpha.base import CircuitBreakerHandler +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( + CircuitBreakerExistingLockError, + CircuitBreakerPersistenceLayer, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState + + +class FakePersistence(CircuitBreakerPersistenceLayer): + """In-memory store for exercising the handler state machine without DynamoDB.""" + + def __init__(self): + self.db: dict[str, CircuitStateRecord] = {} + super().__init__() + + def _get_record(self, name: str) -> CircuitStateRecord | None: + if name not in self.db: + return None + stored = self.db[name] + # Return a copy so the handler can't mutate stored state by reference. + return CircuitStateRecord( + name=stored.name, + state=stored.state, + failure_count=stored.failure_count, + opened_at=stored.opened_at, + half_open_owner=stored.half_open_owner, + probe_lease_expiry=stored.probe_lease_expiry, + ) + + def _put_record( + self, + record: CircuitStateRecord, + condition: str | None = None, + expected_opened_at: int | None = None, + ) -> None: + if condition == "half_open": + existing = self.db.get(record.name) + now = CircuitBreakerHandler._now() + + # Mirror the DynamoDB condition: two valid paths + # Path 1: state=OPEN AND no owner (AND opened_at matches if provided) + # Path 2: state=HALF_OPEN AND probe_lease_expiry <= now (lease takeover) + fresh_election_ok = existing is None or ( + existing.state == CircuitState.OPEN + and existing.half_open_owner is None + and (expected_opened_at is None or existing.opened_at == expected_opened_at) + ) + lease_takeover_ok = ( + existing is not None + and existing.state == CircuitState.HALF_OPEN + and existing.probe_lease_expiry is not None + and now >= existing.probe_lease_expiry + ) + + if not fresh_election_ok and not lease_takeover_ok: + raise CircuitBreakerExistingLockError + self.db[record.name] = record + + def _update_record(self, record: CircuitStateRecord) -> None: + # Mirror DynamoDB UpdateItem semantics: a partial merge driven by which + # attributes the backend actually writes, NOT a wholesale replace. This is + # what exposes attributes the update path forgets to clear (e.g. a stale + # half_open_owner left behind on reopen). + existing = self.db.get(record.name) + if existing is None: + self.db[record.name] = record + return + existing.state = record.state + existing.failure_count = record.failure_count + existing.expiry_timestamp = record.expiry_timestamp + # Leaving HALF_OPEN (close or reopen) always releases the probe-owner lock and + # probe lease; only opened_at differs between the two transitions. + existing.half_open_owner = None + existing.probe_lease_expiry = None + existing.opened_at = record.opened_at + + +@pytest.fixture +def store() -> FakePersistence: + return FakePersistence() + + +@pytest.fixture(autouse=True) +def reset_local_counters(): + """Clear the per-environment module-level counters between tests.""" + base_module._LOCAL_FAILURES.clear() + base_module._LOCAL_SUCCESSES.clear() + base_module._LAST_OBSERVED_STATE.clear() + yield + base_module._LOCAL_FAILURES.clear() + base_module._LOCAL_SUCCESSES.clear() + base_module._LAST_OBSERVED_STATE.clear() + + +@pytest.fixture +def now() -> int: + return base_module.CircuitBreakerHandler._now() diff --git a/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py b/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py new file mode 100644 index 00000000000..1227291ee66 --- /dev/null +++ b/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py @@ -0,0 +1,604 @@ +from __future__ import annotations + +import warnings + +import pytest + +import aws_lambda_powertools.utilities.circuit_breaker_alpha.base as base_module +from aws_lambda_powertools.utilities.circuit_breaker_alpha import ( + CircuitBreakerConfig, + CircuitBreakerOpenError, + CircuitState, + CircuitTransition, + circuit_breaker, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerError +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord + +# All tests disable the local read cache (max_age=0) so each call re-reads the fake store. + + +def test_closed_circuit_returns_result_and_writes_nothing(store): + @circuit_breaker(name="c", persistence_store=store, config=CircuitBreakerConfig(local_cache_max_age=0)) + def call(value): + return value * 2 + + assert call(21) == 42 + assert store.db == {}, "healthy path must not write to the store" + + +def test_trips_open_after_failure_threshold(store): + config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + raise ConnectionError("downstream down") + + for _ in range(3): + with pytest.raises(ConnectionError): + call() + + assert store.db["c"].state == CircuitState.OPEN + assert store.db["c"].opened_at is not None + + +def test_open_with_callback_returns_callback_value_without_calling_protected(store, now): + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now) + protected_ran = {"value": False} + + def on_open(order, circuit): + return {"buffered": order, "state": str(circuit.state)} + + config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, on_circuit_open=on_open, config=config) + def charge(order): + protected_ran["value"] = True + return f"charged {order}" + + result = charge({"id": 1}) + assert result == {"buffered": {"id": 1}, "state": "OPEN"} + assert protected_ran["value"] is False + + +def test_open_without_callback_raises_with_circuit_info(store, now): + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=7, opened_at=now) + config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def charge(order): + return f"charged {order}" + + with pytest.raises(CircuitBreakerOpenError) as exc_info: + charge({"id": 1}) + + assert exc_info.value.circuit.name == "c" + assert exc_info.value.circuit.failure_count == 7 + + +def test_half_open_probe_success_closes_after_success_threshold(store, now): + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100) + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + return "ok" + + call() # wins the probe lock, state becomes HALF_OPEN + assert store.db["c"].state == CircuitState.HALF_OPEN + + call() # second consecutive probe success closes the circuit + assert store.db["c"].state == CircuitState.CLOSED + + +def test_half_open_probe_failure_reopens(store, now): + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100) + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + raise ConnectionError("still down") + + with pytest.raises(ConnectionError): + call() + + assert store.db["c"].state == CircuitState.OPEN + + +# --------------------------------------------------------------------------- bug regressions + + +def test_half_open_can_be_reacquired_after_failed_probe_reopens(store, now): + # Bug #1: a failed probe (HALF_OPEN -> OPEN) must clear the half_open_owner so a + # later recovery window can elect a prober again. Otherwise the circuit is stuck + # OPEN forever because attribute_not_exists(half_open_owner) never holds again. + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100) + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0) + + outcomes = iter([ConnectionError("still down"), "recovered"]) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + result = next(outcomes) + if isinstance(result, Exception): + raise result + return result + + # First recovery window: env wins the probe, probe fails, circuit reopens. + with pytest.raises(ConnectionError): + call() + assert store.db["c"].state == CircuitState.OPEN + assert store.db["c"].half_open_owner is None, "reopen must release the probe lock" + + # Second recovery window (opened_at is fresh, push it into the past again). + store.db["c"].opened_at = now - 100 + # Downstream recovered: the env must be able to acquire the probe again and run it. + assert call() == "recovered" + assert store.db["c"].state == CircuitState.HALF_OPEN + + +def test_open_callback_receives_keyword_arguments_intact(store, now): + # Bug #3: the callback must receive the same kwargs the protected function got, + # as kwargs, not flattened into positional values. + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now) + config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0) + + captured = {} + + def on_open(order, customer, circuit): + captured["order"] = order + captured["customer"] = customer + return "buffered" + + @circuit_breaker(name="c", persistence_store=store, on_circuit_open=on_open, config=config) + def charge(order, customer): + return "charged" + + # Called entirely with keyword arguments, deliberately out of signature order. + assert charge(customer="alice", order={"id": 1}) == "buffered" + assert captured["order"] == {"id": 1} + assert captured["customer"] == "alice" + + +def test_consecutive_failures_trip_but_a_success_resets_the_streak(store): + # The failure counter is per-environment and counts *consecutive* failures as this + # env sees them: any success in between must reset the streak. + config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0) + + should_fail = {"value": True} + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + if should_fail["value"]: + raise ConnectionError("down") + return "ok" + + # Two failures, then a success: the streak resets, so the circuit must NOT be tripping. + for _ in range(2): + with pytest.raises(ConnectionError): + call() + should_fail["value"] = False + assert call() == "ok" + assert "c" not in store.db + + # A fresh run of 3 consecutive failures from here must trip it. + should_fail["value"] = True + for _ in range(3): + with pytest.raises(ConnectionError): + call() + assert store.db["c"].state == CircuitState.OPEN + + +def test_circuit_can_retrip_after_a_previous_close(store): + # Regression guard: a healthy circuit's steady state is a *persisted CLOSED* record. + # Reading that record must not reset the running failure counter, or the circuit + # could never trip again after it has closed once. + config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0) + + # Pretend a prior recovery left a persisted CLOSED record behind. + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.CLOSED, failure_count=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + raise ConnectionError("down again") + + for _ in range(3): + with pytest.raises(ConnectionError): + call() + + assert store.db["c"].state == CircuitState.OPEN, "circuit must re-trip even with a prior CLOSED record present" + + +def test_full_lifecycle_survives_multiple_recovery_cycles(store): + # End-to-end guard tying #1 together: the circuit must cycle OPEN -> HALF_OPEN -> + # CLOSED, re-trip, survive a failed probe (which reopens and must release the lock), + # and then recover again. Before the owner-release fix the second recovery dead-locked. + config = CircuitBreakerConfig( + failure_threshold=2, + recovery_timeout=30, + success_threshold=2, + local_cache_max_age=0, + ) + mode = {"value": "fail"} + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + if mode["value"] == "fail": + raise ConnectionError("down") + return "ok" + + def elapse_recovery_window(): + store.db["c"].opened_at -= 100 + + # Trip open. + for _ in range(2): + with pytest.raises(ConnectionError): + call() + assert store.db["c"].state == CircuitState.OPEN + + # Recover through two successful probes. + mode["value"] = "ok" + elapse_recovery_window() + assert call() == "ok" + assert store.db["c"].state == CircuitState.HALF_OPEN + assert call() == "ok" + assert store.db["c"].state == CircuitState.CLOSED + + # Re-trip from the now-CLOSED state. + mode["value"] = "fail" + for _ in range(2): + with pytest.raises(ConnectionError): + call() + assert store.db["c"].state == CircuitState.OPEN + + # A failed probe reopens it and must release the probe lock. + elapse_recovery_window() + with pytest.raises(ConnectionError): + call() + assert store.db["c"].state == CircuitState.OPEN + assert store.db["c"].half_open_owner is None + + # The lock being free, recovery must be possible again. + mode["value"] = "ok" + elapse_recovery_window() + assert call() == "ok" + assert store.db["c"].state == CircuitState.HALF_OPEN + assert call() == "ok" + assert store.db["c"].state == CircuitState.CLOSED + + +def test_opened_at_zero_is_treated_as_a_real_timestamp(store): + # Bug #7: opened_at == 0 is a valid (if pathological) epoch timestamp, not "missing". + # `record.opened_at or self._now()` wrongly re-anchors it to now, pinning OPEN forever. + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=0) + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + return "recovered" + + # opened_at=0 is far in the past, so the recovery window has long elapsed: + # the call must be allowed to probe, not short-circuited. + assert call() == "recovered" + assert store.db["c"].state in (CircuitState.HALF_OPEN, CircuitState.CLOSED) + + +def test_ignored_exception_does_not_trip_circuit(store): + config = CircuitBreakerConfig( + failure_threshold=2, + handled_exceptions=(ConnectionError,), + local_cache_max_age=0, + ) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + raise ValueError("caller error, not a downstream failure") + + for _ in range(5): + with pytest.raises(ValueError): + call() + + assert "c" not in store.db + + +def test_disabled_env_bypasses_circuit(store, now, monkeypatch): + monkeypatch.setenv("POWERTOOLS_CIRCUIT_BREAKER_DISABLED", "true") + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=9, opened_at=now) + config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + return "ran anyway" + + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + assert call() == "ran anyway" + + +def test_config_is_optional(store): + @circuit_breaker(name="c", persistence_store=store) + def call(): + return "ok" + + assert call() == "ok" + + +# --------------------------------------------------------------------------- on_transition hook + + +def test_on_transition_fires_for_each_state_change(store): + transitions: list[CircuitTransition] = [] + config = CircuitBreakerConfig( + failure_threshold=2, + recovery_timeout=30, + success_threshold=1, + local_cache_max_age=0, + ) + mode = {"value": "fail"} + + @circuit_breaker( + name="c", + persistence_store=store, + on_transition=transitions.append, + config=config, + ) + def call(): + if mode["value"] == "fail": + raise ConnectionError("down") + return "ok" + + # CLOSED -> OPEN after 2 failures. + for _ in range(2): + with pytest.raises(ConnectionError): + call() + # OPEN -> HALF_OPEN (election) -> CLOSED (success_threshold=1) on the recovery probe. + mode["value"] = "ok" + store.db["c"].opened_at -= 100 + assert call() == "ok" + + pairs = [(t.from_state, t.to_state) for t in transitions] + assert pairs == [ + (CircuitState.CLOSED, CircuitState.OPEN), + (CircuitState.OPEN, CircuitState.HALF_OPEN), + (CircuitState.HALF_OPEN, CircuitState.CLOSED), + ] + assert all(t.circuit_name == "c" for t in transitions) + # opened_at carried on the open/probe transitions, absent on close. + assert transitions[0].opened_at is not None + assert transitions[-1].opened_at is None + + +def test_on_transition_fires_on_failed_probe_reopen(store, now): + transitions: list[CircuitTransition] = [] + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100) + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, on_transition=transitions.append, config=config) + def call(): + raise ConnectionError("still down") + + with pytest.raises(ConnectionError): + call() + + pairs = [(t.from_state, t.to_state) for t in transitions] + assert pairs == [ + (CircuitState.OPEN, CircuitState.HALF_OPEN), + (CircuitState.HALF_OPEN, CircuitState.OPEN), + ] + + +def test_raising_on_transition_hook_is_swallowed(store): + config = CircuitBreakerConfig(failure_threshold=1, local_cache_max_age=0) + + def boom(_transition): + raise RuntimeError("hook blew up") + + @circuit_breaker(name="c", persistence_store=store, on_transition=boom, config=config) + def call(): + raise ConnectionError("down") + + # The hook raises during the CLOSED->OPEN notify, but the protected call's own + # ConnectionError must surface unchanged, not the hook's RuntimeError. + with pytest.raises(ConnectionError): + call() + assert store.db["c"].state == CircuitState.OPEN + + +# --------------------------------------------------------------------------- bug regressions + + +def test_stale_local_failures_reset_on_external_close(store, now): + """Bug 1: a partial failure streak in env A must not survive an external recovery cycle.""" + config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0) + mode = {"value": "fail"} + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + if mode["value"] == "fail": + raise ConnectionError("down") + return "ok" + + # Env A accumulates 2 failures (below threshold of 3). + for _ in range(2): + with pytest.raises(ConnectionError): + call() + assert base_module._LOCAL_FAILURES["c"] == 2 + + # Simulate: another env trips the circuit, then a third closes it. + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=3, opened_at=now) + # Force env A to observe OPEN so _LAST_OBSERVED_STATE tracks the transition. + with pytest.raises(CircuitBreakerOpenError): + call() + # Now the circuit is externally closed. + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.CLOSED, failure_count=0) + + # A single failure in env A must NOT re-trip (stale streak was invalidated). + mode["value"] = "fail" + with pytest.raises(ConnectionError): + call() + assert "c" not in store.db or store.db["c"].state == CircuitState.CLOSED + assert base_module._LOCAL_FAILURES["c"] == 1 # fresh count, not 3 + + +def test_store_write_failure_does_not_mask_downstream_result(store, now): + """Bug 2: if save_closed() fails, the successful probe result must still be returned.""" + config = CircuitBreakerConfig(failure_threshold=3, recovery_timeout=30, success_threshold=1, local_cache_max_age=0) + + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=3, opened_at=now - 100) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + return "payment_charged" + + # Make the persistence write fail. + original_update = store._update_record + + def failing_update(record): + raise RuntimeError("DynamoDB timeout") + + store._update_record = failing_update + + # The probe should still return the downstream result despite the write failure. + result = call() + assert result == "payment_charged" + + store._update_record = original_update + + +def test_store_write_failure_on_trip_does_not_replace_downstream_exception(store): + """Bug 2 (trip path): if save_open() fails, the downstream's own exception must propagate.""" + config = CircuitBreakerConfig(failure_threshold=2, local_cache_max_age=0) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + raise ConnectionError("the real error") + + # Make the persistence write fail. + def failing_put(record, condition=None, expected_opened_at=None): + raise RuntimeError("DynamoDB throttle") + + store._put_record = failing_put + + # Two failures should raise the ORIGINAL ConnectionError, not a RuntimeError from the store. + for _ in range(2): + with pytest.raises(ConnectionError, match="the real error"): + call() + + +def test_probe_lease_takeover_when_owner_recycled(store, now): + """Design issue 1: a stranded HALF_OPEN probe with expired lease can be taken over.""" + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0) + + # Simulate: the probe owner ("dead-env") was recycled, lease has expired. + store.db["c"] = CircuitStateRecord( + name="c", + state=CircuitState.HALF_OPEN, + opened_at=now - 200, + half_open_owner="dead-env", + probe_lease_expiry=now - 10, # expired + ) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + return "recovered" + + # Current environment should take over the expired lease and succeed. + result = call() + assert result == "recovered" + assert store.db["c"].state == CircuitState.CLOSED + + +def test_half_open_non_owner_with_active_lease_is_rejected(store, now): + """Design issue 1 negative: active lease must NOT allow takeover.""" + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0) + + # Probe owner is alive (lease not expired yet). + store.db["c"] = CircuitStateRecord( + name="c", + state=CircuitState.HALF_OPEN, + opened_at=now - 50, + half_open_owner="other-env", + probe_lease_expiry=now + 999, # far in the future + ) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + return "should not run" + + with pytest.raises(CircuitBreakerOpenError): + call() + + +def test_open_lost_election_returns_open_response(store, now): + """Branch: try_acquire_half_open returns False (another env won the race).""" + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0) + + # Circuit is OPEN and recovery window has elapsed, but election will fail + # because another env already holds the lock. + store.db["c"] = CircuitStateRecord( + name="c", + state=CircuitState.OPEN, + failure_count=5, + opened_at=now - 100, + half_open_owner="winner-env", + ) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + return "should not run" + + with pytest.raises(CircuitBreakerOpenError): + call() + + +def test_probe_ignored_exception_propagates_without_affecting_circuit(store, now): + """Branch: probe raises an exception that doesn't count as failure.""" + config = CircuitBreakerConfig( + recovery_timeout=30, + success_threshold=1, + handled_exceptions=(ConnectionError,), + local_cache_max_age=0, + ) + + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + raise ValueError("not a counted failure") + + with pytest.raises(ValueError, match="not a counted failure"): + call() + # Circuit should still be HALF_OPEN (not reopened), the ValueError didn't count. + assert store.db["c"].state == CircuitState.HALF_OPEN + + +def test_local_cache_serves_state_without_store_read(store): + """Covers the cache hit path (persistence/base.py line 140).""" + config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=60) + call_count = {"value": 0} + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + call_count["value"] += 1 + return "ok" + + # First call reads the store (cache miss). + assert call() == "ok" + # Second call should serve from cache — override _get_record to detect reads. + original_get = store._get_record + get_called = {"value": False} + + def tracked_get(name): + get_called["value"] = True + return original_get(name) + + store._get_record = tracked_get + assert call() == "ok" + assert not get_called["value"], "second call should have used the cache, not the store" + store._get_record = original_get + + +def test_error_with_details_formatting(): + """Covers exceptions.py line 28 — __str__ with details.""" + err = CircuitBreakerError("main message", "extra detail") + assert str(err) == "main message - (extra detail)" diff --git a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py new file mode 100644 index 00000000000..d1617f26617 --- /dev/null +++ b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py @@ -0,0 +1,270 @@ +from __future__ import annotations + +import boto3 +import pytest +from botocore.config import Config +from botocore.stub import Stubber + +from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState + +TABLE_NAME = "CircuitBreakerState" + + +@pytest.fixture +def persistence(): + client = boto3.client("dynamodb", config=Config(region_name="us-east-1")) + layer = CircuitBreakerDynamoDBPersistence(table_name=TABLE_NAME, boto3_client=client) + layer.configure(CircuitBreakerConfig(local_cache_max_age=0), circuit_name="payment") + return layer + + +def test_get_state_missing_item_returns_closed(persistence): + stubber = Stubber(persistence.client) + stubber.add_response( + "get_item", + {}, + {"TableName": TABLE_NAME, "Key": {"id": {"S": "payment"}}, "ConsistentRead": False}, + ) + with stubber: + record = persistence.get_state("payment") + assert record.state == CircuitState.CLOSED + + +def test_get_state_failing_store_fails_open(persistence): + stubber = Stubber(persistence.client) + stubber.add_client_error("get_item", service_error_code="InternalServerError") + with stubber: + record = persistence.get_state("payment") + assert record.state == CircuitState.CLOSED, "store failure must fail open (CLOSED)" + + +def _capture_put_item(persistence): + """Patch put_item to capture its params instead of asserting a time-dependent TTL.""" + captured = {} + original = persistence.client.put_item + + def capturing(**kwargs): + captured.update(kwargs) + return {} + + persistence.client.put_item = capturing + return captured, lambda: setattr(persistence.client, "put_item", original) + + +def test_save_open_writes_open_item(persistence): + captured, restore = _capture_put_item(persistence) + try: + persistence.save_open("payment", failure_count=5, opened_at=1000) + finally: + restore() + + item = captured["Item"] + assert item["id"] == {"S": "payment"} + assert item["state"] == {"S": "OPEN"} + assert item["failure_count"] == {"N": "5"} + assert item["opened_at"] == {"N": "1000"} + assert "expiration" in item, "open item must carry a TTL" + + +def test_try_acquire_half_open_wins(persistence): + captured, restore = _capture_put_item(persistence) + try: + assert persistence.try_acquire_half_open("payment", "env-a", 1000) is True + finally: + restore() + + item = captured["Item"] + assert item["state"] == {"S": "HALF_OPEN"} + assert item["half_open_owner"] == {"S": "env-a"} + assert item["opened_at"] == {"N": "1000"} + assert "expiration" in item + # Condition supports both fresh election (OPEN, no owner, matching opened_at) and + # lease takeover (HALF_OPEN with expired lease). + assert "#state = :open AND attribute_not_exists(#half_open_owner)" in captured["ConditionExpression"] + assert "#probe_lease_expiry <= :now" in captured["ConditionExpression"] + assert captured["ExpressionAttributeValues"][":open"] == {"S": "OPEN"} + assert captured["ExpressionAttributeValues"][":expected_opened_at"] == {"N": "1000"} + assert "probe_lease_expiry" in item + + +def test_try_acquire_half_open_loses_on_conditional_failure(persistence): + stubber = Stubber(persistence.client) + stubber.add_client_error("put_item", service_error_code="ConditionalCheckFailedException") + with stubber: + assert persistence.try_acquire_half_open("payment", "env-b", 1000) is False + + +def test_save_closed_updates_record(persistence): + stubber = Stubber(persistence.client) + stubber.add_response("update_item", {}) + with stubber: + persistence.save_closed("payment") + stubber.assert_no_pending_responses() + + +# --------------------------------------------------------------------------- bug regressions + + +def test_save_reopen_removes_half_open_owner(persistence): + # Bug #1: HALF_OPEN -> OPEN must clear half_open_owner, otherwise the next + # probe election (attribute_not_exists(half_open_owner)) can never succeed. + captured = {} + original_update = persistence.client.update_item + + def capturing_update(**kwargs): + captured.update(kwargs) + return {} + + persistence.client.update_item = capturing_update + try: + persistence.save_reopen("payment", opened_at=2000) + finally: + persistence.client.update_item = original_update + + expression = captured["UpdateExpression"] + assert "REMOVE" in expression + assert captured["ExpressionAttributeNames"]["#half_open_owner"] == "half_open_owner" + assert "#half_open_owner" in expression.split("REMOVE", 1)[1], "owner must be in the REMOVE clause" + + +def test_save_open_item_contains_expiration_attribute(persistence): + # Bug #2: the written item must carry the TTL (expiration) attribute, otherwise + # the documented self-cleaning of abandoned circuits never happens. Capture the + # actual PutItem params rather than asserting an exact (time-dependent) value. + captured = {} + persistence.local_cache_max_age = 5 + + original_put = persistence.client.put_item + + def capturing_put(**kwargs): + captured.update(kwargs) + return {} + + persistence.client.put_item = capturing_put + try: + persistence.save_open("payment", failure_count=5, opened_at=1000) + finally: + persistence.client.put_item = original_put + + item = captured["Item"] + assert "expiration" in item, "open item must carry a DynamoDB TTL attribute" + + +# --------------------------------------------------------------------------- serialization coverage + + +def test_item_to_record_full_item(persistence): + """Cover _item_to_record with all fields present (lines 109-122).""" + item = { + "id": {"S": "payment"}, + "state": {"S": "HALF_OPEN"}, + "failure_count": {"N": "3"}, + "opened_at": {"N": "1000"}, + "half_open_owner": {"S": "env-x"}, + "probe_lease_expiry": {"N": "2000"}, + "expiration": {"N": "9999"}, + } + record = persistence._item_to_record(item) + assert record.name == "payment" + assert record.state == CircuitState.HALF_OPEN + assert record.failure_count == 3 + assert record.opened_at == 1000 + assert record.half_open_owner == "env-x" + assert record.probe_lease_expiry == 2000 + assert record.expiry_timestamp == 9999 + + +def test_item_to_record_minimal_item(persistence): + """Cover _item_to_record with optional fields absent.""" + item = { + "id": {"S": "payment"}, + "state": {"S": "CLOSED"}, + } + record = persistence._item_to_record(item) + assert record.name == "payment" + assert record.state == CircuitState.CLOSED + assert record.failure_count == 0 + assert record.opened_at is None + assert record.half_open_owner is None + assert record.probe_lease_expiry is None + + +def test_record_to_item_full_record(persistence): + """Cover _record_to_item with all fields set (lines 124-139).""" + from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord + + record = CircuitStateRecord( + name="payment", + state=CircuitState.HALF_OPEN, + failure_count=5, + opened_at=1000, + half_open_owner="env-a", + probe_lease_expiry=2000, + expiry_timestamp=9999, + ) + item = persistence._record_to_item(record) + assert item["id"] == {"S": "payment"} + assert item["state"] == {"S": "HALF_OPEN"} + assert item["failure_count"] == {"N": "5"} + assert item["opened_at"] == {"N": "1000"} + assert item["half_open_owner"] == {"S": "env-a"} + assert item["probe_lease_expiry"] == {"N": "2000"} + assert item["expiration"] == {"N": "9999"} + + +def test_record_to_item_minimal_record(persistence): + """Cover _record_to_item with optional fields as None (branch misses on lines 131-137).""" + from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord + + record = CircuitStateRecord(name="payment", state=CircuitState.CLOSED) + item = persistence._record_to_item(record) + assert item == { + "id": {"S": "payment"}, + "state": {"S": "CLOSED"}, + "failure_count": {"N": "0"}, + } + assert "opened_at" not in item + assert "half_open_owner" not in item + assert "probe_lease_expiry" not in item + assert "expiration" not in item + + +def test_get_record_returns_deserialized_item(persistence): + """Cover _get_record success path (lines 141-153).""" + stubber = Stubber(persistence.client) + stubber.add_response( + "get_item", + { + "Item": { + "id": {"S": "payment"}, + "state": {"S": "OPEN"}, + "failure_count": {"N": "5"}, + "opened_at": {"N": "1000"}, + }, + }, + {"TableName": TABLE_NAME, "Key": {"id": {"S": "payment"}}, "ConsistentRead": False}, + ) + with stubber: + record = persistence._get_record("payment") + assert record.state == CircuitState.OPEN + assert record.failure_count == 5 + assert record.opened_at == 1000 + + +def test_build_half_open_condition_without_expected_opened_at(persistence): + """Cover _build_half_open_condition when expected_opened_at is None (line 172 branch).""" + result = persistence._build_half_open_condition(expected_opened_at=None) + assert ":expected_opened_at" not in result["ConditionExpression"] + assert "#opened_at" not in result["ExpressionAttributeNames"] + + +def test_build_half_open_condition_with_expected_opened_at(persistence): + """Cover _build_half_open_condition when expected_opened_at is set (lines 172-177).""" + result = persistence._build_half_open_condition(expected_opened_at=5000) + assert "#opened_at = :expected_opened_at" in result["ConditionExpression"] + assert result["ExpressionAttributeNames"]["#opened_at"] == "opened_at" + assert result["ExpressionAttributeValues"][":expected_opened_at"] == {"N": "5000"} diff --git a/tests/unit/circuit_breaker_alpha/__init__.py b/tests/unit/circuit_breaker_alpha/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/unit/circuit_breaker_alpha/test_config_and_states.py b/tests/unit/circuit_breaker_alpha/test_config_and_states.py new file mode 100644 index 00000000000..a0b811e38c0 --- /dev/null +++ b/tests/unit/circuit_breaker_alpha/test_config_and_states.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +import dataclasses + +import pytest + +from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import ( + CircuitBreakerConfigError, + CircuitBreakerOpenError, +) +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo, CircuitState + + +def test_circuit_state_serializes_to_plain_string(): + assert str(CircuitState.OPEN) == "OPEN" + assert CircuitState.OPEN == "OPEN" + + +def test_circuit_info_is_immutable(): + info = CircuitInfo(name="payment", state=CircuitState.OPEN, failure_count=5, opened_at=123) + with pytest.raises(dataclasses.FrozenInstanceError): + info.name = "other" # type: ignore[misc] + + +def test_config_defaults(): + config = CircuitBreakerConfig() + assert config.failure_threshold == 5 + assert config.recovery_timeout == 30 + assert config.success_threshold == 3 + assert config.local_cache_max_age == 5 + assert config.handled_exceptions is None + assert config.ignored_exceptions is None + + +def test_config_rejects_both_exception_lists(): + with pytest.raises(CircuitBreakerConfigError, match="mutually exclusive"): + CircuitBreakerConfig(handled_exceptions=(TimeoutError,), ignored_exceptions=(ValueError,)) + + +@pytest.mark.parametrize("field", ["failure_threshold", "recovery_timeout", "success_threshold"]) +def test_config_rejects_non_positive_thresholds(field): + with pytest.raises(CircuitBreakerConfigError, match="positive integer"): + CircuitBreakerConfig(**{field: 0}) + + +def test_config_allows_zero_cache_age(): + assert CircuitBreakerConfig(local_cache_max_age=0).local_cache_max_age == 0 + + +def test_config_rejects_negative_cache_age(): + with pytest.raises(CircuitBreakerConfigError, match="non-negative"): + CircuitBreakerConfig(local_cache_max_age=-1) + + +def test_counts_as_failure_default_any_exception(): + config = CircuitBreakerConfig() + assert config.counts_as_failure(ValueError()) is True + assert config.counts_as_failure(TimeoutError()) is True + + +def test_counts_as_failure_allowlist(): + config = CircuitBreakerConfig(handled_exceptions=(TimeoutError, ConnectionError)) + assert config.counts_as_failure(TimeoutError()) is True + assert config.counts_as_failure(ValueError()) is False + + +def test_counts_as_failure_denylist(): + config = CircuitBreakerConfig(ignored_exceptions=(ValueError,)) + assert config.counts_as_failure(ValueError()) is False + assert config.counts_as_failure(KeyError()) is True + + +def test_open_error_carries_circuit_info(): + info = CircuitInfo(name="payment", state=CircuitState.OPEN, failure_count=5, opened_at=123) + error = CircuitBreakerOpenError("open", circuit=info) + assert error.circuit is info + + +def test_record_to_circuit_info_strips_internal_fields(): + record = CircuitStateRecord( + name="payment", + state=CircuitState.OPEN, + failure_count=5, + opened_at=123, + half_open_owner="env-abc", + expiry_timestamp=999, + ) + info = record.to_circuit_info() + assert info == CircuitInfo(name="payment", state=CircuitState.OPEN, failure_count=5, opened_at=123) + assert not hasattr(info, "half_open_owner") + assert not hasattr(info, "expiry_timestamp") From 29c5dc8ce60735e45aaaa1c434bb1227d96422a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:54:59 +0100 Subject: [PATCH 17/76] chore(deps-dev): bump boto3-stubs from 1.43.29 to 1.43.36 (#8295) Bumps [boto3-stubs](https://github.com/youtype/mypy_boto3_builder) from 1.43.29 to 1.43.36. - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) --- updated-dependencies: - dependency-name: boto3-stubs dependency-version: 1.43.34 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4c05289136d..c7edf154866 100644 --- a/poetry.lock +++ b/poetry.lock @@ -498,14 +498,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "boto3-stubs" -version = "1.43.29" -description = "Type annotations for boto3 1.43.29 generated with mypy-boto3-builder 8.12.0" +version = "1.43.36" +description = "Type annotations for boto3 1.43.36 generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "boto3_stubs-1.43.29-py3-none-any.whl", hash = "sha256:6c4d1766c3b310d23c107a4bd437e139181c17492a468f62cc2a89dbcd7becf3"}, - {file = "boto3_stubs-1.43.29.tar.gz", hash = "sha256:4d7829eca11f02a652d72b353fbd81a5192ae55d9f7425b81d102a51f01d8e58"}, + {file = "boto3_stubs-1.43.36-py3-none-any.whl", hash = "sha256:e89e48f937710919ef2d36623a8a98c3768568ca6fb9726f7b2369f681ec5745"}, + {file = "boto3_stubs-1.43.36.tar.gz", hash = "sha256:35bdcef0f3e5b6bb1f1f6e61ab813fdde0d739508512450b6ea12509b516cdcb"}, ] [package.dependencies] @@ -530,7 +530,7 @@ account = ["mypy-boto3-account (>=1.43.0,<1.44.0)"] acm = ["mypy-boto3-acm (>=1.43.0,<1.44.0)"] acm-pca = ["mypy-boto3-acm-pca (>=1.43.0,<1.44.0)"] aiops = ["mypy-boto3-aiops (>=1.43.0,<1.44.0)"] -all = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)", "mypy-boto3-account (>=1.43.0,<1.44.0)", "mypy-boto3-acm (>=1.43.0,<1.44.0)", "mypy-boto3-acm-pca (>=1.43.0,<1.44.0)", "mypy-boto3-aiops (>=1.43.0,<1.44.0)", "mypy-boto3-amp (>=1.43.0,<1.44.0)", "mypy-boto3-amplify (>=1.43.0,<1.44.0)", "mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)", "mypy-boto3-amplifyuibuilder (>=1.43.0,<1.44.0)", "mypy-boto3-apigateway (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewaymanagementapi (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewayv2 (>=1.43.0,<1.44.0)", "mypy-boto3-appconfig (>=1.43.0,<1.44.0)", "mypy-boto3-appconfigdata (>=1.43.0,<1.44.0)", "mypy-boto3-appfabric (>=1.43.0,<1.44.0)", "mypy-boto3-appflow (>=1.43.0,<1.44.0)", "mypy-boto3-appintegrations (>=1.43.0,<1.44.0)", "mypy-boto3-application-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-application-insights (>=1.43.0,<1.44.0)", "mypy-boto3-application-signals (>=1.43.0,<1.44.0)", "mypy-boto3-applicationcostprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-appmesh (>=1.43.0,<1.44.0)", "mypy-boto3-apprunner (>=1.43.0,<1.44.0)", "mypy-boto3-appstream (>=1.43.0,<1.44.0)", "mypy-boto3-appsync (>=1.43.0,<1.44.0)", "mypy-boto3-arc-region-switch (>=1.43.0,<1.44.0)", "mypy-boto3-arc-zonal-shift (>=1.43.0,<1.44.0)", "mypy-boto3-artifact (>=1.43.0,<1.44.0)", "mypy-boto3-athena (>=1.43.0,<1.44.0)", "mypy-boto3-auditmanager (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling-plans (>=1.43.0,<1.44.0)", "mypy-boto3-b2bi (>=1.43.0,<1.44.0)", "mypy-boto3-backup (>=1.43.0,<1.44.0)", "mypy-boto3-backup-gateway (>=1.43.0,<1.44.0)", "mypy-boto3-backupsearch (>=1.43.0,<1.44.0)", "mypy-boto3-batch (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-dashboards (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-data-exports (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-pricing-calculator (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-recommended-actions (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore-control (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-billing (>=1.43.0,<1.44.0)", "mypy-boto3-billingconductor (>=1.43.0,<1.44.0)", "mypy-boto3-braket (>=1.43.0,<1.44.0)", "mypy-boto3-budgets (>=1.43.0,<1.44.0)", "mypy-boto3-ce (>=1.43.0,<1.44.0)", "mypy-boto3-chatbot (>=1.43.0,<1.44.0)", "mypy-boto3-chime (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-identity (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-meetings (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-messaging (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-voice (>=1.43.0,<1.44.0)", "mypy-boto3-cleanrooms (>=1.43.0,<1.44.0)", "mypy-boto3-cleanroomsml (>=1.43.0,<1.44.0)", "mypy-boto3-cloud9 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudcontrol (>=1.43.0,<1.44.0)", "mypy-boto3-clouddirectory (>=1.43.0,<1.44.0)", "mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsm (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsmv2 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearch (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)", "mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)", "mypy-boto3-codeartifact (>=1.43.0,<1.44.0)", "mypy-boto3-codebuild (>=1.43.0,<1.44.0)", "mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)", "mypy-boto3-codecommit (>=1.43.0,<1.44.0)", "mypy-boto3-codeconnections (>=1.43.0,<1.44.0)", "mypy-boto3-codedeploy (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-reviewer (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-security (>=1.43.0,<1.44.0)", "mypy-boto3-codeguruprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-codepipeline (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-connections (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-identity (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-idp (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-sync (>=1.43.0,<1.44.0)", "mypy-boto3-comprehend (>=1.43.0,<1.44.0)", "mypy-boto3-comprehendmedical (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer-automation (>=1.43.0,<1.44.0)", "mypy-boto3-config (>=1.43.0,<1.44.0)", "mypy-boto3-connect (>=1.43.0,<1.44.0)", "mypy-boto3-connect-contact-lens (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaigns (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaignsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-connectcases (>=1.43.0,<1.44.0)", "mypy-boto3-connecthealth (>=1.43.0,<1.44.0)", "mypy-boto3-connectparticipant (>=1.43.0,<1.44.0)", "mypy-boto3-controlcatalog (>=1.43.0,<1.44.0)", "mypy-boto3-controltower (>=1.43.0,<1.44.0)", "mypy-boto3-cost-optimization-hub (>=1.43.0,<1.44.0)", "mypy-boto3-cur (>=1.43.0,<1.44.0)", "mypy-boto3-customer-profiles (>=1.43.0,<1.44.0)", "mypy-boto3-databrew (>=1.43.0,<1.44.0)", "mypy-boto3-dataexchange (>=1.43.0,<1.44.0)", "mypy-boto3-datapipeline (>=1.43.0,<1.44.0)", "mypy-boto3-datasync (>=1.43.0,<1.44.0)", "mypy-boto3-datazone (>=1.43.0,<1.44.0)", "mypy-boto3-dax (>=1.43.0,<1.44.0)", "mypy-boto3-deadline (>=1.43.0,<1.44.0)", "mypy-boto3-detective (>=1.43.0,<1.44.0)", "mypy-boto3-devicefarm (>=1.43.0,<1.44.0)", "mypy-boto3-devops-agent (>=1.43.0,<1.44.0)", "mypy-boto3-devops-guru (>=1.43.0,<1.44.0)", "mypy-boto3-directconnect (>=1.43.0,<1.44.0)", "mypy-boto3-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-dlm (>=1.43.0,<1.44.0)", "mypy-boto3-dms (>=1.43.0,<1.44.0)", "mypy-boto3-docdb (>=1.43.0,<1.44.0)", "mypy-boto3-docdb-elastic (>=1.43.0,<1.44.0)", "mypy-boto3-drs (>=1.43.0,<1.44.0)", "mypy-boto3-ds (>=1.43.0,<1.44.0)", "mypy-boto3-ds-data (>=1.43.0,<1.44.0)", "mypy-boto3-dsql (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodbstreams (>=1.43.0,<1.44.0)", "mypy-boto3-ebs (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-ec2-instance-connect (>=1.43.0,<1.44.0)", "mypy-boto3-ecr (>=1.43.0,<1.44.0)", "mypy-boto3-ecr-public (>=1.43.0,<1.44.0)", "mypy-boto3-ecs (>=1.43.0,<1.44.0)", "mypy-boto3-efs (>=1.43.0,<1.44.0)", "mypy-boto3-eks (>=1.43.0,<1.44.0)", "mypy-boto3-eks-auth (>=1.43.0,<1.44.0)", "mypy-boto3-elasticache (>=1.43.0,<1.44.0)", "mypy-boto3-elasticbeanstalk (>=1.43.0,<1.44.0)", "mypy-boto3-elb (>=1.43.0,<1.44.0)", "mypy-boto3-elbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-elementalinference (>=1.43.0,<1.44.0)", "mypy-boto3-emr (>=1.43.0,<1.44.0)", "mypy-boto3-emr-containers (>=1.43.0,<1.44.0)", "mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-entityresolution (>=1.43.0,<1.44.0)", "mypy-boto3-es (>=1.43.0,<1.44.0)", "mypy-boto3-events (>=1.43.0,<1.44.0)", "mypy-boto3-evs (>=1.43.0,<1.44.0)", "mypy-boto3-finspace (>=1.43.0,<1.44.0)", "mypy-boto3-finspace-data (>=1.43.0,<1.44.0)", "mypy-boto3-firehose (>=1.43.0,<1.44.0)", "mypy-boto3-fis (>=1.43.0,<1.44.0)", "mypy-boto3-fms (>=1.43.0,<1.44.0)", "mypy-boto3-forecast (>=1.43.0,<1.44.0)", "mypy-boto3-forecastquery (>=1.43.0,<1.44.0)", "mypy-boto3-frauddetector (>=1.43.0,<1.44.0)", "mypy-boto3-freetier (>=1.43.0,<1.44.0)", "mypy-boto3-fsx (>=1.43.0,<1.44.0)", "mypy-boto3-gamelift (>=1.43.0,<1.44.0)", "mypy-boto3-gameliftstreams (>=1.43.0,<1.44.0)", "mypy-boto3-geo-maps (>=1.43.0,<1.44.0)", "mypy-boto3-geo-places (>=1.43.0,<1.44.0)", "mypy-boto3-geo-routes (>=1.43.0,<1.44.0)", "mypy-boto3-glacier (>=1.43.0,<1.44.0)", "mypy-boto3-globalaccelerator (>=1.43.0,<1.44.0)", "mypy-boto3-glue (>=1.43.0,<1.44.0)", "mypy-boto3-grafana (>=1.43.0,<1.44.0)", "mypy-boto3-greengrass (>=1.43.0,<1.44.0)", "mypy-boto3-greengrassv2 (>=1.43.0,<1.44.0)", "mypy-boto3-groundstation (>=1.43.0,<1.44.0)", "mypy-boto3-guardduty (>=1.43.0,<1.44.0)", "mypy-boto3-health (>=1.43.0,<1.44.0)", "mypy-boto3-healthlake (>=1.43.0,<1.44.0)", "mypy-boto3-iam (>=1.43.0,<1.44.0)", "mypy-boto3-identitystore (>=1.43.0,<1.44.0)", "mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)", "mypy-boto3-importexport (>=1.43.0,<1.44.0)", "mypy-boto3-inspector (>=1.43.0,<1.44.0)", "mypy-boto3-inspector-scan (>=1.43.0,<1.44.0)", "mypy-boto3-inspector2 (>=1.43.0,<1.44.0)", "mypy-boto3-interconnect (>=1.43.0,<1.44.0)", "mypy-boto3-internetmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-invoicing (>=1.43.0,<1.44.0)", "mypy-boto3-iot (>=1.43.0,<1.44.0)", "mypy-boto3-iot-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)", "mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents-data (>=1.43.0,<1.44.0)", "mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)", "mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)", "mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)", "mypy-boto3-iotthingsgraph (>=1.43.0,<1.44.0)", "mypy-boto3-iottwinmaker (>=1.43.0,<1.44.0)", "mypy-boto3-iotwireless (>=1.43.0,<1.44.0)", "mypy-boto3-ivs (>=1.43.0,<1.44.0)", "mypy-boto3-ivs-realtime (>=1.43.0,<1.44.0)", "mypy-boto3-ivschat (>=1.43.0,<1.44.0)", "mypy-boto3-kafka (>=1.43.0,<1.44.0)", "mypy-boto3-kafkaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-kendra (>=1.43.0,<1.44.0)", "mypy-boto3-kendra-ranking (>=1.43.0,<1.44.0)", "mypy-boto3-keyspaces (>=1.43.0,<1.44.0)", "mypy-boto3-keyspacesstreams (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-archived-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-signaling (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)", "mypy-boto3-kms (>=1.43.0,<1.44.0)", "mypy-boto3-lakeformation (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)", "mypy-boto3-lex-models (>=1.43.0,<1.44.0)", "mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-models (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-lightsail (>=1.43.0,<1.44.0)", "mypy-boto3-location (>=1.43.0,<1.44.0)", "mypy-boto3-logs (>=1.43.0,<1.44.0)", "mypy-boto3-lookoutequipment (>=1.43.0,<1.44.0)", "mypy-boto3-m2 (>=1.43.0,<1.44.0)", "mypy-boto3-machinelearning (>=1.43.0,<1.44.0)", "mypy-boto3-macie2 (>=1.43.0,<1.44.0)", "mypy-boto3-mailmanager (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain-query (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-agreement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-catalog (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-deployment (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-entitlement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-reporting (>=1.43.0,<1.44.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconvert (>=1.43.0,<1.44.0)", "mypy-boto3-medialive (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage-vod (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackagev2 (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore-data (>=1.43.0,<1.44.0)", "mypy-boto3-mediatailor (>=1.43.0,<1.44.0)", "mypy-boto3-medical-imaging (>=1.43.0,<1.44.0)", "mypy-boto3-memorydb (>=1.43.0,<1.44.0)", "mypy-boto3-meteringmarketplace (>=1.43.0,<1.44.0)", "mypy-boto3-mgh (>=1.43.0,<1.44.0)", "mypy-boto3-mgn (>=1.43.0,<1.44.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhub-config (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhuborchestrator (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhubstrategy (>=1.43.0,<1.44.0)", "mypy-boto3-mpa (>=1.43.0,<1.44.0)", "mypy-boto3-mq (>=1.43.0,<1.44.0)", "mypy-boto3-mturk (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-neptune (>=1.43.0,<1.44.0)", "mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)", "mypy-boto3-neptunedata (>=1.43.0,<1.44.0)", "mypy-boto3-network-firewall (>=1.43.0,<1.44.0)", "mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-networkmanager (>=1.43.0,<1.44.0)", "mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-notificationscontacts (>=1.43.0,<1.44.0)", "mypy-boto3-nova-act (>=1.43.0,<1.44.0)", "mypy-boto3-oam (>=1.43.0,<1.44.0)", "mypy-boto3-observabilityadmin (>=1.43.0,<1.44.0)", "mypy-boto3-odb (>=1.43.0,<1.44.0)", "mypy-boto3-omics (>=1.43.0,<1.44.0)", "mypy-boto3-opensearch (>=1.43.0,<1.44.0)", "mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)", "mypy-boto3-organizations (>=1.43.0,<1.44.0)", "mypy-boto3-osis (>=1.43.0,<1.44.0)", "mypy-boto3-outposts (>=1.43.0,<1.44.0)", "mypy-boto3-panorama (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-ad (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-scep (>=1.43.0,<1.44.0)", "mypy-boto3-pcs (>=1.43.0,<1.44.0)", "mypy-boto3-personalize (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-events (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-pi (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-email (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)", "mypy-boto3-pipes (>=1.43.0,<1.44.0)", "mypy-boto3-polly (>=1.43.0,<1.44.0)", "mypy-boto3-pricing (>=1.43.0,<1.44.0)", "mypy-boto3-proton (>=1.43.0,<1.44.0)", "mypy-boto3-qapps (>=1.43.0,<1.44.0)", "mypy-boto3-qbusiness (>=1.43.0,<1.44.0)", "mypy-boto3-qconnect (>=1.43.0,<1.44.0)", "mypy-boto3-quicksight (>=1.43.0,<1.44.0)", "mypy-boto3-ram (>=1.43.0,<1.44.0)", "mypy-boto3-rbin (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-rds-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-rekognition (>=1.43.0,<1.44.0)", "mypy-boto3-repostspace (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehub (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehubv2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-explorer-2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-groups (>=1.43.0,<1.44.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.43.0,<1.44.0)", "mypy-boto3-rolesanywhere (>=1.43.0,<1.44.0)", "mypy-boto3-route53 (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-cluster (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-control-config (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-readiness (>=1.43.0,<1.44.0)", "mypy-boto3-route53domains (>=1.43.0,<1.44.0)", "mypy-boto3-route53globalresolver (>=1.43.0,<1.44.0)", "mypy-boto3-route53profiles (>=1.43.0,<1.44.0)", "mypy-boto3-route53resolver (>=1.43.0,<1.44.0)", "mypy-boto3-rtbfabric (>=1.43.0,<1.44.0)", "mypy-boto3-rum (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-s3control (>=1.43.0,<1.44.0)", "mypy-boto3-s3files (>=1.43.0,<1.44.0)", "mypy-boto3-s3outposts (>=1.43.0,<1.44.0)", "mypy-boto3-s3tables (>=1.43.0,<1.44.0)", "mypy-boto3-s3vectors (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-edge (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-geospatial (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-metrics (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemakerjobruntime (>=1.43.0,<1.44.0)", "mypy-boto3-savingsplans (>=1.43.0,<1.44.0)", "mypy-boto3-scheduler (>=1.43.0,<1.44.0)", "mypy-boto3-schemas (>=1.43.0,<1.44.0)", "mypy-boto3-sdb (>=1.43.0,<1.44.0)", "mypy-boto3-secretsmanager (>=1.43.0,<1.44.0)", "mypy-boto3-security-ir (>=1.43.0,<1.44.0)", "mypy-boto3-securityagent (>=1.43.0,<1.44.0)", "mypy-boto3-securityhub (>=1.43.0,<1.44.0)", "mypy-boto3-securitylake (>=1.43.0,<1.44.0)", "mypy-boto3-serverlessrepo (>=1.43.0,<1.44.0)", "mypy-boto3-service-quotas (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog-appregistry (>=1.43.0,<1.44.0)", "mypy-boto3-servicediscovery (>=1.43.0,<1.44.0)", "mypy-boto3-ses (>=1.43.0,<1.44.0)", "mypy-boto3-sesv2 (>=1.43.0,<1.44.0)", "mypy-boto3-shield (>=1.43.0,<1.44.0)", "mypy-boto3-signer (>=1.43.0,<1.44.0)", "mypy-boto3-signer-data (>=1.43.0,<1.44.0)", "mypy-boto3-signin (>=1.43.0,<1.44.0)", "mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-simspaceweaver (>=1.43.0,<1.44.0)", "mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)", "mypy-boto3-snowball (>=1.43.0,<1.44.0)", "mypy-boto3-sns (>=1.43.0,<1.44.0)", "mypy-boto3-socialmessaging (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)", "mypy-boto3-ssm (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-contacts (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-guiconnect (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-incidents (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-quicksetup (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-sap (>=1.43.0,<1.44.0)", "mypy-boto3-sso (>=1.43.0,<1.44.0)", "mypy-boto3-sso-admin (>=1.43.0,<1.44.0)", "mypy-boto3-sso-oidc (>=1.43.0,<1.44.0)", "mypy-boto3-stepfunctions (>=1.43.0,<1.44.0)", "mypy-boto3-storagegateway (>=1.43.0,<1.44.0)", "mypy-boto3-sts (>=1.43.0,<1.44.0)", "mypy-boto3-supplychain (>=1.43.0,<1.44.0)", "mypy-boto3-support (>=1.43.0,<1.44.0)", "mypy-boto3-support-app (>=1.43.0,<1.44.0)", "mypy-boto3-sustainability (>=1.43.0,<1.44.0)", "mypy-boto3-swf (>=1.43.0,<1.44.0)", "mypy-boto3-synthetics (>=1.43.0,<1.44.0)", "mypy-boto3-taxsettings (>=1.43.0,<1.44.0)", "mypy-boto3-textract (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-influxdb (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-query (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-write (>=1.43.0,<1.44.0)", "mypy-boto3-tnb (>=1.43.0,<1.44.0)", "mypy-boto3-transcribe (>=1.43.0,<1.44.0)", "mypy-boto3-transfer (>=1.43.0,<1.44.0)", "mypy-boto3-translate (>=1.43.0,<1.44.0)", "mypy-boto3-trustedadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-uxc (>=1.43.0,<1.44.0)", "mypy-boto3-verifiedpermissions (>=1.43.0,<1.44.0)", "mypy-boto3-voice-id (>=1.43.0,<1.44.0)", "mypy-boto3-vpc-lattice (>=1.43.0,<1.44.0)", "mypy-boto3-waf (>=1.43.0,<1.44.0)", "mypy-boto3-waf-regional (>=1.43.0,<1.44.0)", "mypy-boto3-wafv2 (>=1.43.0,<1.44.0)", "mypy-boto3-wellarchitected (>=1.43.0,<1.44.0)", "mypy-boto3-wickr (>=1.43.0,<1.44.0)", "mypy-boto3-wisdom (>=1.43.0,<1.44.0)", "mypy-boto3-workdocs (>=1.43.0,<1.44.0)", "mypy-boto3-workmail (>=1.43.0,<1.44.0)", "mypy-boto3-workmailmessageflow (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-instances (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-thin-client (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-web (>=1.43.0,<1.44.0)", "mypy-boto3-xray (>=1.43.0,<1.44.0)"] +all = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)", "mypy-boto3-account (>=1.43.0,<1.44.0)", "mypy-boto3-acm (>=1.43.0,<1.44.0)", "mypy-boto3-acm-pca (>=1.43.0,<1.44.0)", "mypy-boto3-aiops (>=1.43.0,<1.44.0)", "mypy-boto3-amp (>=1.43.0,<1.44.0)", "mypy-boto3-amplify (>=1.43.0,<1.44.0)", "mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)", "mypy-boto3-amplifyuibuilder (>=1.43.0,<1.44.0)", "mypy-boto3-apigateway (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewaymanagementapi (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewayv2 (>=1.43.0,<1.44.0)", "mypy-boto3-appconfig (>=1.43.0,<1.44.0)", "mypy-boto3-appconfigdata (>=1.43.0,<1.44.0)", "mypy-boto3-appfabric (>=1.43.0,<1.44.0)", "mypy-boto3-appflow (>=1.43.0,<1.44.0)", "mypy-boto3-appintegrations (>=1.43.0,<1.44.0)", "mypy-boto3-application-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-application-insights (>=1.43.0,<1.44.0)", "mypy-boto3-application-signals (>=1.43.0,<1.44.0)", "mypy-boto3-applicationcostprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-appmesh (>=1.43.0,<1.44.0)", "mypy-boto3-apprunner (>=1.43.0,<1.44.0)", "mypy-boto3-appstream (>=1.43.0,<1.44.0)", "mypy-boto3-appsync (>=1.43.0,<1.44.0)", "mypy-boto3-arc-region-switch (>=1.43.0,<1.44.0)", "mypy-boto3-arc-zonal-shift (>=1.43.0,<1.44.0)", "mypy-boto3-artifact (>=1.43.0,<1.44.0)", "mypy-boto3-athena (>=1.43.0,<1.44.0)", "mypy-boto3-auditmanager (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling-plans (>=1.43.0,<1.44.0)", "mypy-boto3-b2bi (>=1.43.0,<1.44.0)", "mypy-boto3-backup (>=1.43.0,<1.44.0)", "mypy-boto3-backup-gateway (>=1.43.0,<1.44.0)", "mypy-boto3-backupsearch (>=1.43.0,<1.44.0)", "mypy-boto3-batch (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-dashboards (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-data-exports (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-pricing-calculator (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-recommended-actions (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore-control (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-billing (>=1.43.0,<1.44.0)", "mypy-boto3-billingconductor (>=1.43.0,<1.44.0)", "mypy-boto3-braket (>=1.43.0,<1.44.0)", "mypy-boto3-budgets (>=1.43.0,<1.44.0)", "mypy-boto3-ce (>=1.43.0,<1.44.0)", "mypy-boto3-chatbot (>=1.43.0,<1.44.0)", "mypy-boto3-chime (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-identity (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-meetings (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-messaging (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-voice (>=1.43.0,<1.44.0)", "mypy-boto3-cleanrooms (>=1.43.0,<1.44.0)", "mypy-boto3-cleanroomsml (>=1.43.0,<1.44.0)", "mypy-boto3-cloud9 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudcontrol (>=1.43.0,<1.44.0)", "mypy-boto3-clouddirectory (>=1.43.0,<1.44.0)", "mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsm (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsmv2 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearch (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)", "mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)", "mypy-boto3-codeartifact (>=1.43.0,<1.44.0)", "mypy-boto3-codebuild (>=1.43.0,<1.44.0)", "mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)", "mypy-boto3-codecommit (>=1.43.0,<1.44.0)", "mypy-boto3-codeconnections (>=1.43.0,<1.44.0)", "mypy-boto3-codedeploy (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-reviewer (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-security (>=1.43.0,<1.44.0)", "mypy-boto3-codeguruprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-codepipeline (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-connections (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-identity (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-idp (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-sync (>=1.43.0,<1.44.0)", "mypy-boto3-comprehend (>=1.43.0,<1.44.0)", "mypy-boto3-comprehendmedical (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer-automation (>=1.43.0,<1.44.0)", "mypy-boto3-config (>=1.43.0,<1.44.0)", "mypy-boto3-connect (>=1.43.0,<1.44.0)", "mypy-boto3-connect-contact-lens (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaigns (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaignsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-connectcases (>=1.43.0,<1.44.0)", "mypy-boto3-connecthealth (>=1.43.0,<1.44.0)", "mypy-boto3-connectparticipant (>=1.43.0,<1.44.0)", "mypy-boto3-controlcatalog (>=1.43.0,<1.44.0)", "mypy-boto3-controltower (>=1.43.0,<1.44.0)", "mypy-boto3-cost-optimization-hub (>=1.43.0,<1.44.0)", "mypy-boto3-cur (>=1.43.0,<1.44.0)", "mypy-boto3-customer-profiles (>=1.43.0,<1.44.0)", "mypy-boto3-databrew (>=1.43.0,<1.44.0)", "mypy-boto3-dataexchange (>=1.43.0,<1.44.0)", "mypy-boto3-datapipeline (>=1.43.0,<1.44.0)", "mypy-boto3-datasync (>=1.43.0,<1.44.0)", "mypy-boto3-datazone (>=1.43.0,<1.44.0)", "mypy-boto3-dax (>=1.43.0,<1.44.0)", "mypy-boto3-deadline (>=1.43.0,<1.44.0)", "mypy-boto3-detective (>=1.43.0,<1.44.0)", "mypy-boto3-devicefarm (>=1.43.0,<1.44.0)", "mypy-boto3-devops-agent (>=1.43.0,<1.44.0)", "mypy-boto3-devops-guru (>=1.43.0,<1.44.0)", "mypy-boto3-directconnect (>=1.43.0,<1.44.0)", "mypy-boto3-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-dlm (>=1.43.0,<1.44.0)", "mypy-boto3-dms (>=1.43.0,<1.44.0)", "mypy-boto3-docdb (>=1.43.0,<1.44.0)", "mypy-boto3-docdb-elastic (>=1.43.0,<1.44.0)", "mypy-boto3-drs (>=1.43.0,<1.44.0)", "mypy-boto3-ds (>=1.43.0,<1.44.0)", "mypy-boto3-ds-data (>=1.43.0,<1.44.0)", "mypy-boto3-dsql (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodbstreams (>=1.43.0,<1.44.0)", "mypy-boto3-ebs (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-ec2-instance-connect (>=1.43.0,<1.44.0)", "mypy-boto3-ecr (>=1.43.0,<1.44.0)", "mypy-boto3-ecr-public (>=1.43.0,<1.44.0)", "mypy-boto3-ecs (>=1.43.0,<1.44.0)", "mypy-boto3-efs (>=1.43.0,<1.44.0)", "mypy-boto3-eks (>=1.43.0,<1.44.0)", "mypy-boto3-eks-auth (>=1.43.0,<1.44.0)", "mypy-boto3-elasticache (>=1.43.0,<1.44.0)", "mypy-boto3-elasticbeanstalk (>=1.43.0,<1.44.0)", "mypy-boto3-elb (>=1.43.0,<1.44.0)", "mypy-boto3-elbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-elementalinference (>=1.43.0,<1.44.0)", "mypy-boto3-emr (>=1.43.0,<1.44.0)", "mypy-boto3-emr-containers (>=1.43.0,<1.44.0)", "mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-entityresolution (>=1.43.0,<1.44.0)", "mypy-boto3-es (>=1.43.0,<1.44.0)", "mypy-boto3-events (>=1.43.0,<1.44.0)", "mypy-boto3-evs (>=1.43.0,<1.44.0)", "mypy-boto3-finspace (>=1.43.0,<1.44.0)", "mypy-boto3-finspace-data (>=1.43.0,<1.44.0)", "mypy-boto3-firehose (>=1.43.0,<1.44.0)", "mypy-boto3-fis (>=1.43.0,<1.44.0)", "mypy-boto3-fms (>=1.43.0,<1.44.0)", "mypy-boto3-forecast (>=1.43.0,<1.44.0)", "mypy-boto3-forecastquery (>=1.43.0,<1.44.0)", "mypy-boto3-frauddetector (>=1.43.0,<1.44.0)", "mypy-boto3-freetier (>=1.43.0,<1.44.0)", "mypy-boto3-fsx (>=1.43.0,<1.44.0)", "mypy-boto3-gamelift (>=1.43.0,<1.44.0)", "mypy-boto3-gameliftstreams (>=1.43.0,<1.44.0)", "mypy-boto3-geo-maps (>=1.43.0,<1.44.0)", "mypy-boto3-geo-places (>=1.43.0,<1.44.0)", "mypy-boto3-geo-routes (>=1.43.0,<1.44.0)", "mypy-boto3-glacier (>=1.43.0,<1.44.0)", "mypy-boto3-globalaccelerator (>=1.43.0,<1.44.0)", "mypy-boto3-glue (>=1.43.0,<1.44.0)", "mypy-boto3-grafana (>=1.43.0,<1.44.0)", "mypy-boto3-greengrass (>=1.43.0,<1.44.0)", "mypy-boto3-greengrassv2 (>=1.43.0,<1.44.0)", "mypy-boto3-groundstation (>=1.43.0,<1.44.0)", "mypy-boto3-guardduty (>=1.43.0,<1.44.0)", "mypy-boto3-health (>=1.43.0,<1.44.0)", "mypy-boto3-healthlake (>=1.43.0,<1.44.0)", "mypy-boto3-iam (>=1.43.0,<1.44.0)", "mypy-boto3-identitystore (>=1.43.0,<1.44.0)", "mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)", "mypy-boto3-importexport (>=1.43.0,<1.44.0)", "mypy-boto3-inspector (>=1.43.0,<1.44.0)", "mypy-boto3-inspector-scan (>=1.43.0,<1.44.0)", "mypy-boto3-inspector2 (>=1.43.0,<1.44.0)", "mypy-boto3-interconnect (>=1.43.0,<1.44.0)", "mypy-boto3-internetmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-invoicing (>=1.43.0,<1.44.0)", "mypy-boto3-iot (>=1.43.0,<1.44.0)", "mypy-boto3-iot-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)", "mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents-data (>=1.43.0,<1.44.0)", "mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)", "mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)", "mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)", "mypy-boto3-iotthingsgraph (>=1.43.0,<1.44.0)", "mypy-boto3-iottwinmaker (>=1.43.0,<1.44.0)", "mypy-boto3-iotwireless (>=1.43.0,<1.44.0)", "mypy-boto3-ivs (>=1.43.0,<1.44.0)", "mypy-boto3-ivs-realtime (>=1.43.0,<1.44.0)", "mypy-boto3-ivschat (>=1.43.0,<1.44.0)", "mypy-boto3-kafka (>=1.43.0,<1.44.0)", "mypy-boto3-kafkaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-kendra (>=1.43.0,<1.44.0)", "mypy-boto3-kendra-ranking (>=1.43.0,<1.44.0)", "mypy-boto3-keyspaces (>=1.43.0,<1.44.0)", "mypy-boto3-keyspacesstreams (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-archived-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-signaling (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)", "mypy-boto3-kms (>=1.43.0,<1.44.0)", "mypy-boto3-lakeformation (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-lambda-core (>=1.43.0,<1.44.0)", "mypy-boto3-lambda-microvms (>=1.43.0,<1.44.0)", "mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)", "mypy-boto3-lex-models (>=1.43.0,<1.44.0)", "mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-models (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-lightsail (>=1.43.0,<1.44.0)", "mypy-boto3-location (>=1.43.0,<1.44.0)", "mypy-boto3-logs (>=1.43.0,<1.44.0)", "mypy-boto3-lookoutequipment (>=1.43.0,<1.44.0)", "mypy-boto3-m2 (>=1.43.0,<1.44.0)", "mypy-boto3-machinelearning (>=1.43.0,<1.44.0)", "mypy-boto3-macie2 (>=1.43.0,<1.44.0)", "mypy-boto3-mailmanager (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain-query (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-agreement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-catalog (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-deployment (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-entitlement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-reporting (>=1.43.0,<1.44.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconvert (>=1.43.0,<1.44.0)", "mypy-boto3-medialive (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage-vod (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackagev2 (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore-data (>=1.43.0,<1.44.0)", "mypy-boto3-mediatailor (>=1.43.0,<1.44.0)", "mypy-boto3-medical-imaging (>=1.43.0,<1.44.0)", "mypy-boto3-memorydb (>=1.43.0,<1.44.0)", "mypy-boto3-meteringmarketplace (>=1.43.0,<1.44.0)", "mypy-boto3-mgh (>=1.43.0,<1.44.0)", "mypy-boto3-mgn (>=1.43.0,<1.44.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhub-config (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhuborchestrator (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhubstrategy (>=1.43.0,<1.44.0)", "mypy-boto3-mpa (>=1.43.0,<1.44.0)", "mypy-boto3-mq (>=1.43.0,<1.44.0)", "mypy-boto3-mturk (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-neptune (>=1.43.0,<1.44.0)", "mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)", "mypy-boto3-neptunedata (>=1.43.0,<1.44.0)", "mypy-boto3-network-firewall (>=1.43.0,<1.44.0)", "mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-networkmanager (>=1.43.0,<1.44.0)", "mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-notificationscontacts (>=1.43.0,<1.44.0)", "mypy-boto3-nova-act (>=1.43.0,<1.44.0)", "mypy-boto3-oam (>=1.43.0,<1.44.0)", "mypy-boto3-observabilityadmin (>=1.43.0,<1.44.0)", "mypy-boto3-odb (>=1.43.0,<1.44.0)", "mypy-boto3-omics (>=1.43.0,<1.44.0)", "mypy-boto3-opensearch (>=1.43.0,<1.44.0)", "mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)", "mypy-boto3-organizations (>=1.43.0,<1.44.0)", "mypy-boto3-osis (>=1.43.0,<1.44.0)", "mypy-boto3-outposts (>=1.43.0,<1.44.0)", "mypy-boto3-panorama (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-ad (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-scep (>=1.43.0,<1.44.0)", "mypy-boto3-pcs (>=1.43.0,<1.44.0)", "mypy-boto3-personalize (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-events (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-pi (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-email (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)", "mypy-boto3-pipes (>=1.43.0,<1.44.0)", "mypy-boto3-polly (>=1.43.0,<1.44.0)", "mypy-boto3-pricing (>=1.43.0,<1.44.0)", "mypy-boto3-proton (>=1.43.0,<1.44.0)", "mypy-boto3-qapps (>=1.43.0,<1.44.0)", "mypy-boto3-qbusiness (>=1.43.0,<1.44.0)", "mypy-boto3-qconnect (>=1.43.0,<1.44.0)", "mypy-boto3-quicksight (>=1.43.0,<1.44.0)", "mypy-boto3-ram (>=1.43.0,<1.44.0)", "mypy-boto3-rbin (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-rds-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-rekognition (>=1.43.0,<1.44.0)", "mypy-boto3-repostspace (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehub (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehubv2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-explorer-2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-groups (>=1.43.0,<1.44.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.43.0,<1.44.0)", "mypy-boto3-rolesanywhere (>=1.43.0,<1.44.0)", "mypy-boto3-route53 (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-cluster (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-control-config (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-readiness (>=1.43.0,<1.44.0)", "mypy-boto3-route53domains (>=1.43.0,<1.44.0)", "mypy-boto3-route53globalresolver (>=1.43.0,<1.44.0)", "mypy-boto3-route53profiles (>=1.43.0,<1.44.0)", "mypy-boto3-route53resolver (>=1.43.0,<1.44.0)", "mypy-boto3-rtbfabric (>=1.43.0,<1.44.0)", "mypy-boto3-rum (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-s3control (>=1.43.0,<1.44.0)", "mypy-boto3-s3files (>=1.43.0,<1.44.0)", "mypy-boto3-s3outposts (>=1.43.0,<1.44.0)", "mypy-boto3-s3tables (>=1.43.0,<1.44.0)", "mypy-boto3-s3vectors (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-edge (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-geospatial (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-metrics (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemakerjobruntime (>=1.43.0,<1.44.0)", "mypy-boto3-savingsplans (>=1.43.0,<1.44.0)", "mypy-boto3-scheduler (>=1.43.0,<1.44.0)", "mypy-boto3-schemas (>=1.43.0,<1.44.0)", "mypy-boto3-sdb (>=1.43.0,<1.44.0)", "mypy-boto3-secretsmanager (>=1.43.0,<1.44.0)", "mypy-boto3-security-ir (>=1.43.0,<1.44.0)", "mypy-boto3-securityagent (>=1.43.0,<1.44.0)", "mypy-boto3-securityhub (>=1.43.0,<1.44.0)", "mypy-boto3-securitylake (>=1.43.0,<1.44.0)", "mypy-boto3-serverlessrepo (>=1.43.0,<1.44.0)", "mypy-boto3-service-quotas (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog-appregistry (>=1.43.0,<1.44.0)", "mypy-boto3-servicediscovery (>=1.43.0,<1.44.0)", "mypy-boto3-ses (>=1.43.0,<1.44.0)", "mypy-boto3-sesv2 (>=1.43.0,<1.44.0)", "mypy-boto3-shield (>=1.43.0,<1.44.0)", "mypy-boto3-signer (>=1.43.0,<1.44.0)", "mypy-boto3-signer-data (>=1.43.0,<1.44.0)", "mypy-boto3-signin (>=1.43.0,<1.44.0)", "mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-simspaceweaver (>=1.43.0,<1.44.0)", "mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)", "mypy-boto3-snowball (>=1.43.0,<1.44.0)", "mypy-boto3-sns (>=1.43.0,<1.44.0)", "mypy-boto3-socialmessaging (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)", "mypy-boto3-ssm (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-contacts (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-guiconnect (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-incidents (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-quicksetup (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-sap (>=1.43.0,<1.44.0)", "mypy-boto3-sso (>=1.43.0,<1.44.0)", "mypy-boto3-sso-admin (>=1.43.0,<1.44.0)", "mypy-boto3-sso-oidc (>=1.43.0,<1.44.0)", "mypy-boto3-stepfunctions (>=1.43.0,<1.44.0)", "mypy-boto3-storagegateway (>=1.43.0,<1.44.0)", "mypy-boto3-sts (>=1.43.0,<1.44.0)", "mypy-boto3-supplychain (>=1.43.0,<1.44.0)", "mypy-boto3-support (>=1.43.0,<1.44.0)", "mypy-boto3-support-app (>=1.43.0,<1.44.0)", "mypy-boto3-sustainability (>=1.43.0,<1.44.0)", "mypy-boto3-swf (>=1.43.0,<1.44.0)", "mypy-boto3-synthetics (>=1.43.0,<1.44.0)", "mypy-boto3-taxsettings (>=1.43.0,<1.44.0)", "mypy-boto3-textract (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-influxdb (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-query (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-write (>=1.43.0,<1.44.0)", "mypy-boto3-tnb (>=1.43.0,<1.44.0)", "mypy-boto3-transcribe (>=1.43.0,<1.44.0)", "mypy-boto3-transfer (>=1.43.0,<1.44.0)", "mypy-boto3-translate (>=1.43.0,<1.44.0)", "mypy-boto3-trustedadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-uxc (>=1.43.0,<1.44.0)", "mypy-boto3-verifiedpermissions (>=1.43.0,<1.44.0)", "mypy-boto3-voice-id (>=1.43.0,<1.44.0)", "mypy-boto3-vpc-lattice (>=1.43.0,<1.44.0)", "mypy-boto3-waf (>=1.43.0,<1.44.0)", "mypy-boto3-waf-regional (>=1.43.0,<1.44.0)", "mypy-boto3-wafv2 (>=1.43.0,<1.44.0)", "mypy-boto3-wellarchitected (>=1.43.0,<1.44.0)", "mypy-boto3-wickr (>=1.43.0,<1.44.0)", "mypy-boto3-wisdom (>=1.43.0,<1.44.0)", "mypy-boto3-workdocs (>=1.43.0,<1.44.0)", "mypy-boto3-workmail (>=1.43.0,<1.44.0)", "mypy-boto3-workmailmessageflow (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-instances (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-thin-client (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-web (>=1.43.0,<1.44.0)", "mypy-boto3-xray (>=1.43.0,<1.44.0)"] amp = ["mypy-boto3-amp (>=1.43.0,<1.44.0)"] amplify = ["mypy-boto3-amplify (>=1.43.0,<1.44.0)"] amplifybackend = ["mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)"] @@ -577,7 +577,7 @@ bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime ( bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)"] billing = ["mypy-boto3-billing (>=1.43.0,<1.44.0)"] billingconductor = ["mypy-boto3-billingconductor (>=1.43.0,<1.44.0)"] -boto3 = ["boto3 (==1.43.29)"] +boto3 = ["boto3 (==1.43.36)"] braket = ["mypy-boto3-braket (>=1.43.0,<1.44.0)"] budgets = ["mypy-boto3-budgets (>=1.43.0,<1.44.0)"] ce = ["mypy-boto3-ce (>=1.43.0,<1.44.0)"] @@ -749,6 +749,8 @@ kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)"] kms = ["mypy-boto3-kms (>=1.43.0,<1.44.0)"] lakeformation = ["mypy-boto3-lakeformation (>=1.43.0,<1.44.0)"] lambda = ["mypy-boto3-lambda (>=1.43.0,<1.44.0)"] +lambda-core = ["mypy-boto3-lambda-core (>=1.43.0,<1.44.0)"] +lambda-microvms = ["mypy-boto3-lambda-microvms (>=1.43.0,<1.44.0)"] launch-wizard = ["mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)"] lex-models = ["mypy-boto3-lex-models (>=1.43.0,<1.44.0)"] lex-runtime = ["mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)"] From a9cffe442151715656aeb58643e597ed422b41d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:56:19 +0100 Subject: [PATCH 18/76] chore(deps-dev): bump sentry-sdk from 2.62.0 to 2.63.0 (#8296) Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.62.0 to 2.63.0. - [Release notes](https://github.com/getsentry/sentry-python/releases) - [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-python/compare/2.62.0...2.63.0) --- updated-dependencies: - dependency-name: sentry-sdk dependency-version: 2.63.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index c7edf154866..faed7ca3831 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4385,14 +4385,14 @@ pathspec = ">=0.10.1" [[package]] name = "sentry-sdk" -version = "2.62.0" +version = "2.63.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "sentry_sdk-2.62.0-py3-none-any.whl", hash = "sha256:27f61d13a86c3c1648dec666dd5a64f79772dd6a84b446f11866601ecab24f6f"}, - {file = "sentry_sdk-2.62.0.tar.gz", hash = "sha256:3c870b9f50d9fd15b58c817dbde1c7cfaa9fe3f05df0a4c6edd5571cb82f5491"}, + {file = "sentry_sdk-2.63.0-py3-none-any.whl", hash = "sha256:3a9b5ddd403f79eb73bd670f75f04485819db53d28f76ced7bc09041cb0dfd6a"}, + {file = "sentry_sdk-2.63.0.tar.gz", hash = "sha256:2a1502bf864769275dbc8c2c9fc7a0f7f5e18358180b615d262d13a31ffba216"}, ] [package.dependencies] From 6c203ea81aec0842aa3bf49f52eb1383540fb0bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:58:35 +0100 Subject: [PATCH 19/76] chore(deps): bump redis from 7.4.0 to 8.0.1 (#8297) Bumps [redis](https://github.com/redis/redis-py) from 7.4.0 to 8.0.1. - [Release notes](https://github.com/redis/redis-py/releases) - [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES) - [Commits](https://github.com/redis/redis-py/compare/v7.4.0...v8.0.1) --- updated-dependencies: - dependency-name: redis dependency-version: 8.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index faed7ca3831..551423d06c1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3976,14 +3976,14 @@ toml = ["tomli (>=2.0.1)"] [[package]] name = "redis" -version = "7.4.0" +version = "8.0.1" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "redis-7.4.0-py3-none-any.whl", hash = "sha256:a9c74a5c893a5ef8455a5adb793a31bb70feb821c86eccb62eebef5a19c429ec"}, - {file = "redis-7.4.0.tar.gz", hash = "sha256:64a6ea7bf567ad43c964d2c30d82853f8df927c5c9017766c55a1d1ed95d18ad"}, + {file = "redis-8.0.1-py3-none-any.whl", hash = "sha256:47daa35a058c23468d6437f17a8c76882cb316b838ef763036af99b96cedd743"}, + {file = "redis-8.0.1.tar.gz", hash = "sha256:afc5a7a2f5a084f5b1880dec548dd45be17db7e43c82a30d84f952aefb05cfb0"}, ] markers = {main = "extra == \"redis\""} @@ -3993,7 +3993,7 @@ async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\ [package.extras] circuit-breaker = ["pybreaker (>=1.4.0)"] hiredis = ["hiredis (>=3.2.0)"] -jwt = ["pyjwt (>=2.9.0)"] +jwt = ["pyjwt (>=2.13.0)"] ocsp = ["cryptography (>=36.0.1)", "pyopenssl (>=20.0.1)", "requests (>=2.31.0)"] otel = ["opentelemetry-api (>=1.39.1)", "opentelemetry-exporter-otlp-proto-http (>=1.39.1)", "opentelemetry-sdk (>=1.39.1)"] xxhash = ["xxhash (>=3.6.0,<3.7.0)"] @@ -5220,4 +5220,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "9f01df9bb0aee394e4821f5d66548c584c22fbbc3d12af9bc3cca7e32a835537" +content-hash = "4487e5115c6fe8c9475bd1c913532b6ece5aa69d3863042af67fd0ef3f1a9980" diff --git a/pyproject.toml b/pyproject.toml index c7360276ba9..8877f9371c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ fastjsonschema = { version = "^2.14.5", optional = true } pydantic = { version = "^2.4.0", optional = true } pydantic-settings = {version = "^2.6.1", optional = true} boto3 = { version = "^1.34.32", optional = true } -redis = { version = ">=4.4,<8.0", optional = true } +redis = { version = ">=4.4,<9.0", optional = true } valkey-glide = { version = ">=1.3.5,<3.0", optional = true } aws-encryption-sdk = { version = ">=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4,<5.0.0", optional = true } jsonpath-ng = { version = "^1.6.0", optional = true } From 2c6b5e0f8cd62d453f827a78d77f8c286afce9af Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 29 Jun 2026 11:11:09 +0100 Subject: [PATCH 20/76] feat(event_handler): support any Pydantic Field annotation in parameter (#8305) feat(event_handler): support any Pydantic Field annotation in parameter validation --- .../event_handler/openapi/params.py | 88 ++++++++++--------- .../test_openapi_validation_middleware.py | 73 ++++++++++++++- 2 files changed, 117 insertions(+), 44 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/params.py b/aws_lambda_powertools/event_handler/openapi/params.py index 468e2253b39..29c0b2abcdb 100644 --- a/aws_lambda_powertools/event_handler/openapi/params.py +++ b/aws_lambda_powertools/event_handler/openapi/params.py @@ -953,54 +953,52 @@ def get_field_info_response_type(annotation, value) -> tuple[FieldInfo | None, A return get_field_info_and_type_annotation(inner_type, value, False, True) -def _has_discriminator(field_info: FieldInfo) -> bool: - """Check if a FieldInfo has a discriminator.""" - return hasattr(field_info, "discriminator") and field_info.discriminator is not None - - -def _handle_discriminator_with_param( +def _split_location_marker_and_field( annotations: list[FieldInfo], - annotation: Any, -) -> tuple[FieldInfo | None, Any, bool]: +) -> tuple[FieldInfo, FieldInfo]: """ - Handle the special case of Field(discriminator) + Body() combination. + Split a pair of FieldInfo into the Powertools location marker and the plain Pydantic Field. + + A parameter like ``Annotated[str, Field(gt=0), Query()]`` flattens to two FieldInfo: the + location marker (``Path``/``Query``/``Header``/``Body``, a ``Param`` or ``Body`` subclass) and + a plain Pydantic ``Field`` carrying constraints. We keep them apart so the location marker + drives where the value comes from, while the ``Field``'s constraints/metadata still apply. Returns: - tuple of (powertools_annotation, type_annotation, has_discriminator_with_body) + tuple of (location_marker, plain_field) """ - field_obj = None - body_obj = None + location_marker: FieldInfo | None = None + plain_field: FieldInfo | None = None for ann in annotations: - if isinstance(ann, Body): - body_obj = ann - elif _has_discriminator(ann): - field_obj = ann + if isinstance(ann, (Param, Body)): + location_marker = ann + else: + plain_field = ann - if field_obj and body_obj: - # Use Body as the primary annotation, preserve full annotation for validation - return body_obj, annotation, True + if location_marker is None or plain_field is None: + raise AssertionError("Only one FieldInfo can be used per parameter") - raise AssertionError("Only one FieldInfo can be used per parameter") + return location_marker, plain_field def _create_field_info( powertools_annotation: FieldInfo, type_annotation: Any, - has_discriminator_with_body: bool, + preserve_full_annotation: bool, ) -> FieldInfo: """Create or copy FieldInfo based on the annotation type.""" - field_info: FieldInfo - if has_discriminator_with_body: - # For discriminator + Body case, create a new Body instance directly - field_info = Body() + # Copy field_info because we mutate field_info.default later. + field_info = copy_field_info( + field_info=powertools_annotation, + annotation=type_annotation, + ) + if preserve_full_annotation: + # The location marker is paired with a plain Field (constraints or discriminator). + # copy_field_info strips the Pydantic Field out of the metadata, so re-attach the full + # Annotated type here, that's what makes the Field's metadata flow into the TypeAdapter + # that ModelField builds for validation. field_info.annotation = type_annotation - else: - # Copy field_info because we mutate field_info.default later - field_info = copy_field_info( - field_info=powertools_annotation, - annotation=type_annotation, - ) return field_info @@ -1043,13 +1041,16 @@ def get_field_info_annotated_type(annotation, value, is_path_param: bool) -> tup # Determine which annotation to use powertools_annotation: FieldInfo | None = None - has_discriminator_with_param = False + # When a plain Pydantic Field is paired with a location marker (e.g. Field(gt=0) + Query), + # we keep the full Annotated type as the annotation so the Field's metadata still validates. + preserve_full_annotation = False if len(powertools_annotations) == 2: - powertools_annotation, type_annotation, has_discriminator_with_param = _handle_discriminator_with_param( - powertools_annotations, - annotation, - ) + # A location marker (Path/Query/Header/Body) plus a plain Pydantic Field carrying + # constraints, a discriminator, or any other Field setting. The marker says where the + # value comes from; the Field says how to validate it. + powertools_annotation, _ = _split_location_marker_and_field(powertools_annotations) + preserve_full_annotation = True elif len(powertools_annotations) > 1: raise AssertionError("Only one FieldInfo can be used per parameter") else: @@ -1057,18 +1058,19 @@ def get_field_info_annotated_type(annotation, value, is_path_param: bool) -> tup # Reconstruct type_annotation with non-FieldInfo metadata if present # This ensures constraints like Interval are preserved - if other_metadata and not has_discriminator_with_param: + if other_metadata and not preserve_full_annotation: type_annotation = Annotated[(type_annotation, *other_metadata)] # Process the annotation if it exists field_info: FieldInfo | None = None - if isinstance(powertools_annotation, FieldInfo): # pragma: no cover - field_info = _create_field_info(powertools_annotation, type_annotation, has_discriminator_with_param) + if isinstance(powertools_annotation, FieldInfo): + # When pairing a location marker with a plain Field, hand the full Annotated[...] to the + # field so the Field's constraints/discriminator flow into the validating TypeAdapter. + field_annotation = annotation if preserve_full_annotation else type_annotation + field_info = _create_field_info(powertools_annotation, field_annotation, preserve_full_annotation) _set_field_default(field_info, value, is_path_param) - - # Preserve full annotated type for discriminated unions - if _has_discriminator(powertools_annotation): # pragma: no cover - type_annotation = annotation # pragma: no cover + if preserve_full_annotation: + type_annotation = annotation return field_info, type_annotation diff --git a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py index 0da092f8aea..16639665c8c 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py @@ -30,7 +30,7 @@ VPCLatticeV2Resolver, ) from aws_lambda_powertools.event_handler.openapi.exceptions import ResponseValidationError -from aws_lambda_powertools.event_handler.openapi.params import Body, Form, Header, Query +from aws_lambda_powertools.event_handler.openapi.params import Body, Form, Header, Path, Query from tests.functional.utils import load_event @@ -2654,6 +2654,77 @@ def create_action(action: Annotated[action_type, Body()]): assert result["statusCode"] == 422 +def test_field_annotation_with_all_param_types(gw_event): + """A reusable Annotated type carrying a Pydantic Field works with every parameter location.""" + app = APIGatewayRestResolver(enable_validation=True) + + # Reusable annotated type, the same kind you'd use inside a model + str_field = Annotated[str, Field()] + + @app.get("/header") + def get_header(h: Annotated[str_field, Header()]): + return {"value": h} + + @app.get("/path/

") + def get_path(p: Annotated[str_field, Path()]): + return {"value": p} + + @app.get("/query") + def get_query(q: Annotated[str_field, Query()]): + return {"value": q} + + @app.post("/body") + def post_body(b: Annotated[str_field, Body()]): + return {"value": b} + + del gw_event["multiValueHeaders"] + del gw_event["multiValueQueryStringParameters"] + + # Header + gw_event["path"] = "/header" + gw_event["httpMethod"] = "GET" + gw_event["headers"] = {"h": "test"} + assert app(gw_event, {})["statusCode"] == 200 + + # Path + gw_event["path"] = "/path/test" + gw_event["pathParameters"] = {"p": "test"} + assert app(gw_event, {})["statusCode"] == 200 + + # Query + gw_event["path"] = "/query" + gw_event["pathParameters"] = None + gw_event["queryStringParameters"] = {"q": "test"} + assert app(gw_event, {})["statusCode"] == 200 + + # Body + gw_event["path"] = "/body" + gw_event["httpMethod"] = "POST" + gw_event["headers"]["content-type"] = "application/json" + gw_event["body"] = '"test"' + assert app(gw_event, {})["statusCode"] == 200 + + +def test_field_constraints_apply_with_param_type(gw_event): + """Constraints declared on a Field are enforced when paired with a location marker.""" + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/items") + def get_items(quantity: Annotated[int, Field(gt=0), Query()]): + return {"quantity": quantity} + + gw_event["path"] = "/items" + gw_event["httpMethod"] = "GET" + + # Passes the gt=0 constraint + gw_event["queryStringParameters"] = {"quantity": "5"} + assert app(gw_event, {})["statusCode"] == 200 + + # Violates gt=0 + gw_event["queryStringParameters"] = {"quantity": "-1"} + assert app(gw_event, {})["statusCode"] == 422 + + def test_validate_pydantic_query_params_with_config_dict_and_validators(gw_event): """Test that Pydantic models with ConfigDict, aliases, and validators work correctly""" From ea57e82fe3ef95da5706f3e8821c6d0aa5d67895 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 14:01:30 +0100 Subject: [PATCH 21/76] chore(ci): bump version to 3.31.0 (#8306) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index 4f56571437c..0854a8929e3 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "3.30.0" +VERSION = "3.31.0" diff --git a/pyproject.toml b/pyproject.toml index 8877f9371c4..24047d1ba4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "3.30.0" +version = "3.31.0" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From f8c7faf9c47c6d1ea60e50324670f1aafaa797f8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 14:03:16 +0100 Subject: [PATCH 22/76] chore(ci): layer docs update (#8307) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Leandro Damascena --- CHANGELOG.md | 63 +++- docs/includes/_layer_homepage_arm64.md | 290 ++++++++--------- docs/includes/_layer_homepage_x86.md | 300 +++++++++--------- examples/build_recipes/cdk/basic/app.py | 2 +- .../stacks/powertools_cdk_stack.py | 2 +- .../build_recipes/sam/multi-env/template.yaml | 2 +- .../sam/with-layers/template.yaml | 4 +- examples/homepage/install/arm64/amplify.txt | 4 +- examples/homepage/install/arm64/cdk_arm64.py | 2 +- .../homepage/install/arm64/pulumi_arm64.py | 2 +- examples/homepage/install/arm64/sam.yaml | 2 +- .../homepage/install/arm64/serverless.yml | 2 +- examples/homepage/install/arm64/terraform.tf | 2 +- examples/homepage/install/x86_64/amplify.txt | 4 +- examples/homepage/install/x86_64/cdk_x86.py | 2 +- .../homepage/install/x86_64/pulumi_x86.py | 2 +- examples/homepage/install/x86_64/sam.yaml | 2 +- .../homepage/install/x86_64/serverless.yml | 2 +- examples/homepage/install/x86_64/terraform.tf | 2 +- examples/logger/sam/template.yaml | 2 +- examples/metrics/sam/template.yaml | 2 +- examples/metrics_datadog/sam/template.yaml | 2 +- examples/tracer/sam/template.yaml | 2 +- 23 files changed, 380 insertions(+), 319 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8573c373338..ad7dc22c5a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,72 @@ # Unreleased + +## [v3.31.0] - 2026-06-29 +## Features + +* **event_handler:** support any Pydantic Field annotation in parameter ([#8305](https://github.com/aws-powertools/powertools-lambda-python/issues/8305)) + +## Maintenance + +* version bump + + ## [v3.30.0] - 2026-06-24 +## Bug Fixes + +* **batch:** add optional logger injection for BatchProcessors ([#7553](https://github.com/aws-powertools/powertools-lambda-python/issues/7553)) ([#8272](https://github.com/aws-powertools/powertools-lambda-python/issues/8272)) +* **docs:** update broken AWS Lambda Metadata Endpoint link ([#8209](https://github.com/aws-powertools/powertools-lambda-python/issues/8209)) +* **event-handler:** handle CORS preflight OPTIONS in HttpResolverLocal ([#8268](https://github.com/aws-powertools/powertools-lambda-python/issues/8268)) +* **event-handler:** fix ruff lint violations in event_handler module ([#8208](https://github.com/aws-powertools/powertools-lambda-python/issues/8208)) + +## Code Refactoring + +* **event_handler:** promote HttpResolver to stable ([#8289](https://github.com/aws-powertools/powertools-lambda-python/issues/8289)) + +## Documentation + +* **event-handler:** add import path gotcha for dependency_overrides testing ([#8269](https://github.com/aws-powertools/powertools-lambda-python/issues/8269)) +* **metadata:** fix broken Lambda Metadata Endpoint link ([#8212](https://github.com/aws-powertools/powertools-lambda-python/issues/8212)) + +## Features + +* **event_handler:** allow custom serializer on BedrockAgentResolver ([#8271](https://github.com/aws-powertools/powertools-lambda-python/issues/8271)) + ## Maintenance * version bump +* fix minor typos and grammar in docs and comments ([#8245](https://github.com/aws-powertools/powertools-lambda-python/issues/8245)) +* **deps:** bump the github-actions group across 1 directory with 5 updates ([#8256](https://github.com/aws-powertools/powertools-lambda-python/issues/8256)) +* **deps:** bump ujson from 5.12.1 to 5.13.0 ([#8298](https://github.com/aws-powertools/powertools-lambda-python/issues/8298)) +* **deps:** bump pydantic-settings from 2.14.1 to 2.14.2 ([#8299](https://github.com/aws-powertools/powertools-lambda-python/issues/8299)) +* **deps:** bump cryptography from 46.0.7 to 48.0.1 ([#8286](https://github.com/aws-powertools/powertools-lambda-python/issues/8286)) +* **deps:** consolidate Dependabot dependency updates ([#8285](https://github.com/aws-powertools/powertools-lambda-python/issues/8285)) +* **deps:** batch dependency updates ([#8207](https://github.com/aws-powertools/powertools-lambda-python/issues/8207)) +* **deps:** bump gitpython from 3.1.47 to 3.1.50 in /docs ([#8213](https://github.com/aws-powertools/powertools-lambda-python/issues/8213)) +* **deps:** bump urllib3 from 2.6.3 to 2.7.0 in /docs ([#8216](https://github.com/aws-powertools/powertools-lambda-python/issues/8216)) +* **deps:** consolidate dependabot updates (13052026) ([#8228](https://github.com/aws-powertools/powertools-lambda-python/issues/8228)) +* **deps:** bump the github-actions group with 3 updates ([#8221](https://github.com/aws-powertools/powertools-lambda-python/issues/8221)) +* **deps:** bump codecov/codecov-action from 6.0.1 to 7.0.0 in the github-actions group ([#8260](https://github.com/aws-powertools/powertools-lambda-python/issues/8260)) +* **deps:** consolidate all open Dependabot updates ([#8241](https://github.com/aws-powertools/powertools-lambda-python/issues/8241)) +* **deps:** bump the github-actions group with 2 updates ([#8292](https://github.com/aws-powertools/powertools-lambda-python/issues/8292)) +* **deps:** bump pydantic from 2.12.5 to 2.13.4 ([#8252](https://github.com/aws-powertools/powertools-lambda-python/issues/8252)) +* **deps:** update requests requirement from >=2.33.1 to >=2.34.2 in /examples/event_handler_graphql/src ([#8254](https://github.com/aws-powertools/powertools-lambda-python/issues/8254)) +* **deps-dev:** bump aws-cdk from 2.1127.0 to 2.1128.1 in the aws-cdk group ([#8290](https://github.com/aws-powertools/powertools-lambda-python/issues/8290)) +* **deps-dev:** bump the dev-dependencies group across 1 directory with 2 updates ([#8242](https://github.com/aws-powertools/powertools-lambda-python/issues/8242)) +* **deps-dev:** bump aws-cdk from 2.1122.0 to 2.1124.1 in the aws-cdk group across 1 directory ([#8234](https://github.com/aws-powertools/powertools-lambda-python/issues/8234)) +* **deps-dev:** bump boto3-stubs from 1.43.3 to 1.43.24 ([#8265](https://github.com/aws-powertools/powertools-lambda-python/issues/8265)) +* **deps-dev:** bump aws-cdk from 2.1124.1 to 2.1126.0 in the aws-cdk group across 1 directory ([#8255](https://github.com/aws-powertools/powertools-lambda-python/issues/8255)) +* **deps-dev:** bump the dev-dependencies group with 3 updates ([#8261](https://github.com/aws-powertools/powertools-lambda-python/issues/8261)) +* **deps-dev:** bump urllib3 from 2.6.3 to 2.7.0 in /layer_v3 ([#8218](https://github.com/aws-powertools/powertools-lambda-python/issues/8218)) +* **deps-dev:** bump urllib3 from 2.6.3 to 2.7.0 ([#8217](https://github.com/aws-powertools/powertools-lambda-python/issues/8217)) +* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.251.0a0 to 2.259.0a0 ([#8262](https://github.com/aws-powertools/powertools-lambda-python/issues/8262)) +* **deps-dev:** bump sentry-sdk from 2.57.0 to 2.62.0 ([#8263](https://github.com/aws-powertools/powertools-lambda-python/issues/8263)) +* **deps-dev:** bump gitpython from 3.1.47 to 3.1.50 ([#8214](https://github.com/aws-powertools/powertools-lambda-python/issues/8214)) +* **deps-dev:** bump the dev-dependencies group across 1 directory with 2 updates ([#8276](https://github.com/aws-powertools/powertools-lambda-python/issues/8276)) * **deps-dev:** bump aws-cdk-lib from 2.259.0 to 2.260.0 ([#8294](https://github.com/aws-powertools/powertools-lambda-python/issues/8294)) +* **deps-dev:** bump the dev-dependencies group across 1 directory with 3 updates ([#8293](https://github.com/aws-powertools/powertools-lambda-python/issues/8293)) @@ -7699,7 +7759,8 @@ * Merge pull request [#5](https://github.com/aws-powertools/powertools-lambda-python/issues/5) from jfuss/feat/python38 -[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.30.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.31.0...HEAD +[v3.31.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.30.0...v3.31.0 [v3.30.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.29.0...v3.30.0 [v3.29.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.28.0...v3.29.0 [v3.28.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.27.0...v3.28.0 diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index a9aea03c29d..8c7337ee7ee 100644 --- a/docs/includes/_layer_homepage_arm64.md +++ b/docs/includes/_layer_homepage_arm64.md @@ -6,168 +6,168 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 811cd17eee4..10789aede59 100644 --- a/docs/includes/_layer_homepage_x86.md +++ b/docs/includes/_layer_homepage_x86.md @@ -5,173 +5,173 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:34**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | diff --git a/examples/build_recipes/cdk/basic/app.py b/examples/build_recipes/cdk/basic/app.py index 121701664ce..9f4fef0d988 100644 --- a/examples/build_recipes/cdk/basic/app.py +++ b/examples/build_recipes/cdk/basic/app.py @@ -24,7 +24,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35", ) # Lambda Function diff --git a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py index 02624fd0138..fd0dd8768a2 100644 --- a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py +++ b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py @@ -47,7 +47,7 @@ def _create_powertools_layer(self) -> _lambda.ILayerVersion: return _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35", ) def _create_dynamodb_table(self) -> dynamodb.Table: diff --git a/examples/build_recipes/sam/multi-env/template.yaml b/examples/build_recipes/sam/multi-env/template.yaml index 6276d0b740f..2d3f03adb5a 100644 --- a/examples/build_recipes/sam/multi-env/template.yaml +++ b/examples/build_recipes/sam/multi-env/template.yaml @@ -61,7 +61,7 @@ Resources: CodeUri: src/ Handler: app.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35 - !Ref DependenciesLayer Events: ApiEvent: diff --git a/examples/build_recipes/sam/with-layers/template.yaml b/examples/build_recipes/sam/with-layers/template.yaml index 38a33639ad2..fb4a97f8f06 100644 --- a/examples/build_recipes/sam/with-layers/template.yaml +++ b/examples/build_recipes/sam/with-layers/template.yaml @@ -31,7 +31,7 @@ Resources: CodeUri: src/app/ Handler: app_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35 - !Ref DependenciesLayer Events: ApiEvent: @@ -50,7 +50,7 @@ Resources: CodeUri: src/worker/ Handler: worker_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:34 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35 - !Ref DependenciesLayer Events: SQSEvent: diff --git a/examples/homepage/install/arm64/amplify.txt b/examples/homepage/install/arm64/amplify.txt index c15899b82ee..55025d12efe 100644 --- a/examples/homepage/install/arm64/amplify.txt +++ b/examples/homepage/install/arm64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/arm64/cdk_arm64.py b/examples/homepage/install/arm64/cdk_arm64.py index 62626fe010c..2ecad4de5b7 100644 --- a/examples/homepage/install/arm64/cdk_arm64.py +++ b/examples/homepage/install/arm64/cdk_arm64.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/arm64/pulumi_arm64.py b/examples/homepage/install/arm64/pulumi_arm64.py index a5fcc1c6159..e835aaad8b5 100644 --- a/examples/homepage/install/arm64/pulumi_arm64.py +++ b/examples/homepage/install/arm64/pulumi_arm64.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/arm64/sam.yaml b/examples/homepage/install/arm64/sam.yaml index ad4527209a9..251be092618 100644 --- a/examples/homepage/install/arm64/sam.yaml +++ b/examples/homepage/install/arm64/sam.yaml @@ -9,4 +9,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 diff --git a/examples/homepage/install/arm64/serverless.yml b/examples/homepage/install/arm64/serverless.yml index 0bf70b1edf3..3a31aa80873 100644 --- a/examples/homepage/install/arm64/serverless.yml +++ b/examples/homepage/install/arm64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 diff --git a/examples/homepage/install/arm64/terraform.tf b/examples/homepage/install/arm64/terraform.tf index 3f09dd9c1c5..15cb3fdb6d2 100644 --- a/examples/homepage/install/arm64/terraform.tf +++ b/examples/homepage/install/arm64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:34"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") diff --git a/examples/homepage/install/x86_64/amplify.txt b/examples/homepage/install/x86_64/amplify.txt index e0a543f96f9..de4a09e62e6 100644 --- a/examples/homepage/install/x86_64/amplify.txt +++ b/examples/homepage/install/x86_64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/x86_64/cdk_x86.py b/examples/homepage/install/x86_64/cdk_x86.py index 29e67578591..7cc43a5535b 100644 --- a/examples/homepage/install/x86_64/cdk_x86.py +++ b/examples/homepage/install/x86_64/cdk_x86.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/x86_64/pulumi_x86.py b/examples/homepage/install/x86_64/pulumi_x86.py index 3d3e4a6f650..b96c7a61107 100644 --- a/examples/homepage/install/x86_64/pulumi_x86.py +++ b/examples/homepage/install/x86_64/pulumi_x86.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml index 1a2dc187a10..738e54ab340 100644 --- a/examples/homepage/install/x86_64/sam.yaml +++ b/examples/homepage/install/x86_64/sam.yaml @@ -8,4 +8,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml index 92ce1c2c434..bcede79fdac 100644 --- a/examples/homepage/install/x86_64/serverless.yml +++ b/examples/homepage/install/x86_64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf index 27433e192a6..3a272d5ac81 100644 --- a/examples/homepage/install/x86_64/terraform.tf +++ b/examples/homepage/install/x86_64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 87387aff1fe..ba411569c86 100644 --- a/examples/logger/sam/template.yaml +++ b/examples/logger/sam/template.yaml @@ -14,7 +14,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index 21e08387e5d..d5dab46f9d2 100644 --- a/examples/metrics/sam/template.yaml +++ b/examples/metrics/sam/template.yaml @@ -16,7 +16,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 Resources: CaptureLambdaHandlerExample: diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml index cf6ac73c17b..6191e384264 100644 --- a/examples/metrics_datadog/sam/template.yaml +++ b/examples/metrics_datadog/sam/template.yaml @@ -20,7 +20,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 # Find the latest Layer version in the Datadog official documentation # Datadog SDK diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml index 4140c75ece6..156b5db6b83 100644 --- a/examples/tracer/sam/template.yaml +++ b/examples/tracer/sam/template.yaml @@ -13,7 +13,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:34 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 Resources: CaptureLambdaHandlerExample: From 5535469871fc9ef47e2b2e4bd1bbcf2639a174a3 Mon Sep 17 00:00:00 2001 From: Amin Farjadi <31803062+amin-farjadi@users.noreply.github.com> Date: Thu, 2 Jul 2026 08:31:25 +0100 Subject: [PATCH 23/76] fix: EventBridgeEvent data class (#8301) * fix: EventBridgeEvent data class * refactor: improve namings, add docstring * address comment on issue 8300 * fix small things --------- Co-authored-by: Amin Farjadi Co-authored-by: Leandro Damascena --- .../utilities/data_classes/event_bridge_event.py | 2 +- tests/events/eventBridgeEvent.json | 9 +++------ .../required_dependencies/test_event_bridge_event.py | 2 +- tests/unit/parser/_pydantic/test_eventbridge.py | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py b/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py index f7ce1953e2a..4655701574d 100644 --- a/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py +++ b/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py @@ -68,4 +68,4 @@ def detail(self) -> dict[str, Any]: @property def replay_name(self) -> str | None: """Identifies whether the event is being replayed and what is the name of the replay.""" - return self["replay-name"] + return self.get("replay-name") diff --git a/tests/events/eventBridgeEvent.json b/tests/events/eventBridgeEvent.json index 65872cf9a34..f7c6d4c0d37 100644 --- a/tests/events/eventBridgeEvent.json +++ b/tests/events/eventBridgeEvent.json @@ -6,12 +6,9 @@ "account": "111122223333", "time": "2017-12-22T18:43:48Z", "region": "us-west-1", - "resources": [ - "arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0" - ], + "resources": [], "detail": { "instance_id": "i-1234567890abcdef0", "state": "terminated" - }, - "replay-name": "replay_archive" -} + } +} \ No newline at end of file diff --git a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py index 6dfc0c82485..e581cacae32 100644 --- a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py +++ b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py @@ -17,4 +17,4 @@ def test_event_bridge_event(): assert parsed_event.source == raw_event["source"] assert parsed_event.detail_type == raw_event["detail-type"] assert parsed_event.detail == raw_event["detail"] - assert parsed_event.replay_name == "replay_archive" + assert parsed_event.replay_name is None diff --git a/tests/unit/parser/_pydantic/test_eventbridge.py b/tests/unit/parser/_pydantic/test_eventbridge.py index 585406e7095..86ebc5bc204 100644 --- a/tests/unit/parser/_pydantic/test_eventbridge.py +++ b/tests/unit/parser/_pydantic/test_eventbridge.py @@ -45,7 +45,7 @@ def test_handle_eventbridge_trigger_event_no_envelope(): assert parsed_event.resources == raw_event["resources"] assert parsed_event.source == raw_event["source"] assert parsed_event.detail_type == raw_event["detail-type"] - assert parsed_event.replay_name == raw_event["replay-name"] + assert parsed_event.replay_name is None def test_handle_invalid_event_with_eventbridge_envelope(): From cb6f90620ffdf68c8df58cd3defb6e7ed19dc0d1 Mon Sep 17 00:00:00 2001 From: rodos Date: Thu, 2 Jul 2026 21:26:56 +1000 Subject: [PATCH 24/76] feat(circuit_breaker): support composite primary key in DynamoDB persistence (#8316) * feat(circuit_breaker): support composite primary key in DynamoDB persistence Add optional `sort_key_attr` and `static_pk_value` parameters to CircuitBreakerDynamoDBPersistence so circuit state can be stored in a single-table (composite key) design, mirroring the Idempotency utility. When `sort_key_attr` is set, the circuit name is written to the sort key and `static_pk_value` to the partition key (default `circuit_breaker#`); omit it for the current partition-key-only behavior. The composite key is threaded through the get, conditional put (half-open probe election) and update paths. Includes Stubber-based tests for both modes, docs, and an example. Closes #8315 * fix(circuit_breaker): rename the composite-key example to a unique basename so mypy no longer clashes with the idempotency example. * feat(circuit_breaker): warn when static_pk_value is passed without sort_key_attr since it is otherwise silently ignored. --------- Co-authored-by: Leandro Damascena --- .../persistence/dynamodb.py | 48 ++++++- docs/utilities/circuit_breaker.md | 24 +++- .../src/working_with_composite_primary_key.py | 31 +++++ .../test_dynamodb_persistence.py | 127 ++++++++++++++++++ 4 files changed, 224 insertions(+), 6 deletions(-) create mode 100644 examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py index 386de753839..dc557ef1218 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py @@ -6,19 +6,22 @@ import datetime import logging +import os +import warnings from typing import TYPE_CHECKING import boto3 from boto3.dynamodb.types import TypeDeserializer from botocore.exceptions import ClientError -from aws_lambda_powertools.shared import user_agent +from aws_lambda_powertools.shared import constants, user_agent from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( CircuitBreakerExistingLockError, CircuitBreakerPersistenceLayer, ) from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState +from aws_lambda_powertools.warnings import PowertoolsUserWarning if TYPE_CHECKING: from botocore.config import Config @@ -41,6 +44,13 @@ class CircuitBreakerDynamoDBPersistence(CircuitBreakerPersistenceLayer): Name of the DynamoDB table that stores circuit state. key_attr : str Partition key attribute holding the circuit name. Defaults to ``"id"``. + static_pk_value : str, optional + Partition key value used when ``sort_key_attr`` is set, so the circuit name + moves to the sort key. Defaults to ``"circuit_breaker#"``. + sort_key_attr : str, optional + Sort key attribute holding the circuit name. When set, the table is treated as + composite: ``static_pk_value`` is written to the partition key and the circuit + name to the sort key. Omit it for the default partition-key-only behavior. state_attr : str Attribute holding the circuit state. Defaults to ``"state"``. failure_count_attr : str @@ -75,6 +85,8 @@ def __init__( self, table_name: str, key_attr: str = "id", + static_pk_value: str | None = None, + sort_key_attr: str | None = None, state_attr: str = "state", failure_count_attr: str = "failure_count", opened_at_attr: str = "opened_at", @@ -92,8 +104,23 @@ def __init__( user_agent.register_feature_to_client(client=self.client, feature="circuit_breaker") + if sort_key_attr == key_attr: + raise ValueError(f"key_attr [{key_attr}] and sort_key_attr [{sort_key_attr}] cannot be the same!") + + if static_pk_value is not None and sort_key_attr is None: + warnings.warn( + "static_pk_value is ignored unless sort_key_attr is also set.", + category=PowertoolsUserWarning, + stacklevel=2, + ) + + if static_pk_value is None: + static_pk_value = f"circuit_breaker#{os.getenv(constants.LAMBDA_FUNCTION_NAME_ENV, '')}" + self.table_name = table_name self.key_attr = key_attr + self.static_pk_value = static_pk_value + self.sort_key_attr = sort_key_attr self.state_attr = state_attr self.failure_count_attr = failure_count_attr self.opened_at_attr = opened_at_attr @@ -111,7 +138,7 @@ def _item_to_record(self, item: dict) -> CircuitStateRecord: opened_at = data.get(self.opened_at_attr) probe_lease_expiry = data.get(self.probe_lease_expiry_attr) return CircuitStateRecord( - name=data[self.key_attr], + name=data[self.sort_key_attr] if self.sort_key_attr else data[self.key_attr], state=CircuitState(data[self.state_attr]), failure_count=int(data.get(self.failure_count_attr, 0)), opened_at=int(opened_at) if opened_at is not None else None, @@ -130,10 +157,21 @@ def _s(value: str) -> dict: """Wrap a value as a DynamoDB string attribute.""" return {"S": value} + def _get_key(self, name: str) -> dict: + """Build the simple or composite primary key for a circuit. + + When ``sort_key_attr`` is set the key is composite: ``static_pk_value`` in the + partition and the circuit name in the sort key. Otherwise the name is the + partition key. + """ + if self.sort_key_attr: + return {self.key_attr: self._s(self.static_pk_value), self.sort_key_attr: self._s(name)} + return {self.key_attr: self._s(name)} + def _record_to_item(self, record: CircuitStateRecord) -> dict: """Translate a :class:`CircuitStateRecord` into a DynamoDB item.""" item: dict = { - self.key_attr: self._s(record.name), + **self._get_key(record.name), self.state_attr: self._s(str(record.state)), self.failure_count_attr: self._n(record.failure_count), } @@ -152,7 +190,7 @@ def _get_record(self, name: str) -> CircuitStateRecord | None: # and halves the read cost on the hot path. response = self.client.get_item( TableName=self.table_name, - Key={self.key_attr: self._s(name)}, + Key=self._get_key(name), ConsistentRead=False, ) item = response.get("Item") @@ -242,7 +280,7 @@ def _build_update_query(self, record: CircuitStateRecord) -> dict: return { "TableName": self.table_name, - "Key": {self.key_attr: self._s(record.name)}, + "Key": self._get_key(record.name), "UpdateExpression": update_expression, "ExpressionAttributeNames": expression_attr_names, "ExpressionAttributeValues": expression_attr_values, diff --git a/docs/utilities/circuit_breaker.md b/docs/utilities/circuit_breaker.md index 5087e24310b..f83685862f0 100644 --- a/docs/utilities/circuit_breaker.md +++ b/docs/utilities/circuit_breaker.md @@ -91,7 +91,7 @@ Unless you're looking to [customize each attribute](#customizing-the-dynamodb-ta | Partition key | `id` | Holds the circuit name | | TTL attribute name | `expiration` | Using AWS Console? This is configurable after table creation | -You **can** use a single DynamoDB table for all your circuits. +You **can** use a single DynamoDB table for all your circuits. Already have a single-table (composite key) design you want to reuse? See [Using a composite primary key](#using-a-composite-primary-key). ##### DynamoDB IaC example @@ -218,6 +218,28 @@ Set **`POWERTOOLS_CIRCUIT_BREAKER_DISABLED`**{: .copyMe} to a truthy value to by `CircuitBreakerDynamoDBPersistence` accepts attribute-name overrides (`key_attr`, `state_attr`, `failure_count_attr`, `opened_at_attr`, `half_open_owner_attr`, `expiry_attr`) and the usual boto3 escape hatches (`boto3_session`, `boto3_client`, `boto_config`) for reusing an existing table layout or client. +#### Using a composite primary key + +Use the `sort_key_attr` parameter when your table is configured with a composite primary key _(hash+range key)_, as in a single-table design. + +When enabled, the circuit name is saved in the sort key instead, and the partition key defaults to `circuit_breaker#{LAMBDA_FUNCTION_NAME}` — this **namespaces circuits per function** so two functions can use the same circuit name without sharing state. (Without `sort_key_attr`, the default remains partition-key-only with the circuit name as the partition key.) + +Set `static_pk_value` to a fixed value (as below) when you instead want **multiple functions to share the same circuit** — for example, every function guarding the same downstream dependency should trip together. + +```python hl_lines="12-14" +--8<-- "examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py" +``` + +??? note "Click to expand and learn how table items would look like" + + The circuit name is stored in the sort key, so several circuits share one partition. Attributes that don't apply to a state are simply absent. + + | PK | SK | state | failure_count | opened_at | half_open_owner | probe_lease_expiry | expiration | + | --------------- | --------------- | --------- | ------------- | ---------- | --------------- | ------------------ | ---------- | + | CIRCUIT_BREAKER | payment-backend | OPEN | 5 | 1699999999 | | | 1700003599 | + | CIRCUIT_BREAKER | inventory-api | HALF_OPEN | 5 | 1699999999 | 9f3c1a2b-env | 1700000030 | 1700003599 | + | CIRCUIT_BREAKER | email-service | CLOSED | 0 | | | | | + ## Testing your code When unit testing the function a circuit protects, set `POWERTOOLS_CIRCUIT_BREAKER_DISABLED=true` to bypass the circuit and persistence layer entirely, so your tests exercise the business logic without needing DynamoDB. diff --git a/examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py b/examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py new file mode 100644 index 00000000000..d2ef0ae9a17 --- /dev/null +++ b/examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py @@ -0,0 +1,31 @@ +import os + +from aws_lambda_powertools.utilities.circuit_breaker_alpha import circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.typing import LambdaContext + +table = os.getenv("CIRCUIT_BREAKER_TABLE", "") +persistence = CircuitBreakerDynamoDBPersistence( + table_name=table, + key_attr="PK", + sort_key_attr="SK", + static_pk_value="CIRCUIT_BREAKER", +) + + +class PaymentBackend: + def charge(self, order: dict): ... + + +payment_api = PaymentBackend() + + +@circuit_breaker(name="payment-backend", persistence_store=persistence) +def charge(order: dict) -> dict: + return payment_api.charge(order) # the protected downstream call + + +def lambda_handler(event: dict, context: LambdaContext): + return charge(event) diff --git a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py index d1617f26617..4555c088e36 100644 --- a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py +++ b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py @@ -10,6 +10,7 @@ CircuitBreakerDynamoDBPersistence, ) from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState +from aws_lambda_powertools.warnings import PowertoolsUserWarning TABLE_NAME = "CircuitBreakerState" @@ -268,3 +269,129 @@ def test_build_half_open_condition_with_expected_opened_at(persistence): assert "#opened_at = :expected_opened_at" in result["ConditionExpression"] assert result["ExpressionAttributeNames"]["#opened_at"] == "opened_at" assert result["ExpressionAttributeValues"][":expected_opened_at"] == {"N": "5000"} + + +# --------------------------------------------------------------------------- composite (single-table) key + + +COMPOSITE_KEY = {"PK": {"S": "CIRCUIT_BREAKER"}, "SK": {"S": "payment"}} + + +@pytest.fixture +def composite_persistence(): + client = boto3.client("dynamodb", config=Config(region_name="us-east-1")) + layer = CircuitBreakerDynamoDBPersistence( + table_name=TABLE_NAME, + boto3_client=client, + key_attr="PK", + sort_key_attr="SK", + static_pk_value="CIRCUIT_BREAKER", + ) + layer.configure(CircuitBreakerConfig(local_cache_max_age=0), circuit_name="payment") + return layer + + +def test_composite_get_state_reads_composite_key(composite_persistence): + stubber = Stubber(composite_persistence.client) + stubber.add_response( + "get_item", + {}, + {"TableName": TABLE_NAME, "Key": COMPOSITE_KEY, "ConsistentRead": False}, + ) + with stubber: + record = composite_persistence.get_state("payment") + assert record.state == CircuitState.CLOSED + + +def test_composite_save_open_writes_composite_key(composite_persistence): + captured, restore = _capture_put_item(composite_persistence) + try: + composite_persistence.save_open("payment", failure_count=5, opened_at=1000) + finally: + restore() + + item = captured["Item"] + assert item["PK"] == {"S": "CIRCUIT_BREAKER"} + assert item["SK"] == {"S": "payment"} + assert "id" not in item + assert item["state"] == {"S": "OPEN"} + + +def test_composite_try_acquire_half_open_writes_composite_key(composite_persistence): + captured, restore = _capture_put_item(composite_persistence) + try: + assert composite_persistence.try_acquire_half_open("payment", "env-a", 1000) is True + finally: + restore() + + item = captured["Item"] + assert item["PK"] == {"S": "CIRCUIT_BREAKER"} + assert item["SK"] == {"S": "payment"} + assert item["state"] == {"S": "HALF_OPEN"} + # The conditional election is still emitted in composite mode (condition is key-independent). + assert "#state = :open AND attribute_not_exists(#half_open_owner)" in captured["ConditionExpression"] + assert "#probe_lease_expiry <= :now" in captured["ConditionExpression"] + + +def test_composite_try_acquire_half_open_loses_on_conditional_failure(composite_persistence): + stubber = Stubber(composite_persistence.client) + stubber.add_client_error("put_item", service_error_code="ConditionalCheckFailedException") + with stubber: + assert composite_persistence.try_acquire_half_open("payment", "env-b", 1000) is False + + +def test_composite_save_closed_updates_composite_key(composite_persistence): + captured = {} + original_update = composite_persistence.client.update_item + + def capturing_update(**kwargs): + captured.update(kwargs) + return {} + + composite_persistence.client.update_item = capturing_update + try: + composite_persistence.save_closed("payment") + finally: + composite_persistence.client.update_item = original_update + + assert captured["Key"] == COMPOSITE_KEY + + +def test_composite_item_to_record_reads_name_from_sort_key(composite_persistence): + item = { + "PK": {"S": "CIRCUIT_BREAKER"}, + "SK": {"S": "payment"}, + "state": {"S": "OPEN"}, + "failure_count": {"N": "2"}, + } + record = composite_persistence._item_to_record(item) + assert record.name == "payment" + assert record.state == CircuitState.OPEN + + +def test_sort_key_equal_to_key_attr_raises(): + client = boto3.client("dynamodb", config=Config(region_name="us-east-1")) + with pytest.raises(ValueError, match="cannot be the same"): + CircuitBreakerDynamoDBPersistence( + table_name=TABLE_NAME, + boto3_client=client, + key_attr="PK", + sort_key_attr="PK", + ) + + +def test_default_static_pk_value_namespaces_function_name(monkeypatch): + monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", "orders-fn") + client = boto3.client("dynamodb", config=Config(region_name="us-east-1")) + layer = CircuitBreakerDynamoDBPersistence(table_name=TABLE_NAME, boto3_client=client, sort_key_attr="SK") + assert layer.static_pk_value == "circuit_breaker#orders-fn" + + +def test_static_pk_value_without_sort_key_attr_warns(): + client = boto3.client("dynamodb", config=Config(region_name="us-east-1")) + with pytest.warns(PowertoolsUserWarning, match="static_pk_value is ignored unless sort_key_attr"): + CircuitBreakerDynamoDBPersistence( + table_name=TABLE_NAME, + boto3_client=client, + static_pk_value="CIRCUIT_BREAKER", + ) From bc78b7f1de1fb918e692871825f528e59b884b1b Mon Sep 17 00:00:00 2001 From: rodos Date: Sat, 4 Jul 2026 19:00:28 +1000 Subject: [PATCH 25/76] fix(circuit_breaker): normalize handled/ignored exceptions to a validated tuple at construction (#8319) --- .../utilities/circuit_breaker_alpha/config.py | 72 ++++++++++++++++--- .../persistence/dynamodb.py | 5 +- .../test_dynamodb_persistence.py | 3 +- .../test_config_and_states.py | 45 ++++++++++++ 4 files changed, 115 insertions(+), 10 deletions(-) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py index 9425e90ab38..398ff33d6e2 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py @@ -4,8 +4,13 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerConfigError +if TYPE_CHECKING: + from collections.abc import Iterable + class CircuitBreakerConfig: """ @@ -24,12 +29,14 @@ class CircuitBreakerConfig: success_threshold : int Number of *consecutive* probe successes required to close a half-open circuit. Defaults to 3. - handled_exceptions : tuple[type[Exception], ...] | None + handled_exceptions : type[Exception] | Iterable[type[Exception]] | None Allowlist: only these exception types count as failures; anything else - propagates without affecting the circuit. Mutually exclusive with + propagates without affecting the circuit. Accepts a single exception type or + an iterable of them (normalized to a tuple). Mutually exclusive with ``ignored_exceptions``. Defaults to ``None`` (treated as ``(Exception,)``). - ignored_exceptions : tuple[type[Exception], ...] | None - Denylist: every exception counts as a failure *except* these. Mutually + ignored_exceptions : type[Exception] | Iterable[type[Exception]] | None + Denylist: every exception counts as a failure *except* these. Accepts a single + exception type or an iterable of them (normalized to a tuple). Mutually exclusive with ``handled_exceptions``. Defaults to ``None``. local_cache_max_age : int Seconds a circuit's state is cached in the execution environment before a @@ -38,8 +45,9 @@ class CircuitBreakerConfig: Raises ------ CircuitBreakerConfigError - If both ``handled_exceptions`` and ``ignored_exceptions`` are provided, or a - numeric tunable is not a positive integer. + If both ``handled_exceptions`` and ``ignored_exceptions`` are provided, a + numeric tunable is not a positive integer, or an exception allowlist/denylist + is empty or contains a value that is not an exception type. Example ------- @@ -57,10 +65,16 @@ def __init__( failure_threshold: int = 5, recovery_timeout: int = 30, success_threshold: int = 3, - handled_exceptions: tuple[type[Exception], ...] | None = None, - ignored_exceptions: tuple[type[Exception], ...] | None = None, + handled_exceptions: type[Exception] | Iterable[type[Exception]] | None = None, + ignored_exceptions: type[Exception] | Iterable[type[Exception]] | None = None, local_cache_max_age: int = 5, ): + # Normalize first: a single exception type or any iterable becomes a tuple, and a + # bad value fails here (at construction) rather than as a cryptic isinstance + # TypeError later, the first time the circuit evaluates a failure. + handled_exceptions = self._normalize_exceptions(handled_exceptions, "handled_exceptions") + ignored_exceptions = self._normalize_exceptions(ignored_exceptions, "ignored_exceptions") + self._validate( failure_threshold=failure_threshold, recovery_timeout=recovery_timeout, @@ -105,6 +119,48 @@ def _validate( f"local_cache_max_age must be a non-negative integer, got {local_cache_max_age!r}.", ) + @classmethod + def _normalize_exceptions( + cls, + value: type[Exception] | Iterable[type[Exception]] | None, + field: str, + ) -> tuple[type[Exception], ...] | None: + """Coerce a single exception type or an iterable of them into a validated, non-empty tuple. + + Runs at construction so a bad value fails immediately with a clear error, rather + than as a cryptic ``isinstance`` ``TypeError`` from ``counts_as_failure`` the + first time the circuit evaluates a failure (i.e. only once the dependency is + already unhealthy). + """ + if value is None: + return None + + invalid = f"{field} must be an exception type or an iterable of exception types, got {value!r}." + # A str is iterable; reject it rather than iterate it as a sequence of characters. + if isinstance(value, str): + raise CircuitBreakerConfigError(invalid) + + if isinstance(value, type): + # ty (unlike mypy) does not narrow the union here, so it needs the ignore. + exceptions: tuple[type[Exception], ...] = (value,) # ty: ignore[invalid-assignment] + else: + try: + exceptions = tuple(value) + except TypeError: + raise CircuitBreakerConfigError(invalid) from None + + cls._validate_exception_types(exceptions, field) + return exceptions + + @staticmethod + def _validate_exception_types(exceptions: tuple[type[Exception], ...], field: str) -> None: + """Require a non-empty tuple whose every element is an exception type.""" + if not exceptions: + raise CircuitBreakerConfigError(f"{field} must contain at least one exception type.") + for exception in exceptions: + if not (isinstance(exception, type) and issubclass(exception, Exception)): + raise CircuitBreakerConfigError(f"{field} must contain only exception types, got {exception!r}.") + def counts_as_failure(self, exception: Exception) -> bool: """ Decide whether an exception raised by the protected call counts as a circuit failure. diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py index dc557ef1218..edcbf502ab5 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py @@ -15,6 +15,7 @@ from botocore.exceptions import ClientError from aws_lambda_powertools.shared import constants, user_agent +from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerConfigError from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( CircuitBreakerExistingLockError, CircuitBreakerPersistenceLayer, @@ -105,7 +106,9 @@ def __init__( user_agent.register_feature_to_client(client=self.client, feature="circuit_breaker") if sort_key_attr == key_attr: - raise ValueError(f"key_attr [{key_attr}] and sort_key_attr [{sort_key_attr}] cannot be the same!") + raise CircuitBreakerConfigError( + f"key_attr [{key_attr}] and sort_key_attr [{sort_key_attr}] cannot be the same!", + ) if static_pk_value is not None and sort_key_attr is None: warnings.warn( diff --git a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py index 4555c088e36..9effa8cbafd 100644 --- a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py +++ b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py @@ -6,6 +6,7 @@ from botocore.stub import Stubber from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerConfigError from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( CircuitBreakerDynamoDBPersistence, ) @@ -371,7 +372,7 @@ def test_composite_item_to_record_reads_name_from_sort_key(composite_persistence def test_sort_key_equal_to_key_attr_raises(): client = boto3.client("dynamodb", config=Config(region_name="us-east-1")) - with pytest.raises(ValueError, match="cannot be the same"): + with pytest.raises(CircuitBreakerConfigError, match="cannot be the same"): CircuitBreakerDynamoDBPersistence( table_name=TABLE_NAME, boto3_client=client, diff --git a/tests/unit/circuit_breaker_alpha/test_config_and_states.py b/tests/unit/circuit_breaker_alpha/test_config_and_states.py index a0b811e38c0..602f7f4c9d7 100644 --- a/tests/unit/circuit_breaker_alpha/test_config_and_states.py +++ b/tests/unit/circuit_breaker_alpha/test_config_and_states.py @@ -72,6 +72,51 @@ def test_counts_as_failure_denylist(): assert config.counts_as_failure(KeyError()) is True +def test_config_normalizes_handled_exceptions_list_to_tuple(): + config = CircuitBreakerConfig(handled_exceptions=[TimeoutError, ConnectionError]) + assert config.handled_exceptions == (TimeoutError, ConnectionError) + # The reported bug: a list must not break counts_as_failure when the circuit evaluates a failure. + assert config.counts_as_failure(TimeoutError()) is True + assert config.counts_as_failure(ValueError()) is False + + +def test_config_normalizes_single_exception_type_to_tuple(): + config = CircuitBreakerConfig(handled_exceptions=ValueError) + assert config.handled_exceptions == (ValueError,) + assert config.counts_as_failure(ValueError()) is True + + +def test_config_normalizes_ignored_exceptions_list_to_tuple(): + config = CircuitBreakerConfig(ignored_exceptions=[ValueError]) + assert config.ignored_exceptions == (ValueError,) + assert config.counts_as_failure(ValueError()) is False + assert config.counts_as_failure(KeyError()) is True + + +def test_config_normalizes_iterator_of_exceptions(): + config = CircuitBreakerConfig(handled_exceptions=iter((TimeoutError, KeyError))) + assert config.handled_exceptions == (TimeoutError, KeyError) + + +@pytest.mark.parametrize("field", ["handled_exceptions", "ignored_exceptions"]) +def test_config_rejects_non_exception_type_in_list(field): + with pytest.raises(CircuitBreakerConfigError, match="only exception types"): + CircuitBreakerConfig(**{field: ["not-an-exception"]}) + + +@pytest.mark.parametrize("field", ["handled_exceptions", "ignored_exceptions"]) +@pytest.mark.parametrize("value", [5, "ValueError"]) +def test_config_rejects_non_iterable_or_str_exceptions(field, value): + with pytest.raises(CircuitBreakerConfigError, match="iterable of exception types"): + CircuitBreakerConfig(**{field: value}) + + +@pytest.mark.parametrize("field", ["handled_exceptions", "ignored_exceptions"]) +def test_config_rejects_empty_exceptions(field): + with pytest.raises(CircuitBreakerConfigError, match="at least one exception type"): + CircuitBreakerConfig(**{field: []}) + + def test_open_error_carries_circuit_info(): info = CircuitInfo(name="payment", state=CircuitState.OPEN, failure_count=5, opened_at=123) error = CircuitBreakerOpenError("open", circuit=info) From e7f70660e7048ec2dc3c4d79fcbddc92214fdf3a Mon Sep 17 00:00:00 2001 From: rodos Date: Sun, 5 Jul 2026 22:38:41 +1000 Subject: [PATCH 26/76] fix(circuit_breaker): make probe election per-thread and synchronize local counters (#8323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(circuit_breaker): make probe election per-thread and synchronize local counters The half-open probe owner id was minted once per process, so every thread in a process passed the owner check once any sibling won the election and all of them probed the recovering backend. The id is now a per-thread uuid (pid-aware for forked workers); the existing DynamoDB conditional write then elects one prober across threads and processes with no protocol change. The in-memory failure/success counters and observed-state map are now guarded by a lock, with threshold crossings detected atomically so a trip is persisted exactly once. Persistence settings are keyed per circuit name instead of living as shared instance attributes, and the local cache no longer raises into the protected call on concurrent expiry. * test(circuit_breaker): cover losing the expired-lease probe takeover election The takeover's failure arm was untested: when another environment wins the conditional election, the caller must get the open-circuit response and the protected function must not run. * fix(circuit_breaker): address review feedback - Make the counter race test catch a missing lock: park readers mid-increment so an unsynchronized read-modify-write deterministically loses updates (fails 10/10 unlocked, passes 10/10 locked) - Document that on_circuit_open and on_transition callbacks can run concurrently and must be thread-safe - Use dict.get's default instead of `or` for the per-circuit settings lookup * fix(circuit_breaker): avoid LRUDict.pop when evicting expired cache entries - On Python 3.10, OrderedDict.pop re-enters the subclass __getitem__ after detaching the linked-list node, so LRUDict.pop raises KeyError for a present key and corrupts the dict (fixed in CPython 3.11) — this failed 14 tests on the 3.10 CI job only - Evict with a guarded del instead, which never calls subclass hooks; the surrounding lock already makes the get-then-delete atomic, and the try/except keeps the never-raise-into-the-protected-call contract explicit --- .../utilities/circuit_breaker_alpha/base.py | 82 +++++-- .../circuit_breaker_alpha/persistence/base.py | 104 +++++--- .../persistence/record.py | 3 +- docs/utilities/circuit_breaker.md | 14 ++ .../circuit_breaker_alpha/conftest.py | 102 ++++---- .../test_circuit_breaker.py | 232 ++++++++++++++++++ .../test_dynamodb_persistence.py | 1 - 7 files changed, 433 insertions(+), 105 deletions(-) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py index b4f66b98dc8..88fcedf61fe 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py @@ -10,6 +10,8 @@ import datetime import logging +import os +import threading import uuid from typing import TYPE_CHECKING, Any @@ -37,8 +39,31 @@ # recovered), so stale local failure streaks can be invalidated. _LAST_OBSERVED_STATE: dict[str, CircuitState] = {} -# Stable per-environment identifier used to claim the half-open probe lock. -_ENVIRONMENT_ID = uuid.uuid4().hex +# Guards the three dicts above. Increments are read-modify-write and a threshold +# crossing must be observed by exactly one thread, so every access goes through this +# lock. Held only while mutating the dicts, never across persistence writes or user +# callbacks. +_COUNTERS_LOCK = threading.Lock() + +# Identifier used to claim the half-open probe lock, unique per thread so the store's +# conditional election picks a single prober across threads as well as processes. +_PROBE_OWNER = threading.local() + + +def _probe_owner_id() -> str: + """ + Return this thread's stable probe-owner identifier, minting it on first use. + + A uuid in thread-local storage rather than ``threading.get_ident()``: the OS reuses + thread ids, and a recycled id would let an unrelated thread pass the owner check and + probe alongside the real owner. The pid check re-mints the id in forked children, + which inherit the forking thread's local storage. + """ + pid = os.getpid() + if getattr(_PROBE_OWNER, "pid", None) != pid: + _PROBE_OWNER.id = f"{pid}#{uuid.uuid4().hex}" + _PROBE_OWNER.pid = pid + return _PROBE_OWNER.id class CircuitBreakerHandler: @@ -111,32 +136,35 @@ def handle(self) -> Any: # If we previously observed a non-CLOSED state and the circuit is now back to # CLOSED, another environment completed the recovery cycle. Reset local counters # so a stale partial failure streak doesn't immediately re-trip the circuit. - prev = _LAST_OBSERVED_STATE.get(self.name) - if prev is not None and prev != CircuitState.CLOSED: - _LOCAL_FAILURES[self.name] = 0 - _LAST_OBSERVED_STATE[self.name] = CircuitState.CLOSED + with _COUNTERS_LOCK: + prev = _LAST_OBSERVED_STATE.get(self.name) + if prev is not None and prev != CircuitState.CLOSED: + _LOCAL_FAILURES[self.name] = 0 + _LAST_OBSERVED_STATE[self.name] = CircuitState.CLOSED return self._call_closed() if record.state == CircuitState.OPEN: - _LAST_OBSERVED_STATE[self.name] = CircuitState.OPEN + with _COUNTERS_LOCK: + _LAST_OBSERVED_STATE[self.name] = CircuitState.OPEN # ``opened_at`` may legitimately be 0 (epoch); treat only None as missing. opened_at = record.opened_at if record.opened_at is not None else self._now() if self._now() >= opened_at + self.config.recovery_timeout: # Recovery window elapsed: try to become the single prober. - if self.persistence_store.try_acquire_half_open(self.name, _ENVIRONMENT_ID, opened_at): + if self.persistence_store.try_acquire_half_open(self.name, _probe_owner_id(), opened_at): self._notify(CircuitState.OPEN, CircuitState.HALF_OPEN, opened_at=opened_at) return self._call_probe() return self._open_response(record.to_circuit_info()) - # HALF_OPEN: only the environment that owns the probe lock runs. - _LAST_OBSERVED_STATE[self.name] = CircuitState.HALF_OPEN - if record.half_open_owner == _ENVIRONMENT_ID: + # HALF_OPEN: only the thread that owns the probe lock runs. + with _COUNTERS_LOCK: + _LAST_OBSERVED_STATE[self.name] = CircuitState.HALF_OPEN + if record.half_open_owner == _probe_owner_id(): return self._call_probe() # If the probe lease has expired (owner recycled mid-probe), take over. if record.probe_lease_expiry is not None and self._now() >= record.probe_lease_expiry: logger.debug("Circuit '%s' probe lease expired; attempting takeover.", self.name) - if self.persistence_store.try_acquire_half_open(self.name, _ENVIRONMENT_ID, record.opened_at or 0): + if self.persistence_store.try_acquire_half_open(self.name, _probe_owner_id(), record.opened_at or 0): return self._call_probe() return self._open_response(record.to_circuit_info()) @@ -148,9 +176,14 @@ def _call_closed(self) -> Any: except Exception as exc: if not self.config.counts_as_failure(exc): raise - failures = _LOCAL_FAILURES.get(self.name, 0) + 1 - _LOCAL_FAILURES[self.name] = failures - if failures >= self.config.failure_threshold: + # Increment and reset atomically so exactly one thread observes the threshold + # crossing; racing threads would otherwise lose increments (tripping late) or + # each persist the same transition. + with _COUNTERS_LOCK: + failures = _LOCAL_FAILURES.get(self.name, 0) + 1 + tripped = failures >= self.config.failure_threshold + _LOCAL_FAILURES[self.name] = 0 if tripped else failures + if tripped: logger.debug("Circuit '%s' tripping CLOSED to OPEN after %d failures.", self.name, failures) opened_at = self._now() self._safe_persist( @@ -159,11 +192,11 @@ def _call_closed(self) -> Any: failure_count=failures, opened_at=opened_at, ) - _LOCAL_FAILURES[self.name] = 0 self._notify(CircuitState.CLOSED, CircuitState.OPEN, opened_at=opened_at) raise else: - _LOCAL_FAILURES[self.name] = 0 + with _COUNTERS_LOCK: + _LOCAL_FAILURES[self.name] = 0 return result def _call_probe(self) -> Any: @@ -176,17 +209,20 @@ def _call_probe(self) -> Any: logger.debug("Circuit '%s' probe failed; reopening.", self.name) opened_at = self._now() self._safe_persist(self.persistence_store.save_reopen, self.name, opened_at=opened_at) - _LOCAL_SUCCESSES[self.name] = 0 + with _COUNTERS_LOCK: + _LOCAL_SUCCESSES[self.name] = 0 self._notify(CircuitState.HALF_OPEN, CircuitState.OPEN, opened_at=opened_at) raise else: - successes = _LOCAL_SUCCESSES.get(self.name, 0) + 1 - _LOCAL_SUCCESSES[self.name] = successes - if successes >= self.config.success_threshold: + with _COUNTERS_LOCK: + successes = _LOCAL_SUCCESSES.get(self.name, 0) + 1 + closed = successes >= self.config.success_threshold + _LOCAL_SUCCESSES[self.name] = 0 if closed else successes + if closed: + _LOCAL_FAILURES[self.name] = 0 + if closed: logger.debug("Circuit '%s' closing after %d probe successes.", self.name, successes) self._safe_persist(self.persistence_store.save_closed, self.name) - _LOCAL_SUCCESSES[self.name] = 0 - _LOCAL_FAILURES[self.name] = 0 self._notify(CircuitState.HALF_OPEN, CircuitState.CLOSED) return result diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py index f1dee4c745f..a4ca7e1985b 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py @@ -10,8 +10,9 @@ import datetime import logging +import threading from abc import ABC, abstractmethod -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, NamedTuple from aws_lambda_powertools.shared.cache_dict import LRUDict from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord @@ -32,6 +33,17 @@ PERSISTED_STATE_TTL_BUFFER = 3600 +class _CircuitSettings(NamedTuple): + """Per-circuit tunables the layer captures from :meth:`configure`.""" + + local_cache_max_age: int + recovery_timeout: int + + +# Fallback for direct layer use before configure() has run; mirrors CircuitBreakerConfig defaults. +_DEFAULT_SETTINGS = _CircuitSettings(local_cache_max_age=5, recovery_timeout=30) + + class CircuitBreakerExistingLockError(Exception): """Internal signal that a conditional half-open probe write lost the race.""" @@ -50,19 +62,26 @@ class CircuitBreakerPersistenceLayer(ABC): def __init__(self) -> None: """Initialize defaults; real configuration happens in :meth:`configure`.""" - self.circuit_name: str = "" - self.local_cache_max_age: int = 5 - self.recovery_timeout: int = 30 + # Per-circuit tunables, keyed by circuit name. One persistence instance is shared + # by every circuit (and thread) using the same store, so these must never live in + # plain instance attributes: circuits with different configs would stamp each + # other's TTL and probe lease. A plain dict, not an LRUDict: evicting a live + # circuit's settings would silently swap in the defaults (wrong lease and TTL), + # whereas evicting a cache entry below only costs a store re-read. + self._settings: dict[str, _CircuitSettings] = {} # Maps circuit name -> the unix timestamp the locally cached record goes stale. # Kept separate from the record's durable ``expiry_timestamp`` (the store TTL) so # the short in-memory freshness window is never mistaken for the long store TTL. self._cache: LRUDict = LRUDict(max_items=LOCAL_CACHE_MAX_ITEMS) + # One lock for both maps: LRUDict reorders entries even on reads, so unguarded + # concurrent access can corrupt it or raise. + self._lock = threading.Lock() def configure(self, config: CircuitBreakerConfig, circuit_name: str) -> None: """ - Bind the layer to a circuit and its configuration. + Bind a circuit's configuration to the layer. - Called once per invocation by the handler; the assignments are cheap and the + Called once per invocation by the handler; the assignment is cheap and the same persistence instance is reused across invocations within an environment. Parameters @@ -70,43 +89,59 @@ def configure(self, config: CircuitBreakerConfig, circuit_name: str) -> None: config : CircuitBreakerConfig Configuration providing the local cache TTL and recovery timeout. circuit_name : str - The circuit this layer instance serves. + The circuit these settings apply to. """ - self.circuit_name = circuit_name - self.local_cache_max_age = config.local_cache_max_age - self.recovery_timeout = config.recovery_timeout + with self._lock: + self._settings[circuit_name] = _CircuitSettings( + local_cache_max_age=config.local_cache_max_age, + recovery_timeout=config.recovery_timeout, + ) + + def _settings_for(self, name: str) -> _CircuitSettings: + """Return a circuit's configured settings, or the defaults if never configured.""" + with self._lock: + return self._settings.get(name, _DEFAULT_SETTINGS) # ------------------------------------------------------------------ cache def _cache_key(self, name: str) -> str: return name - def _durable_ttl(self) -> int: + def _durable_ttl(self, name: str) -> int: """ Compute the store TTL stamped on a persisted record. Sized to outlive a full recovery window so a live circuit is never reaped mid-cycle, while an abandoned circuit (no further writes) self-cleans soon after. """ - return int(datetime.datetime.now().timestamp()) + self.recovery_timeout + PERSISTED_STATE_TTL_BUFFER + now = int(datetime.datetime.now().timestamp()) + return now + self._settings_for(name).recovery_timeout + PERSISTED_STATE_TTL_BUFFER def _save_to_cache(self, record: CircuitStateRecord) -> None: """Cache a record locally with a short in-memory freshness window.""" - local_expiry = int(datetime.datetime.now().timestamp()) + self.local_cache_max_age - self._cache[self._cache_key(record.name)] = (local_expiry, record) + local_expiry = int(datetime.datetime.now().timestamp()) + self._settings_for(record.name).local_cache_max_age + with self._lock: + self._cache[self._cache_key(record.name)] = (local_expiry, record) def _retrieve_from_cache(self, name: str) -> CircuitStateRecord | None: """Return a cached record if present and still within its local freshness window.""" - cached = self._cache.get(self._cache_key(name)) - if cached is None: - return None - - local_expiry, record = cached - if int(datetime.datetime.now().timestamp()) >= local_expiry: - del self._cache[self._cache_key(name)] - return None - - return record + with self._lock: + cached = self._cache.get(self._cache_key(name)) + if cached is None: + return None + + local_expiry, record = cached + if int(datetime.datetime.now().timestamp()) >= local_expiry: + # Guarded del, not pop: on Python 3.10 OrderedDict.pop re-enters the + # subclass __getitem__ after detaching the node, so LRUDict.pop raises + # KeyError for a *present* key and corrupts the dict (fixed in 3.11). + try: + del self._cache[self._cache_key(name)] + except KeyError: + pass + return None + + return record # ------------------------------------------------------------- public API @@ -175,19 +210,19 @@ def save_open(self, name: str, failure_count: int, opened_at: int) -> None: state=CircuitState.OPEN, failure_count=failure_count, opened_at=opened_at, - expiry_timestamp=self._durable_ttl(), + expiry_timestamp=self._durable_ttl(name), ) self._put_record(record) self._save_to_cache(record) def try_acquire_half_open(self, name: str, owner: str, opened_at: int) -> bool: """ - Atomically elect a single environment to run the half-open probe. + Atomically elect a single worker to run the half-open probe. The conditional write succeeds only when the circuit is OPEN with no existing lock owner AND the ``opened_at`` matches what the caller observed (guards against stale eventually-consistent reads). A lease expiry is stamped so that if the - winning environment is recycled before completing the probe, others can take over + winning worker is recycled before completing the probe, others can take over once the lease lapses. Parameters @@ -195,25 +230,26 @@ def try_acquire_half_open(self, name: str, owner: str, opened_at: int) -> bool: name : str Circuit name. owner : str - Identifier of the environment attempting the probe. + Identifier of the worker (one thread in one execution environment) + attempting the probe. opened_at : int The ``opened_at`` the caller observed, kept stable across the transition. Returns ------- bool - ``True`` if this environment won the probe lock, ``False`` if another - environment already holds it. + ``True`` if this worker won the probe lock, ``False`` if another + worker already holds it. """ # Lease = recovery_timeout gives the probe a full cycle to complete. - probe_lease_expiry = int(datetime.datetime.now().timestamp()) + self.recovery_timeout + probe_lease_expiry = int(datetime.datetime.now().timestamp()) + self._settings_for(name).recovery_timeout record = CircuitStateRecord( name=name, state=CircuitState.HALF_OPEN, opened_at=opened_at, half_open_owner=owner, probe_lease_expiry=probe_lease_expiry, - expiry_timestamp=self._durable_ttl(), + expiry_timestamp=self._durable_ttl(name), ) try: self._put_record(record, condition="half_open", expected_opened_at=opened_at) @@ -228,7 +264,7 @@ def save_closed(self, name: str) -> None: name=name, state=CircuitState.CLOSED, failure_count=0, - expiry_timestamp=self._durable_ttl(), + expiry_timestamp=self._durable_ttl(name), ) self._update_record(record) self._save_to_cache(record) @@ -245,7 +281,7 @@ def save_reopen(self, name: str, opened_at: int) -> None: name=name, state=CircuitState.OPEN, opened_at=opened_at, - expiry_timestamp=self._durable_ttl(), + expiry_timestamp=self._durable_ttl(name), ) self._update_record(record) self._save_to_cache(record) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py index 71086c3c1a7..ec48737810f 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py +++ b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py @@ -30,7 +30,8 @@ class CircuitStateRecord: Unix timestamp (seconds) the circuit opened. Anchors the recovery timeout; ``None`` while closed. half_open_owner : str | None - Identifier of the execution environment that won the half-open probe lock, if any. + Identifier of the worker (one thread in one execution environment) that won the + half-open probe lock, if any. expiry_timestamp : int | None Unix timestamp (seconds) for the store's TTL attribute. """ diff --git a/docs/utilities/circuit_breaker.md b/docs/utilities/circuit_breaker.md index f83685862f0..b2117f7316b 100644 --- a/docs/utilities/circuit_breaker.md +++ b/docs/utilities/circuit_breaker.md @@ -20,6 +20,7 @@ The circuit breaker utility stops sending traffic to an unhealthy downstream dep * Hands rejected requests to an `on_circuit_open` callback so you decide what happens next (buffer, drop, return a cached value) * Tests recovery with an explicit half-open probe rather than blindly retrying everything at once * Shares circuit state across execution environments via Amazon DynamoDB +* Safe under concurrency: one half-open probe across all threads and execution environments, and synchronized failure counting * Keeps the healthy path write-free: failures are counted in memory and only persisted on a state transition ## Terminology @@ -182,6 +183,19 @@ Passing both raises `CircuitBreakerConfigError`. An exception that doesn't count After `recovery_timeout` seconds, the circuit moves to `HALF_OPEN` and elects a **single** execution environment (via a conditional DynamoDB write) to run a probe. If `success_threshold` consecutive probes succeed, the circuit closes; a single failing probe reopens it. This stops a thundering herd of every environment hammering a recovering backend at once. +!!! note "Thread safety" + The utility is safe to share across threads: within a multi-threaded environment the probe election picks a single + thread, so the single-prober guarantee spans threads as well as environments, and the in-memory failure counter is + synchronized. Single-threaded functions (the normal Lambda model) are unaffected. + + Probe ownership belongs to the thread that won the election. If that thread never runs the circuit again (for + example, a thread-per-request worker pool), recovery waits for the probe lease to expire before another thread or + environment takes over. + +!!! warning "Make your hooks thread-safe" + If your function runs multiple threads, `on_circuit_open` and `on_transition` callbacks can run concurrently + for the same circuit. Make them thread-safe. + ### State coordination across environments The consecutive-failure counter lives in memory per execution environment, so a healthy circuit performs **no writes**. Only when an environment reaches `failure_threshold` does it persist `OPEN`. The shared state is cached locally for `local_cache_max_age` seconds to avoid a read per invocation. A cache miss (cold start or expired entry) forces a read-through before routing. diff --git a/tests/functional/circuit_breaker_alpha/conftest.py b/tests/functional/circuit_breaker_alpha/conftest.py index e2c9fc4d0d8..297c088750b 100644 --- a/tests/functional/circuit_breaker_alpha/conftest.py +++ b/tests/functional/circuit_breaker_alpha/conftest.py @@ -1,5 +1,7 @@ from __future__ import annotations +import threading + import pytest import aws_lambda_powertools.utilities.circuit_breaker_alpha.base as base_module @@ -15,23 +17,29 @@ class FakePersistence(CircuitBreakerPersistenceLayer): """In-memory store for exercising the handler state machine without DynamoDB.""" + # Each DynamoDB operation is atomic, including the conditional put; the fake must be + # too, or threaded tests race inside the fake instead of the code under test. + # Class-level so store instances sharing a db (multi-environment tests) share it. + _db_lock = threading.Lock() + def __init__(self): self.db: dict[str, CircuitStateRecord] = {} super().__init__() def _get_record(self, name: str) -> CircuitStateRecord | None: - if name not in self.db: - return None - stored = self.db[name] - # Return a copy so the handler can't mutate stored state by reference. - return CircuitStateRecord( - name=stored.name, - state=stored.state, - failure_count=stored.failure_count, - opened_at=stored.opened_at, - half_open_owner=stored.half_open_owner, - probe_lease_expiry=stored.probe_lease_expiry, - ) + with self._db_lock: + if name not in self.db: + return None + stored = self.db[name] + # Return a copy so the handler can't mutate stored state by reference. + return CircuitStateRecord( + name=stored.name, + state=stored.state, + failure_count=stored.failure_count, + opened_at=stored.opened_at, + half_open_owner=stored.half_open_owner, + probe_lease_expiry=stored.probe_lease_expiry, + ) def _put_record( self, @@ -39,46 +47,48 @@ def _put_record( condition: str | None = None, expected_opened_at: int | None = None, ) -> None: - if condition == "half_open": - existing = self.db.get(record.name) - now = CircuitBreakerHandler._now() - - # Mirror the DynamoDB condition: two valid paths - # Path 1: state=OPEN AND no owner (AND opened_at matches if provided) - # Path 2: state=HALF_OPEN AND probe_lease_expiry <= now (lease takeover) - fresh_election_ok = existing is None or ( - existing.state == CircuitState.OPEN - and existing.half_open_owner is None - and (expected_opened_at is None or existing.opened_at == expected_opened_at) - ) - lease_takeover_ok = ( - existing is not None - and existing.state == CircuitState.HALF_OPEN - and existing.probe_lease_expiry is not None - and now >= existing.probe_lease_expiry - ) - - if not fresh_election_ok and not lease_takeover_ok: - raise CircuitBreakerExistingLockError - self.db[record.name] = record + with self._db_lock: + if condition == "half_open": + existing = self.db.get(record.name) + now = CircuitBreakerHandler._now() + + # Mirror the DynamoDB condition: two valid paths + # Path 1: state=OPEN AND no owner (AND opened_at matches if provided) + # Path 2: state=HALF_OPEN AND probe_lease_expiry <= now (lease takeover) + fresh_election_ok = existing is None or ( + existing.state == CircuitState.OPEN + and existing.half_open_owner is None + and (expected_opened_at is None or existing.opened_at == expected_opened_at) + ) + lease_takeover_ok = ( + existing is not None + and existing.state == CircuitState.HALF_OPEN + and existing.probe_lease_expiry is not None + and now >= existing.probe_lease_expiry + ) + + if not fresh_election_ok and not lease_takeover_ok: + raise CircuitBreakerExistingLockError + self.db[record.name] = record def _update_record(self, record: CircuitStateRecord) -> None: # Mirror DynamoDB UpdateItem semantics: a partial merge driven by which # attributes the backend actually writes, NOT a wholesale replace. This is # what exposes attributes the update path forgets to clear (e.g. a stale # half_open_owner left behind on reopen). - existing = self.db.get(record.name) - if existing is None: - self.db[record.name] = record - return - existing.state = record.state - existing.failure_count = record.failure_count - existing.expiry_timestamp = record.expiry_timestamp - # Leaving HALF_OPEN (close or reopen) always releases the probe-owner lock and - # probe lease; only opened_at differs between the two transitions. - existing.half_open_owner = None - existing.probe_lease_expiry = None - existing.opened_at = record.opened_at + with self._db_lock: + existing = self.db.get(record.name) + if existing is None: + self.db[record.name] = record + return + existing.state = record.state + existing.failure_count = record.failure_count + existing.expiry_timestamp = record.expiry_timestamp + # Leaving HALF_OPEN (close or reopen) always releases the probe-owner lock and + # probe lease; only opened_at differs between the two transitions. + existing.half_open_owner = None + existing.probe_lease_expiry = None + existing.opened_at = record.opened_at @pytest.fixture diff --git a/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py b/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py index 1227291ee66..8a6daf7c17f 100644 --- a/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py +++ b/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py @@ -1,5 +1,7 @@ from __future__ import annotations +import threading +import time import warnings import pytest @@ -529,6 +531,40 @@ def call(): call() +def test_half_open_expired_lease_lost_takeover_returns_open_response(store, now): + """Losing the takeover election must NOT probe: another thread/environment won + the conditional write between our expiry check and our acquire, so the call + has to get the open-circuit response — electing every candidate is exactly + the multi-prober bug the per-thread owner id exists to prevent.""" + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0) + + # A stranded probe with an expired lease, owned by someone else. + store.db["c"] = CircuitStateRecord( + name="c", + state=CircuitState.HALF_OPEN, + opened_at=now - 200, + half_open_owner="dead-env", + probe_lease_expiry=now - 10, # expired — takeover will be attempted + ) + + # The race's loser: the conditional election fails. + def lost_election(name, owner_id, opened_at): + return False + + store.try_acquire_half_open = lost_election + + protected_ran = {"value": False} + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + protected_ran["value"] = True + return "must not probe" + + with pytest.raises(CircuitBreakerOpenError): + call() + assert protected_ran["value"] is False + + def test_open_lost_election_returns_open_response(store, now): """Branch: try_acquire_half_open returns False (another env won the race).""" config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0) @@ -602,3 +638,199 @@ def test_error_with_details_formatting(): """Covers exceptions.py line 28 — __str__ with details.""" err = CircuitBreakerError("main message", "extra detail") assert str(err) == "main message - (extra detail)" + + +# --------------------------------------------------------------------------- thread safety (#8320) + + +def _run_in_threads(worker, count): + threads = [threading.Thread(target=worker) for _ in range(count)] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + + +def test_threads_elect_a_single_prober_on_recovery(store, now): + """Regression for #8320: after one thread wins the election, siblings must not also probe.""" + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60) + # success_threshold=2 keeps the circuit HALF_OPEN after the winning probe, so a + # late-reading loser can never legitimately run the function through a closed circuit. + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0) + probes = [] + open_responses = [] + barrier = threading.Barrier(8) + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + probes.append(threading.current_thread().name) + return "ok" + + def worker(): + barrier.wait(timeout=10) + try: + call() + except CircuitBreakerOpenError: + open_responses.append(threading.current_thread().name) + + _run_in_threads(worker, 8) + + assert len(probes) == 1, "exactly one thread must probe per recovery window" + assert len(open_responses) == 7, "every other thread must get the open response" + assert store.db["c"].state == CircuitState.HALF_OPEN + assert store.db["c"].half_open_owner is not None + + +class _RacyCounters(dict): + """Counter dict that yields between the read and the write of an increment. + + Without this, the GIL makes the unlocked read-modify-write effectively atomic + (the interpreter rarely switches threads inside those few bytecodes), so a + missing lock would still pass. Holding every reader mid-increment long enough + for its siblings to read the same stale value makes the lost update + deterministic: unlocked, all threads write back the same count and the + threshold is never reached. + """ + + def get(self, key, default=None): + value = super().get(key, default) + time.sleep(0.005) # park mid-increment so sibling threads read the same stale value + return value + + +def test_threads_trip_at_exactly_the_failure_threshold(store, monkeypatch): + """Racing increments must neither lose updates (tripping late) nor persist the trip twice.""" + monkeypatch.setattr(base_module, "_LOCAL_FAILURES", _RacyCounters()) + threads_count, threshold = 8, 5 + config = CircuitBreakerConfig(failure_threshold=threshold, local_cache_max_age=0) + barrier = threading.Barrier(threads_count) + siblings_done = threading.Event() + done_lock = threading.Lock() + finished = [] + save_open_counts = [] + original_save_open = store.save_open + + def blocking_save_open(name, failure_count, opened_at): + save_open_counts.append(failure_count) + if len(save_open_counts) > 1: + # A second persist is the bug itself; unblock immediately so it fails fast. + siblings_done.set() + # Park the tripping thread mid-persist until every sibling has recorded its + # failure. Code that resets the counter only after persisting lets the + # remaining threads cross the threshold too and persist the trip again. + siblings_done.wait(timeout=10) + original_save_open(name, failure_count=failure_count, opened_at=opened_at) + + store.save_open = blocking_save_open + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + # Hold every thread inside the protected call so all pass the CLOSED check + # before any failure is recorded, forcing the increments to race. + barrier.wait(timeout=10) + raise ConnectionError("downstream down") + + raised = [] + + def worker(): + try: + call() + except ConnectionError: + raised.append(threading.current_thread().name) + finally: + with done_lock: + finished.append(threading.current_thread().name) + if len(finished) == threads_count - 1: + # Only the tripping thread is still parked in the persist spy. + siblings_done.set() + + _run_in_threads(worker, threads_count) + + assert save_open_counts == [threshold], "the trip must be persisted exactly once, at the threshold" + assert store.db["c"].state == CircuitState.OPEN + assert len(raised) == threads_count + assert base_module._LOCAL_FAILURES["c"] == threads_count - threshold, "post-trip failures restart the streak" + + +def test_probe_ownership_is_per_thread_and_stable_across_invocations(store, now): + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60) + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0) + calls = [] + + @circuit_breaker(name="c", persistence_store=store, config=config) + def call(): + calls.append(threading.current_thread().name) + return "ok" + + # This thread wins the election; one more probe success is needed to close. + assert call() == "ok" + assert store.db["c"].state == CircuitState.HALF_OPEN + + # A sibling thread must not inherit ownership (it did when the id was per-process). + sibling_outcome = [] + + def sibling(): + try: + sibling_outcome.append(call()) + except CircuitBreakerOpenError: + sibling_outcome.append("rejected") + + _run_in_threads(sibling, 1) + assert sibling_outcome == ["rejected"] + + # The owner's identity must survive across invocations so it can finish the recovery; + # a per-handler or per-invocation id would strand the circuit until the lease expired. + assert call() == "ok" + assert store.db["c"].state == CircuitState.CLOSED + assert len(calls) == 2 + + +def test_single_probe_spans_environments_and_threads(store, now): + """The same election covers threads in one process and separate environments.""" + other_env = type(store)() + other_env.db = store.db + store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60) + config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0) + probes = [] + open_responses = [] + barrier = threading.Barrier(8) + + def protect(persistence): + @circuit_breaker(name="c", persistence_store=persistence, config=config) + def call(): + probes.append(threading.current_thread().name) + return "ok" + + return call + + calls = [protect(store), protect(other_env)] + + def worker(index): + env_call = calls[index % 2] + barrier.wait(timeout=10) + try: + env_call() + except CircuitBreakerOpenError: + open_responses.append(threading.current_thread().name) + + threads = [threading.Thread(target=worker, args=(index,)) for index in range(8)] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + + assert len(probes) == 1, "one probe across all threads of all environments" + assert len(open_responses) == 7 + + +def test_settings_are_kept_per_circuit_on_a_shared_layer(store, now): + """Configuring another circuit on the same layer must not stamp this one's probe lease.""" + store.configure(CircuitBreakerConfig(recovery_timeout=30, local_cache_max_age=0), circuit_name="a") + store.configure(CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0), circuit_name="b") + store.db["a"] = CircuitStateRecord(name="a", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60) + + assert store.try_acquire_half_open("a", "owner-1", now - 60) + + lease = store.db["a"].probe_lease_expiry + assert lease is not None + assert lease <= now + 30 + 2, "the lease must derive from circuit 'a' recovery_timeout, not 'b'" diff --git a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py index 9effa8cbafd..c395d663cad 100644 --- a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py +++ b/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py @@ -138,7 +138,6 @@ def test_save_open_item_contains_expiration_attribute(persistence): # the documented self-cleaning of abandoned circuits never happens. Capture the # actual PutItem params rather than asserting an exact (time-dependent) value. captured = {} - persistence.local_cache_max_age = 5 original_put = persistence.client.put_item From 8e8f6cbbbd6cb83a6980ac06c265a150b2df33e5 Mon Sep 17 00:00:00 2001 From: Emanuele Giaquinta Date: Tue, 7 Jul 2026 13:14:18 +0300 Subject: [PATCH 27/76] fix(parser): fix DynamoDB Stream Lambda invocation record model (#8321) * fix(parser): fix DynamoDB Stream Lambda invocation record model The responseContext.functionError field is null if the error did not occur during function execution. * chore: fix ruff B905 errors * chore: bump ruff target version to 3.10 Also add temporary ignores for some upgrade rules, as there are 1017 corresponding errors. --------- Co-authored-by: Leandro Damascena --- .../events_appsync/appsync_events.py | 2 +- .../utilities/parser/models/dynamodb.py | 3 ++- ruff.toml | 6 ++++- .../test_bedrock_agent_function_event.py | 2 +- tests/unit/parser/_pydantic/test_dynamodb.py | 26 +++++++++++++++++-- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/aws_lambda_powertools/event_handler/events_appsync/appsync_events.py b/aws_lambda_powertools/event_handler/events_appsync/appsync_events.py index ee03db5c625..ad718cca104 100644 --- a/aws_lambda_powertools/event_handler/events_appsync/appsync_events.py +++ b/aws_lambda_powertools/event_handler/events_appsync/appsync_events.py @@ -321,7 +321,7 @@ async def _call_publish_event_async_resolver( if isinstance(ret, Exception) else {"id": e.get("id"), "payload": ret} ) - for e, ret in zip(self.current_event.events, results) + for e, ret in zip(self.current_event.events, results, strict=True) ], ) diff --git a/aws_lambda_powertools/utilities/parser/models/dynamodb.py b/aws_lambda_powertools/utilities/parser/models/dynamodb.py index d6091d32d7a..595e19068e3 100644 --- a/aws_lambda_powertools/utilities/parser/models/dynamodb.py +++ b/aws_lambda_powertools/utilities/parser/models/dynamodb.py @@ -175,7 +175,8 @@ class ResponseContext(BaseModel): description="The version of the Lambda executed", examples=["$LATEST"], ) - function_error: str = Field( + function_error: Optional[str] = Field( + default=None, description="", examples=["Unhandled"], ) diff --git a/ruff.toml b/ruff.toml index fa89816a7de..6761e206cdc 100644 --- a/ruff.toml +++ b/ruff.toml @@ -41,6 +41,10 @@ lint.ignore = [ "A005", "TC006", # https://docs.astral.sh/ruff/rules/runtime-cast-value/ "PLC0415", # https://docs.astral.sh/ruff/rules/import-outside-top-level/ + "UP006", + "UP007", + "UP035", + "UP045", ] # Exclude files and directories @@ -62,7 +66,7 @@ exclude = [ # Maximum line length line-length = 120 -target-version = "py38" +target-version = "py310" fix = true lint.fixable = ["I", "COM812", "W"] diff --git a/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py b/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py index e055c894604..2ff81a21bb8 100644 --- a/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py +++ b/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py @@ -32,7 +32,7 @@ def test_bedrock_agent_function_event(): raw_parameters = raw_event["parameters"] assert len(parameters) == len(raw_parameters) - for param, raw_param in zip(parameters, raw_parameters): + for param, raw_param in zip(parameters, raw_parameters, strict=True): assert param.name == raw_param["name"] assert param.type == raw_param["type"] assert param.value == raw_param["value"] diff --git a/tests/unit/parser/_pydantic/test_dynamodb.py b/tests/unit/parser/_pydantic/test_dynamodb.py index 13ee5610e6d..f21f6d717c3 100644 --- a/tests/unit/parser/_pydantic/test_dynamodb.py +++ b/tests/unit/parser/_pydantic/test_dynamodb.py @@ -1,3 +1,5 @@ +from typing import Any + import pytest from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse @@ -86,8 +88,26 @@ def test_validate_event_does_not_conform_with_model(): parse(event=raw_event, model=MyDynamoBusiness, envelope=envelopes.DynamoDBStreamEnvelope) -def test_dynamo_db_stream_lambda_invocation_event(): +@pytest.mark.parametrize( + "response_context", + [ + pytest.param( + {"statusCode": 200, "executedVersion": "$LATEST"}, + id="without function error", + ), + pytest.param( + {"statusCode": 200, "executedVersion": "$LATEST", "functionError": None}, + id="with null function error", + ), + pytest.param( + {"statusCode": 200, "executedVersion": "$LATEST", "functionError": "Unhandled"}, + id="with function error", + ), + ], +) +def test_dynamo_db_stream_lambda_invocation_event(response_context: dict[str, Any]): raw_event = load_event("dynamoStreamLambdaInvocationEvent.json") + raw_event["responseContext"] = response_context parsed_event: DynamoDBStreamLambdaOnFailureDestinationModel = parse( event=raw_event, model=DynamoDBStreamLambdaOnFailureDestinationModel, @@ -111,6 +131,8 @@ def test_dynamo_db_stream_lambda_invocation_event(): ) assert parsed_event.ddb_stream_batch_info.stream_arn == raw_event["DDBStreamBatchInfo"]["streamArn"] assert parsed_event.request_context.model_dump(by_alias=True) == raw_event["requestContext"] - assert parsed_event.response_context.model_dump(by_alias=True) == raw_event["responseContext"] + assert parsed_event.response_context.status_code == response_context["statusCode"] + assert parsed_event.response_context.executed_version == response_context["executedVersion"] + assert parsed_event.response_context.function_error == response_context.get("functionError") assert parsed_event.timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") == raw_event["timestamp"] assert parsed_event.version == raw_event["version"] From 1f5e1f18abc2494832b0c764cc852d1d125c5ca1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 12:21:11 +0200 Subject: [PATCH 28/76] chore(deps): bump the github-actions group across 1 directory with 8 updates (#8327) Bumps the github-actions group with 8 updates in the / directory: | Package | From | To | | --- | --- | --- | | [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) | `6.2.0` | `6.2.1` | | [actions/setup-go](https://github.com/actions/setup-go) | `6.4.0` | `6.5.0` | | [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `2.2.4` | `4.36.3` | | [actions/setup-python](https://github.com/actions/setup-python) | `6.2.0` | `6.3.0` | | [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `4.1.0` | `4.2.0` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.1.0` | `4.2.0` | | [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) | `7.4.0` | `7.5.1` | | [zgosalvez/github-actions-ensure-sha-pinned-actions](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions) | `5.0.4` | `5.0.5` | Updates `aws-actions/configure-aws-credentials` from 6.2.0 to 6.2.1 - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/e7f100cf4c008499ea8adda475de1042d6975c7b...254c19bd240aabef8777f48595e9d2d7b972184b) Updates `actions/setup-go` from 6.4.0 to 6.5.0 - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/4a3601121dd01d1626a1e23e37211e3254c1c06c...924ae3a1cded613372ab5595356fb5720e22ba16) Updates `github/codeql-action/upload-sarif` from 2.2.4 to 4.36.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/17573ee1cc1b9d061760f3a006fc4aac4f944fd5...54f647b7e1bb85c95cddabcd46b0c578ec92bc1a) Updates `actions/setup-python` from 6.2.0 to 6.3.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/a309ff8b426b58ec0e2a45f0f869d46889d02405...ece7cb06caefa5fff74198d8649806c4678c61a1) Updates `docker/setup-qemu-action` from 4.1.0 to 4.2.0 - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/06116385d9baf250c9f4dcb4858b16962ea869c3...96fe6ef7f33517b61c61be40b68a1882f3264fb8) Updates `docker/setup-buildx-action` from 4.1.0 to 4.2.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5...bb05f3f5519dd87d3ba754cc423b652a5edd6d2c) Updates `release-drafter/release-drafter` from 7.4.0 to 7.5.1 - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/ed4bc48ec97379be2258e7b7ac2624a3e26ab809...4d75298e00d9e34c483e5ff8c68d0ea1c1940c1e) Updates `zgosalvez/github-actions-ensure-sha-pinned-actions` from 5.0.4 to 5.0.5 - [Release notes](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions/releases) - [Commits](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions/compare/ca46236c6ce584ae24bc6283ba8dcf4b3ec8a066...3db98c0363e2fa5df3e1c4c471777a7c10b24cc9) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 6.2.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/setup-go dependency-version: 6.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: github/codeql-action/upload-sarif dependency-version: 4.36.3 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/setup-python dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: docker/setup-qemu-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: docker/setup-buildx-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: release-drafter/release-drafter dependency-version: 7.5.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: zgosalvez/github-actions-ensure-sha-pinned-actions dependency-version: 5.0.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .github/workflows/bootstrap_region.yml | 6 +++--- .github/workflows/layer_govcloud.yml | 6 +++--- .github/workflows/layer_govcloud_python313.yml | 6 +++--- .github/workflows/layer_govcloud_verify.yml | 6 +++--- .github/workflows/layers_partition_verify.yml | 4 ++-- .github/workflows/layers_partitions.yml | 4 ++-- .github/workflows/ossf_scorecard.yml | 2 +- .github/workflows/pre-release.yml | 4 ++-- .github/workflows/publish_v3_layer.yml | 6 +++--- .github/workflows/quality_check.yml | 2 +- .github/workflows/quality_check_docs.yml | 2 +- .github/workflows/quality_code_cdk_constructor.yml | 6 +++--- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release-v3.yml | 4 ++-- .github/workflows/reusable_deploy_v3_layer_stack.yml | 4 ++-- .github/workflows/reusable_deploy_v3_sar.yml | 4 ++-- .github/workflows/reusable_publish_docs.yml | 4 ++-- .github/workflows/run-e2e-tests.yml | 4 ++-- .github/workflows/secure_workflows.yml | 2 +- .github/workflows/update_ssm.yml | 2 +- 20 files changed, 40 insertions(+), 40 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index c464909367b..5f4ed90a940 100644 --- a/.github/workflows/bootstrap_region.yml +++ b/.github/workflows/bootstrap_region.yml @@ -55,7 +55,7 @@ jobs: uses: aws-powertools/actions/.github/actions/cached-node-modules@4bf64a4072489399fbf39b78f558eeeed6767189 - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b with: aws-region: ${{ inputs.region }} role-to-assume: ${{ secrets.REGION_IAM_ROLE }} @@ -96,14 +96,14 @@ jobs: steps: - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: aws-region: us-east-1 role-to-assume: ${{ secrets.REGION_IAM_ROLE }} mask-aws-account-id: true - id: go-setup name: Setup Go - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: go-version: '>=1.23.0' - id: go-env diff --git a/.github/workflows/layer_govcloud.yml b/.github/workflows/layer_govcloud.yml index 97796a9f896..0c7d51bc72c 100644 --- a/.github/workflows/layer_govcloud.yml +++ b/.github/workflows/layer_govcloud.yml @@ -60,7 +60,7 @@ jobs: environment: Prod (Readonly) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -118,7 +118,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 @@ -188,7 +188,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-west-1 diff --git a/.github/workflows/layer_govcloud_python313.yml b/.github/workflows/layer_govcloud_python313.yml index 9128fd9a264..9d09050d613 100644 --- a/.github/workflows/layer_govcloud_python313.yml +++ b/.github/workflows/layer_govcloud_python313.yml @@ -55,7 +55,7 @@ jobs: environment: Prod (Readonly) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -108,7 +108,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 @@ -173,7 +173,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-west-1 diff --git a/.github/workflows/layer_govcloud_verify.yml b/.github/workflows/layer_govcloud_verify.yml index 051a567463c..23cccc7b9d5 100644 --- a/.github/workflows/layer_govcloud_verify.yml +++ b/.github/workflows/layer_govcloud_verify.yml @@ -40,7 +40,7 @@ jobs: environment: Prod (Readonly) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -71,7 +71,7 @@ jobs: environment: GovCloud Prod (East) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 @@ -103,7 +103,7 @@ jobs: environment: GovCloud Prod (West) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 diff --git a/.github/workflows/layers_partition_verify.yml b/.github/workflows/layers_partition_verify.yml index 3cb8e68c3c7..c3701ca6179 100644 --- a/.github/workflows/layers_partition_verify.yml +++ b/.github/workflows/layers_partition_verify.yml @@ -88,7 +88,7 @@ jobs: - x86_64 steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -138,7 +138,7 @@ jobs: run: | echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT" - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }} aws-region: ${{ matrix.region}} diff --git a/.github/workflows/layers_partitions.yml b/.github/workflows/layers_partitions.yml index 515f7071e40..31818c7d61d 100644 --- a/.github/workflows/layers_partitions.yml +++ b/.github/workflows/layers_partitions.yml @@ -85,7 +85,7 @@ jobs: - x86_64 steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -150,7 +150,7 @@ jobs: run: | echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT" - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }} aws-region: ${{ matrix.region}} diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index cb8c8880690..eecaa99f832 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -43,6 +43,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4 + uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3 with: sarif_file: results.sarif diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 776cb86673c..e58c2d0c569 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -115,7 +115,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.14" cache: "poetry" @@ -153,7 +153,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.14" cache: "poetry" diff --git a/.github/workflows/publish_v3_layer.yml b/.github/workflows/publish_v3_layer.yml index c73de63808d..41bea487d57 100644 --- a/.github/workflows/publish_v3_layer.yml +++ b/.github/workflows/publish_v3_layer.yml @@ -127,7 +127,7 @@ jobs: with: node-version: "18.20.4" - name: Setup python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} cache: "pip" @@ -139,14 +139,14 @@ jobs: pip install --require-hashes -r requirements.txt - name: Set up QEMU - uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 + uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 with: platforms: arm64 # NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM) - name: Set up Docker Buildx id: builder - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 with: driver: docker platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml index 938b44de268..f894553b79a 100644 --- a/.github/workflows/quality_check.yml +++ b/.github/workflows/quality_check.yml @@ -56,7 +56,7 @@ jobs: - name: Install poetry run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/quality_check_docs.yml b/.github/workflows/quality_check_docs.yml index af2648a67f5..afc3ed9f05a 100644 --- a/.github/workflows/quality_check_docs.yml +++ b/.github/workflows/quality_check_docs.yml @@ -37,7 +37,7 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: 3.14 - name: Install doc generation dependencies diff --git a/.github/workflows/quality_code_cdk_constructor.yml b/.github/workflows/quality_code_cdk_constructor.yml index c7d6b308fe8..5982d7dc1bf 100644 --- a/.github/workflows/quality_code_cdk_constructor.yml +++ b/.github/workflows/quality_code_cdk_constructor.yml @@ -46,18 +46,18 @@ jobs: - name: Install poetry run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} cache: "poetry" - name: Set up QEMU - uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 + uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 with: platforms: arm64 # NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM) - name: Set up Docker Buildx id: builder - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 with: driver: docker platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 038ac4c9ad7..ea31f077e5c 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -27,4 +27,4 @@ jobs: permissions: contents: write # create release in draft mode steps: - - uses: release-drafter/release-drafter@ed4bc48ec97379be2258e7b7ac2624a3e26ab809 # v7.4.0 + - uses: release-drafter/release-drafter@4d75298e00d9e34c483e5ff8c68d0ea1c1940c1e # v7.5.1 diff --git a/.github/workflows/release-v3.yml b/.github/workflows/release-v3.yml index 7bbeae80402..f5588fad0ae 100644 --- a/.github/workflows/release-v3.yml +++ b/.github/workflows/release-v3.yml @@ -140,7 +140,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.14" cache: "poetry" @@ -178,7 +178,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.14" cache: "poetry" diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index 01cd7048f22..b6e2840e082 100644 --- a/.github/workflows/reusable_deploy_v3_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v3_layer_stack.yml @@ -157,7 +157,7 @@ jobs: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 pipx inject poetry git+https://github.com/python-poetry/poetry-plugin-export@8c83d26603ca94f2e203bfded7b6d7f530960e06 # v1.8.0 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} @@ -167,7 +167,7 @@ jobs: with: node-version: "18.20.4" - name: Setup python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} cache: "pip" diff --git a/.github/workflows/reusable_deploy_v3_sar.yml b/.github/workflows/reusable_deploy_v3_sar.yml index 988acca3e7d..ba2af3bb190 100644 --- a/.github/workflows/reusable_deploy_v3_sar.yml +++ b/.github/workflows/reusable_deploy_v3_sar.yml @@ -87,7 +87,7 @@ jobs: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} @@ -98,7 +98,7 @@ jobs: # we then jump to our specific SAR Account with the correctly scoped IAM Role # this allows us to have a single trail when a release occurs for a given layer (beta+prod+SAR beta+SAR prod) - name: AWS credentials SAR role - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 id: aws-credentials-sar-role with: aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 474b0fb7e74..27b4b9642b0 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -47,7 +47,7 @@ jobs: fetch-depth: 0 ref: ${{ inputs.git_ref }} - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" - name: Install doc generation dependencies @@ -68,7 +68,7 @@ jobs: env: BRANCH: ${{ inputs.git_ref }} - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 6a2c4d4abec..10ac5126934 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -56,7 +56,7 @@ jobs: - name: Install poetry run: pipx install poetry - name: "Use Python" - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.version }} architecture: "x64" @@ -72,7 +72,7 @@ jobs: - name: Install dependencies run: make dev-quality-code - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: role-to-assume: ${{ secrets.AWS_TEST_ROLE_ARN }} aws-region: ${{ env.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index 766ac964c3d..00f0b3069a3 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Ensure 3rd party workflows have SHA pinned - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@ca46236c6ce584ae24bc6283ba8dcf4b3ec8a066 # v5.0.4 + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@3db98c0363e2fa5df3e1c4c471777a7c10b24cc9 # v5.0.5 with: allowlist: | slsa-framework/slsa-github-generator diff --git a/.github/workflows/update_ssm.yml b/.github/workflows/update_ssm.yml index e8c89c4141f..056f2674d88 100644 --- a/.github/workflows/update_ssm.yml +++ b/.github/workflows/update_ssm.yml @@ -89,7 +89,7 @@ jobs: run: | echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT" - id: creds - uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0 + uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets[format('{0}', steps.transform.outputs.CONVERTED_REGION)] }} From 37641b66614532e4c7ed12512b8b626fe84ad514 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:57:59 +0100 Subject: [PATCH 29/76] chore(deps-dev): bump aws-cdk from 2.1128.1 to 2.1129.0 in the aws-cdk group (#8324) chore(deps-dev): bump aws-cdk in the aws-cdk group Bumps the aws-cdk group with 1 update: [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `aws-cdk` from 2.1128.1 to 2.1129.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1129.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1129.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 23e2c4a7e90..e8b56763f3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,13 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1128.1" + "aws-cdk": "^2.1129.0" } }, "node_modules/aws-cdk": { - "version": "2.1128.1", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1128.1.tgz", - "integrity": "sha512-y9OHn5/BOcIiq409vPvpypMIr7/8M1ScFe8IkFMSCN1/GI/5c73fQ4pfzNq+VDkj86T5zxs7BQ1qU2lQQytdXA==", + "version": "2.1129.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1129.0.tgz", + "integrity": "sha512-M0EWbjeKW+baUsirjtKuWh7w/9dPxF8taEi2hqo9ecCjGeQxV1dzyosJf+caR3Jh7dFyyT3J8zEtRb/cU971Rw==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 1c550b6bddb..b43ac00bdbd 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1128.1" + "aws-cdk": "^2.1129.0" } } From 2a014a36a5f5c806aa8e1a3611ce63b1abb8e64d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 11:06:04 +0100 Subject: [PATCH 30/76] chore(deps-dev): bump types-python-dateutil from 2.9.0.20260508 to 2.9.0.20260518 (#8311) chore(deps-dev): bump types-python-dateutil Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.9.0.20260508 to 2.9.0.20260518. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-python-dateutil dependency-version: 2.9.0.20260518 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 551423d06c1..e056cbc035c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4742,14 +4742,14 @@ types-cffi = "*" [[package]] name = "types-python-dateutil" -version = "2.9.0.20260508" +version = "2.9.0.20260518" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_python_dateutil-2.9.0.20260508-py3-none-any.whl", hash = "sha256:bfc6fd2d81aa86e5ac97206a64304f6bd247426eedbca9b98619bbc48c6a1c10"}, - {file = "types_python_dateutil-2.9.0.20260508.tar.gz", hash = "sha256:596a6d63d81f587bf04c8254fb78df9d2344e915ce67948d7400512e3a6206d5"}, + {file = "types_python_dateutil-2.9.0.20260518-py3-none-any.whl", hash = "sha256:d6a9c5bd0de61460c8fdef8ab2b400f956a1a1075cce08d4e2b4434e478c50b8"}, + {file = "types_python_dateutil-2.9.0.20260518.tar.gz", hash = "sha256:51f02dc03b61c7f6a07df45797d4dfe8a1aa47f0b7db9ad89f6fd3a1a70e1b51"}, ] [[package]] From 6b41dc8581b1dc48104d11adfc3665184cd284d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 11:55:24 +0100 Subject: [PATCH 31/76] chore(deps): bump protobuf from 7.34.1 to 7.35.1 (#8312) Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 7.34.1 to 7.35.1. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: protobuf dependency-version: 7.35.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index e056cbc035c..f2233d08b79 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3364,20 +3364,20 @@ testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "protobuf" -version = "7.34.1" +version = "7.35.1" description = "" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7"}, - {file = "protobuf-7.34.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b"}, - {file = "protobuf-7.34.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a"}, - {file = "protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4"}, - {file = "protobuf-7.34.1-cp310-abi3-win32.whl", hash = "sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a"}, - {file = "protobuf-7.34.1-cp310-abi3-win_amd64.whl", hash = "sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c"}, - {file = "protobuf-7.34.1-py3-none-any.whl", hash = "sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11"}, - {file = "protobuf-7.34.1.tar.gz", hash = "sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280"}, + {file = "protobuf-7.35.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6"}, + {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799"}, + {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4"}, + {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4"}, + {file = "protobuf-7.35.1-cp310-abi3-win32.whl", hash = "sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30"}, + {file = "protobuf-7.35.1-cp310-abi3-win_amd64.whl", hash = "sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87"}, + {file = "protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9"}, + {file = "protobuf-7.35.1.tar.gz", hash = "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a"}, ] markers = {main = "extra == \"kafka-consumer-protobuf\" or extra == \"valkey\""} From 32267101136cc8976423b5bdaea10cfb166a87c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 11:57:22 +0100 Subject: [PATCH 32/76] chore(deps-dev): bump filelock from 3.29.0 to 3.29.7 (#8314) Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.29.0 to 3.29.7. - [Release notes](https://github.com/tox-dev/py-filelock/releases) - [Changelog](https://github.com/tox-dev/filelock/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/py-filelock/compare/3.29.0...3.29.7) --- updated-dependencies: - dependency-name: filelock dependency-version: 3.29.4 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index f2233d08b79..b61ece1536e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1878,14 +1878,14 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "filelock" -version = "3.29.0" +version = "3.29.7" description = "A platform independent file lock." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258"}, - {file = "filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90"}, + {file = "filelock-3.29.7-py3-none-any.whl", hash = "sha256:987db6f789a3a2a59f55081801b2b3697cb97e2a736b5f1a9e99b559285fbc51"}, + {file = "filelock-3.29.7.tar.gz", hash = "sha256:5b481979797ae69e72f0b389d89a80bdd585c260c5b3f1fb9c0a5ba9bb3f195d"}, ] [[package]] From 2fd212d286d420145bca8d683a0baa092c683942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:00:06 +0100 Subject: [PATCH 33/76] chore(deps-dev): bump requests from 2.33.1 to 2.34.2 (#8313) Bumps [requests](https://github.com/psf/requests) from 2.33.1 to 2.34.2. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.33.1...v2.34.2) --- updated-dependencies: - dependency-name: requests dependency-version: 2.34.2 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index b61ece1536e..1971bc7a560 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4141,14 +4141,14 @@ files = [ [[package]] name = "requests" -version = "2.33.1" +version = "2.34.2" description = "Python HTTP for Humans." optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}, - {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}, + {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, + {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, ] markers = {main = "extra == \"datadog\""} From 8a0ae64677254351f6cb0f0f7d0d726482763c3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 09:24:03 +0200 Subject: [PATCH 34/76] chore(deps-dev): bump soupsieve from 2.7 to 2.8.4 (#8329) Bumps [soupsieve](https://github.com/facelessuser/soupsieve) from 2.7 to 2.8.4. - [Release notes](https://github.com/facelessuser/soupsieve/releases) - [Commits](https://github.com/facelessuser/soupsieve/compare/2.7...2.8.4) --- updated-dependencies: - dependency-name: soupsieve dependency-version: 2.8.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1971bc7a560..2faf20816d1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4487,14 +4487,14 @@ files = [ [[package]] name = "soupsieve" -version = "2.8.3" +version = "2.8.4" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95"}, - {file = "soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349"}, + {file = "soupsieve-2.8.4-py3-none-any.whl", hash = "sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65"}, + {file = "soupsieve-2.8.4.tar.gz", hash = "sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e"}, ] [[package]] From dd8918f5d798c954d1454e98dd4fa4e57c813b10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 09:25:52 +0200 Subject: [PATCH 35/76] chore(deps): bump soupsieve from 2.7 to 2.8.4 in /docs (#8328) Bumps [soupsieve](https://github.com/facelessuser/soupsieve) from 2.7 to 2.8.4. - [Release notes](https://github.com/facelessuser/soupsieve/releases) - [Commits](https://github.com/facelessuser/soupsieve/compare/2.7...2.8.4) --- updated-dependencies: - dependency-name: soupsieve dependency-version: 2.8.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrea Amorosi --- docs/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index a7b731a7d5a..a4ad8668c0f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -411,9 +411,9 @@ smmap==5.0.2 \ --hash=sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5 \ --hash=sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e # via gitdb -soupsieve==2.7 \ - --hash=sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4 \ - --hash=sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a +soupsieve==2.8.4 \ + --hash=sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e \ + --hash=sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65 # via beautifulsoup4 typing-extensions==4.14.0 \ --hash=sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4 \ From a9fce32b0020aa4f9e559a909b27b2639cf15fd5 Mon Sep 17 00:00:00 2001 From: Tamas Stenczel <39164540+stenczelt@users.noreply.github.com> Date: Sun, 12 Jul 2026 10:31:16 +0100 Subject: [PATCH 36/76] fix(event_source): mypy strict mode compliance (#8332) * protocol & casting * remove redundant casting from kinesis firehose response exception example --- .../utilities/data_classes/event_source.py | 29 +++++++++++++++---- .../kinesis_firehose_response_exception.py | 5 ++-- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/event_source.py b/aws_lambda_powertools/utilities/data_classes/event_source.py index 6096e3ae7bc..58c8be968f5 100644 --- a/aws_lambda_powertools/utilities/data_classes/event_source.py +++ b/aws_lambda_powertools/utilities/data_classes/event_source.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Protocol, TypeVar, cast from aws_lambda_powertools.middleware_factory import lambda_handler_decorator @@ -10,14 +10,30 @@ from aws_lambda_powertools.utilities.data_classes.common import DictWrapper from aws_lambda_powertools.utilities.typing import LambdaContext +DataClassT = TypeVar("DataClassT", bound="DictWrapper") +OutputT = TypeVar("OutputT") + + +class _EventSourceDecorator(Protocol): + """Annotation of event_source, that lambda_handler_decorator erases at runtime.""" + + def __call__( + self, + *, + data_class: type[DataClassT], + ) -> Callable[ + [Callable[[DataClassT, LambdaContext], OutputT]], + Callable[[dict[str, Any], LambdaContext], OutputT], + ]: ... + @lambda_handler_decorator -def event_source( - handler: Callable[[Any, LambdaContext], Any], +def _event_source( + handler: Callable[[Any, LambdaContext], OutputT], event: dict[str, Any], context: LambdaContext, - data_class: type[DictWrapper], -): + data_class: type[DataClassT], +) -> OutputT: """Middleware to create an instance of the passed in event source data class Parameters @@ -43,3 +59,6 @@ def handler(event: S3Event, context): return {"key": event.object_key} """ return handler(data_class(event), context) + + +event_source = cast(_EventSourceDecorator, _event_source) diff --git a/examples/event_sources/src/kinesis_firehose_response_exception.py b/examples/event_sources/src/kinesis_firehose_response_exception.py index 43ba3a039b2..5363107eea8 100644 --- a/examples/event_sources/src/kinesis_firehose_response_exception.py +++ b/examples/event_sources/src/kinesis_firehose_response_exception.py @@ -9,11 +9,10 @@ @event_source(data_class=KinesisFirehoseEvent) -def lambda_handler(event: dict, context: LambdaContext): - firehose_event = KinesisFirehoseEvent(event) +def lambda_handler(event: KinesisFirehoseEvent, context: LambdaContext): result = KinesisFirehoseDataTransformationResponse() - for record in firehose_event.records: + for record in event.records: try: payload = record.data_as_text # base64 decoded data as str From 5bc8d00eeeaf5fac4627ccd1f8f22fb5374e0989 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 13 Jul 2026 09:41:58 +0100 Subject: [PATCH 37/76] fix(event_handler): resolve dependency injection failure with arbitrary return types (#8334) fix(event_handler): resolve dependency injection failure with arbitrary return types (#8330) --- .../event_handler/openapi/dependant.py | 9 ++- .../event_handler/_pydantic/test_depends.py | 79 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/event_handler/openapi/dependant.py b/aws_lambda_powertools/event_handler/openapi/dependant.py index 1e7f4327602..17d98914c73 100644 --- a/aws_lambda_powertools/event_handler/openapi/dependant.py +++ b/aws_lambda_powertools/event_handler/openapi/dependant.py @@ -156,6 +156,7 @@ def get_dependant( call: Callable[..., Any], name: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, + is_dependency: bool = False, ) -> Dependant: """ Returns a dependant model for a handler function. A dependant model is a model that contains @@ -200,6 +201,7 @@ def get_dependant( sub_dependant = get_dependant( path=path, call=depends_instance.dependency, + is_dependency=True, ) dependant.dependencies.append( DependencyParam( @@ -229,7 +231,12 @@ def get_dependant( else: add_param_to_fields(field=param_field, dependant=dependant) - _add_return_annotation(dependant, endpoint_signature) + # A dependency's return value is injected directly into the handler, never serialized as a + # response body nor validated as an OpenAPI parameter — so building a Pydantic schema for it is + # both unused (no reader consumes a sub-dependency's return_param) and actively harmful: it crashes + # for arbitrary return types (e.g. boto3/botocore clients). Only the top-level handler needs it. + if not is_dependency: + _add_return_annotation(dependant, endpoint_signature) _add_extra_responses(dependant, responses) return dependant diff --git a/tests/functional/event_handler/_pydantic/test_depends.py b/tests/functional/event_handler/_pydantic/test_depends.py index 0cbc05b83c7..1a4be667377 100644 --- a/tests/functional/event_handler/_pydantic/test_depends.py +++ b/tests/functional/event_handler/_pydantic/test_depends.py @@ -214,3 +214,82 @@ def handler(name: str = "world", greeting: Annotated[str, Depends(get_greeting)] result = app(event, {}) assert result["statusCode"] == 200 assert json.loads(result["body"]) == {"message": "hello, Lambda!"} + + +class ArbitraryClient: + """Stand-in for an arbitrary non-Pydantic type such as a boto3 client.""" + + def __init__(self, name: str = "default"): + self.name = name + + +def test_depends_with_arbitrary_return_type_and_validation(): + """A dependency returning a non-Pydantic type must not crash under enable_validation (#8330).""" + app = APIGatewayHttpResolver(enable_validation=True) + + def get_client() -> ArbitraryClient: + return ArbitraryClient(name="orders") + + @app.get("/items") + def handler(client: Annotated[ArbitraryClient, Depends(get_client)]): + return {"client": client.name} + + event = {**API_GW_V2_EVENT} + event["rawPath"] = "/items" + event["requestContext"] = { + **event["requestContext"], + "http": {"method": "GET", "path": "/items"}, + } + + result = app(event, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"client": "orders"} + + +def test_depends_nested_arbitrary_return_types_and_validation(): + """A nested dependency chain of non-Pydantic return types must resolve (#8330). + + Mirrors the reported chain: botocore session -> boto3 session -> dynamodb client. + """ + app = APIGatewayHttpResolver(enable_validation=True) + + def get_session() -> ArbitraryClient: + return ArbitraryClient(name="session") + + def get_client(session: Annotated[ArbitraryClient, Depends(get_session)]) -> ArbitraryClient: + return ArbitraryClient(name=f"client-of-{session.name}") + + @app.get("/items") + def handler(client: Annotated[ArbitraryClient, Depends(get_client)]): + return {"client": client.name} + + event = {**API_GW_V2_EVENT} + event["rawPath"] = "/items" + event["requestContext"] = { + **event["requestContext"], + "http": {"method": "GET", "path": "/items"}, + } + + result = app(event, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"client": "client-of-session"} + + +def test_depends_arbitrary_return_type_excluded_from_openapi_schema(): + """A non-Pydantic dependency return type must not appear in (or break) the OpenAPI schema (#8330).""" + app = APIGatewayHttpResolver(enable_validation=True) + + def get_client() -> ArbitraryClient: + return ArbitraryClient() + + @app.get("/items") + def handler(client: Annotated[ArbitraryClient, Depends(get_client)]): + return {"ok": True} + + # Schema generation itself must not raise, and the dependency must not leak into params/body. + schema = app.get_openapi_schema() + get_op = schema.paths["/items"].get + param_names = [p.name for p in (get_op.parameters or [])] + + assert "client" not in param_names + assert get_op.requestBody is None From 71d58f1fac15f364995fcf6bc183d7d312593e25 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 13 Jul 2026 09:44:55 +0100 Subject: [PATCH 38/76] chore(data-masking): bump encryption sdk version (#8335) --- poetry.lock | 46 +++++++------------ pyproject.toml | 2 +- .../function_1024/requirements.txt | 2 +- .../function_128/requirements.txt | 2 +- .../function_1769/requirements.txt | 2 +- 5 files changed, 21 insertions(+), 33 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2faf20816d1..6e2f93b69d2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "annotated-types" @@ -11,7 +11,7 @@ files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [[package]] name = "anyio" @@ -129,7 +129,6 @@ files = [ {file = "avro-1.12.1-py2.py3-none-any.whl", hash = "sha256:970475dd6457924533966fe761be607c759d5a48390cc8fbed472f7c9a8868f2"}, {file = "avro-1.12.1.tar.gz", hash = "sha256:c5b8dd2dd4c10816f0dc127cc29cfd43b5e405cf7e6840e89460a024bf3d098d"}, ] -markers = {main = "extra == \"kafka-consumer-avro\""} [package.extras] snappy = ["python-snappy"] @@ -201,7 +200,7 @@ files = [ ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1a0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1.a0" aws-cdk-lib = ">=2.114.1,<3.0.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.92.0,<2.0.0" @@ -221,7 +220,7 @@ files = [ ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1a0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1.a0" aws-cdk-lib = ">=2.114.1,<3.0.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.92.0,<2.0.0" @@ -369,7 +368,7 @@ description = "The AWS X-Ray SDK for Python (the SDK) enables Python developers optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"all\" or extra == \"tracer\"" +markers = "extra == \"tracer\" or extra == \"all\"" files = [ {file = "aws_xray_sdk-2.15.0-py2.py3-none-any.whl", hash = "sha256:422d62ad7d52e373eebb90b642eb1bb24657afe03b22a8df4a8b2e5108e278a3"}, {file = "aws_xray_sdk-2.15.0.tar.gz", hash = "sha256:794381b96e835314345068ae1dd3b9120bd8b4e21295066c37e8814dbb341365"}, @@ -486,7 +485,6 @@ files = [ {file = "boto3-1.42.67-py3-none-any.whl", hash = "sha256:aa900216bdc48bbd0115ed7128a4baed5548c6a60673160a38df8a8566df57cd"}, {file = "boto3-1.42.67.tar.gz", hash = "sha256:d4123ceb3be36c5cb7ddccc7a7c43701e1fb6af612ef46e3b5d667daf5447d4b"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\""} [package.dependencies] botocore = ">=1.42.67,<1.43.0" @@ -968,7 +966,6 @@ files = [ {file = "botocore-1.42.67-py3-none-any.whl", hash = "sha256:a94317d2ce83deae230964beb2729639455de65595d0154f285b0ccfd29780cd"}, {file = "botocore-1.42.67.tar.gz", hash = "sha256:ee307f30fcb798d244fb35a87847b274e1e1f72cd5f7f2e31bd1826df0c45295"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\""} [package.dependencies] jmespath = ">=0.7.1,<2.0.0" @@ -1086,7 +1083,6 @@ files = [ {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, ] -markers = {main = "extra == \"datadog\""} [[package]] name = "cffi" @@ -1335,7 +1331,6 @@ files = [ {file = "charset_normalizer-3.4.5-py3-none-any.whl", hash = "sha256:9db5e3fcdcee89a78c04dffb3fe33c79f77bd741a624946db2591c81b2fc85b0"}, {file = "charset_normalizer-3.4.5.tar.gz", hash = "sha256:95adae7b6c42a6c5b5b559b1a99149f090a57128155daeea91732c8d970d8644"}, ] -markers = {main = "extra == \"datadog\""} [[package]] name = "click" @@ -1699,11 +1694,11 @@ files = [ [package.dependencies] bytecode = [ - {version = ">=0.13.0,<1", markers = "python_version < \"3.11.0\""}, - {version = ">=0.16.0,<1", markers = "python_version >= \"3.13.0\" and python_version < \"3.14.0\""}, {version = ">=0.17.0,<1", markers = "python_version >= \"3.14.0\""}, - {version = ">=0.14.0,<1", markers = "python_version ~= \"3.11.0\""}, + {version = ">=0.16.0,<1", markers = "python_version >= \"3.13.0\" and python_version < \"3.14.0\""}, {version = ">=0.15.1,<1", markers = "python_version ~= \"3.12.0\""}, + {version = ">=0.14.0,<1", markers = "python_version ~= \"3.11.0\""}, + {version = ">=0.13.0,<1", markers = "python_version < \"3.11.0\""}, ] envier = ">=0.6.1,<0.7.0" opentelemetry-api = ">=1,<2" @@ -1867,7 +1862,7 @@ description = "Fastest Python implementation of JSON schema" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"all\" or extra == \"validation\"" +markers = "extra == \"validation\" or extra == \"all\"" files = [ {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"}, {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"}, @@ -2093,7 +2088,6 @@ files = [ {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, ] -markers = {main = "extra == \"datadog\" or extra == \"valkey\""} [package.extras] all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] @@ -2359,7 +2353,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.3.6" +jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rpds-py = ">=0.25.0" @@ -3379,7 +3373,6 @@ files = [ {file = "protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9"}, {file = "protobuf-7.35.1.tar.gz", hash = "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a"}, ] -markers = {main = "extra == \"kafka-consumer-protobuf\" or extra == \"valkey\""} [[package]] name = "publication" @@ -3429,7 +3422,7 @@ files = [ {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3570,7 +3563,7 @@ files = [ {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983"}, {file = "pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -3785,7 +3778,6 @@ files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\""} [package.dependencies] six = ">=1.5" @@ -4150,7 +4142,6 @@ files = [ {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, ] -markers = {main = "extra == \"datadog\""} [package.dependencies] certifi = ">=2023.5.7" @@ -4359,13 +4350,12 @@ files = [ {file = "s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:18e25d66fed509e3868dc1572b3f427ff947dd2c56f844a5bf09481ad3f3b2fe"}, {file = "s3transfer-0.16.0.tar.gz", hash = "sha256:8e990f13268025792229cd52fa10cb7163744bf56e719e0b9cb925ab79abf920"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\""} [package.dependencies] -botocore = ">=1.37.4,<2.0a0" +botocore = ">=1.37.4,<2.0a.0" [package.extras] -crt = ["botocore[crt] (>=1.37.4,<2.0a0)"] +crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"] [[package]] name = "scantree" @@ -4458,7 +4448,6 @@ files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\""} [[package]] name = "smmap" @@ -4830,7 +4819,7 @@ files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] typing-extensions = ">=4.12.0" @@ -4950,7 +4939,6 @@ files = [ {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\" or extra == \"datadog\""} [package.extras] brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] @@ -5164,7 +5152,7 @@ files = [ {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}, {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"tracer\" or extra == \"datadog\""} +markers = {main = "extra == \"tracer\" or extra == \"all\" or extra == \"datamasking\" or extra == \"datadog\""} [[package]] name = "xenon" @@ -5220,4 +5208,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "4487e5115c6fe8c9475bd1c913532b6ece5aa69d3863042af67fd0ef3f1a9980" +content-hash = "76b052fac1e517cf35f1c4ffea334118266db8464384a5c7dad9211439985034" diff --git a/pyproject.toml b/pyproject.toml index 24047d1ba4d..548f25a03fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ pydantic-settings = {version = "^2.6.1", optional = true} boto3 = { version = "^1.34.32", optional = true } redis = { version = ">=4.4,<9.0", optional = true } valkey-glide = { version = ">=1.3.5,<3.0", optional = true } -aws-encryption-sdk = { version = ">=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4,<5.0.0", optional = true } +aws-encryption-sdk = { version = ">=4.0.5,<5.0.0", optional = true } jsonpath-ng = { version = "^1.6.0", optional = true } datadog-lambda = { version = ">=8.114.0,<9.0.0", optional = true } avro = { version = "^1.12.0", optional = true } diff --git a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt index 397c11ba436..c168cb36ead 100644 --- a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt +++ b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt @@ -1,3 +1,3 @@ requests>=2.32.0 aws-lambda-powertools[tracer] -aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4 +aws-encryption-sdk>=4.0.5,<5.0.0 diff --git a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt index 397c11ba436..c168cb36ead 100644 --- a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt +++ b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt @@ -1,3 +1,3 @@ requests>=2.32.0 aws-lambda-powertools[tracer] -aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4 +aws-encryption-sdk>=4.0.5,<5.0.0 diff --git a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt index 397c11ba436..c168cb36ead 100644 --- a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt +++ b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt @@ -1,3 +1,3 @@ requests>=2.32.0 aws-lambda-powertools[tracer] -aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4 +aws-encryption-sdk>=4.0.5,<5.0.0 From 3b029e51abdf9b7d391f89b7ff9f6db00aa28a62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:18:53 +0100 Subject: [PATCH 39/76] chore(ci): bump version to 3.31.1 (#8336) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index 0854a8929e3..1162b589e36 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "3.31.0" +VERSION = "3.31.1" diff --git a/pyproject.toml b/pyproject.toml index 548f25a03fd..4178dca4616 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "3.31.0" +version = "3.31.1" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From 51473090c5fd25d79c80446cf635f49a4355006c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:34:49 +0100 Subject: [PATCH 40/76] chore(ci): layer docs update (#8337) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Leandro Damascena --- CHANGELOG.md | 15 +- docs/includes/_layer_homepage_arm64.md | 290 ++++++++--------- docs/includes/_layer_homepage_x86.md | 300 +++++++++--------- examples/build_recipes/cdk/basic/app.py | 2 +- .../stacks/powertools_cdk_stack.py | 2 +- .../build_recipes/sam/multi-env/template.yaml | 2 +- .../sam/with-layers/template.yaml | 4 +- examples/homepage/install/arm64/amplify.txt | 4 +- examples/homepage/install/arm64/cdk_arm64.py | 2 +- .../homepage/install/arm64/pulumi_arm64.py | 2 +- examples/homepage/install/arm64/sam.yaml | 2 +- .../homepage/install/arm64/serverless.yml | 2 +- examples/homepage/install/arm64/terraform.tf | 2 +- examples/homepage/install/x86_64/amplify.txt | 4 +- examples/homepage/install/x86_64/cdk_x86.py | 2 +- .../homepage/install/x86_64/pulumi_x86.py | 2 +- examples/homepage/install/x86_64/sam.yaml | 2 +- .../homepage/install/x86_64/serverless.yml | 2 +- examples/homepage/install/x86_64/terraform.tf | 2 +- examples/logger/sam/template.yaml | 2 +- examples/metrics/sam/template.yaml | 2 +- examples/metrics_datadog/sam/template.yaml | 2 +- examples/tracer/sam/template.yaml | 2 +- 23 files changed, 332 insertions(+), 319 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad7dc22c5a9..ab85a6c9792 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,27 @@ # Unreleased + +## [v3.31.1] - 2026-07-13 +## Maintenance + +* version bump +* **data-masking:** bump encryption sdk version ([#8335](https://github.com/aws-powertools/powertools-lambda-python/issues/8335)) + + ## [v3.31.0] - 2026-06-29 ## Features +* adding circuit breaker feature ([#8266](https://github.com/aws-powertools/powertools-lambda-python/issues/8266)) * **event_handler:** support any Pydantic Field annotation in parameter ([#8305](https://github.com/aws-powertools/powertools-lambda-python/issues/8305)) ## Maintenance * version bump +* **deps:** bump redis from 7.4.0 to 8.0.1 ([#8297](https://github.com/aws-powertools/powertools-lambda-python/issues/8297)) +* **deps-dev:** bump sentry-sdk from 2.62.0 to 2.63.0 ([#8296](https://github.com/aws-powertools/powertools-lambda-python/issues/8296)) +* **deps-dev:** bump boto3-stubs from 1.43.29 to 1.43.36 ([#8295](https://github.com/aws-powertools/powertools-lambda-python/issues/8295)) @@ -7759,7 +7771,8 @@ * Merge pull request [#5](https://github.com/aws-powertools/powertools-lambda-python/issues/5) from jfuss/feat/python38 -[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.31.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.31.1...HEAD +[v3.31.1]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.31.0...v3.31.1 [v3.31.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.30.0...v3.31.0 [v3.30.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.29.0...v3.30.0 [v3.29.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.28.0...v3.29.0 diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index 8c7337ee7ee..e722e169fb7 100644 --- a/docs/includes/_layer_homepage_arm64.md +++ b/docs/includes/_layer_homepage_arm64.md @@ -6,168 +6,168 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 10789aede59..86daee00793 100644 --- a/docs/includes/_layer_homepage_x86.md +++ b/docs/includes/_layer_homepage_x86.md @@ -5,173 +5,173 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:35**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | diff --git a/examples/build_recipes/cdk/basic/app.py b/examples/build_recipes/cdk/basic/app.py index 9f4fef0d988..018888bdf1d 100644 --- a/examples/build_recipes/cdk/basic/app.py +++ b/examples/build_recipes/cdk/basic/app.py @@ -24,7 +24,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36", ) # Lambda Function diff --git a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py index fd0dd8768a2..565807a226b 100644 --- a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py +++ b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py @@ -47,7 +47,7 @@ def _create_powertools_layer(self) -> _lambda.ILayerVersion: return _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36", ) def _create_dynamodb_table(self) -> dynamodb.Table: diff --git a/examples/build_recipes/sam/multi-env/template.yaml b/examples/build_recipes/sam/multi-env/template.yaml index 2d3f03adb5a..415bb0cbe09 100644 --- a/examples/build_recipes/sam/multi-env/template.yaml +++ b/examples/build_recipes/sam/multi-env/template.yaml @@ -61,7 +61,7 @@ Resources: CodeUri: src/ Handler: app.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36 - !Ref DependenciesLayer Events: ApiEvent: diff --git a/examples/build_recipes/sam/with-layers/template.yaml b/examples/build_recipes/sam/with-layers/template.yaml index fb4a97f8f06..b349cf55236 100644 --- a/examples/build_recipes/sam/with-layers/template.yaml +++ b/examples/build_recipes/sam/with-layers/template.yaml @@ -31,7 +31,7 @@ Resources: CodeUri: src/app/ Handler: app_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36 - !Ref DependenciesLayer Events: ApiEvent: @@ -50,7 +50,7 @@ Resources: CodeUri: src/worker/ Handler: worker_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:35 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36 - !Ref DependenciesLayer Events: SQSEvent: diff --git a/examples/homepage/install/arm64/amplify.txt b/examples/homepage/install/arm64/amplify.txt index 55025d12efe..20a4ff29e6d 100644 --- a/examples/homepage/install/arm64/amplify.txt +++ b/examples/homepage/install/arm64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/arm64/cdk_arm64.py b/examples/homepage/install/arm64/cdk_arm64.py index 2ecad4de5b7..ba9d76f2e43 100644 --- a/examples/homepage/install/arm64/cdk_arm64.py +++ b/examples/homepage/install/arm64/cdk_arm64.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/arm64/pulumi_arm64.py b/examples/homepage/install/arm64/pulumi_arm64.py index e835aaad8b5..834bab0506b 100644 --- a/examples/homepage/install/arm64/pulumi_arm64.py +++ b/examples/homepage/install/arm64/pulumi_arm64.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/arm64/sam.yaml b/examples/homepage/install/arm64/sam.yaml index 251be092618..7def81c290f 100644 --- a/examples/homepage/install/arm64/sam.yaml +++ b/examples/homepage/install/arm64/sam.yaml @@ -9,4 +9,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 diff --git a/examples/homepage/install/arm64/serverless.yml b/examples/homepage/install/arm64/serverless.yml index 3a31aa80873..477ef56591e 100644 --- a/examples/homepage/install/arm64/serverless.yml +++ b/examples/homepage/install/arm64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 diff --git a/examples/homepage/install/arm64/terraform.tf b/examples/homepage/install/arm64/terraform.tf index 15cb3fdb6d2..b90a20cbcfe 100644 --- a/examples/homepage/install/arm64/terraform.tf +++ b/examples/homepage/install/arm64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:35"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") diff --git a/examples/homepage/install/x86_64/amplify.txt b/examples/homepage/install/x86_64/amplify.txt index de4a09e62e6..cdfc77196e3 100644 --- a/examples/homepage/install/x86_64/amplify.txt +++ b/examples/homepage/install/x86_64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/x86_64/cdk_x86.py b/examples/homepage/install/x86_64/cdk_x86.py index 7cc43a5535b..8480c9ea0ae 100644 --- a/examples/homepage/install/x86_64/cdk_x86.py +++ b/examples/homepage/install/x86_64/cdk_x86.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/x86_64/pulumi_x86.py b/examples/homepage/install/x86_64/pulumi_x86.py index b96c7a61107..e4f42647e25 100644 --- a/examples/homepage/install/x86_64/pulumi_x86.py +++ b/examples/homepage/install/x86_64/pulumi_x86.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml index 738e54ab340..6ce13861171 100644 --- a/examples/homepage/install/x86_64/sam.yaml +++ b/examples/homepage/install/x86_64/sam.yaml @@ -8,4 +8,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml index bcede79fdac..a510b046023 100644 --- a/examples/homepage/install/x86_64/serverless.yml +++ b/examples/homepage/install/x86_64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf index 3a272d5ac81..19938fa6979 100644 --- a/examples/homepage/install/x86_64/terraform.tf +++ b/examples/homepage/install/x86_64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index ba411569c86..98bfce6f2c5 100644 --- a/examples/logger/sam/template.yaml +++ b/examples/logger/sam/template.yaml @@ -14,7 +14,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index d5dab46f9d2..729590594d9 100644 --- a/examples/metrics/sam/template.yaml +++ b/examples/metrics/sam/template.yaml @@ -16,7 +16,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 Resources: CaptureLambdaHandlerExample: diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml index 6191e384264..53e8469b8f5 100644 --- a/examples/metrics_datadog/sam/template.yaml +++ b/examples/metrics_datadog/sam/template.yaml @@ -20,7 +20,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 # Find the latest Layer version in the Datadog official documentation # Datadog SDK diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml index 156b5db6b83..9dfdff730e2 100644 --- a/examples/tracer/sam/template.yaml +++ b/examples/tracer/sam/template.yaml @@ -13,7 +13,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:35 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 Resources: CaptureLambdaHandlerExample: From 62b1378fba0752f551b357500a15cfb777e6d73f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:07:33 -0700 Subject: [PATCH 41/76] chore(deps): bump gitpython from 3.1.50 to 3.1.57 in /docs (#8362) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.50 to 3.1.57. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.50...3.1.57) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.57 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index a4ad8668c0f..441befb4538 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -139,9 +139,9 @@ gitdb==4.0.12 \ --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf # via gitpython -gitpython==3.1.50 \ - --hash=sha256:80da2d12504d52e1f998772dc5baf6e553f8d2fcfe1fcc226c9d9a2ee3372dcc \ - --hash=sha256:d352abe2908d07355014abdd21ddf798c2a961469239afec4962e9da884858f9 +gitpython==3.1.57 \ + --hash=sha256:4ccf7d73c10f5c9e76043fbb2675ac5a1b3ff5b41e648f56bcbed5f63792ecaf \ + --hash=sha256:c493ec57c0ef6b19743798b6a5af859c71814b524e7e6f97baa2f8e658961488 # via mkdocs-git-revision-date-plugin griffe==1.13.0 \ --hash=sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0 \ From 53d3fafefc4231ea7eefb7b588526c7de9a8d401 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 14:13:57 -0700 Subject: [PATCH 42/76] chore(deps): bump cryptography from 48.0.1 to 50.0.0 (#8364) Bumps [cryptography](https://github.com/pyca/cryptography) from 48.0.1 to 50.0.0. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/48.0.1...50.0.0) --- updated-dependencies: - dependency-name: cryptography dependency-version: 50.0.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 146 +++++++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 69 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6e2f93b69d2..891909ab202 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. [[package]] name = "annotated-types" @@ -11,7 +11,7 @@ files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [[package]] name = "anyio" @@ -129,6 +129,7 @@ files = [ {file = "avro-1.12.1-py2.py3-none-any.whl", hash = "sha256:970475dd6457924533966fe761be607c759d5a48390cc8fbed472f7c9a8868f2"}, {file = "avro-1.12.1.tar.gz", hash = "sha256:c5b8dd2dd4c10816f0dc127cc29cfd43b5e405cf7e6840e89460a024bf3d098d"}, ] +markers = {main = "extra == \"kafka-consumer-avro\""} [package.extras] snappy = ["python-snappy"] @@ -200,7 +201,7 @@ files = [ ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1.a0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1a0" aws-cdk-lib = ">=2.114.1,<3.0.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.92.0,<2.0.0" @@ -220,7 +221,7 @@ files = [ ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1.a0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.114.1a0" aws-cdk-lib = ">=2.114.1,<3.0.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.92.0,<2.0.0" @@ -368,7 +369,7 @@ description = "The AWS X-Ray SDK for Python (the SDK) enables Python developers optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"tracer\" or extra == \"all\"" +markers = "extra == \"all\" or extra == \"tracer\"" files = [ {file = "aws_xray_sdk-2.15.0-py2.py3-none-any.whl", hash = "sha256:422d62ad7d52e373eebb90b642eb1bb24657afe03b22a8df4a8b2e5108e278a3"}, {file = "aws_xray_sdk-2.15.0.tar.gz", hash = "sha256:794381b96e835314345068ae1dd3b9120bd8b4e21295066c37e8814dbb341365"}, @@ -485,6 +486,7 @@ files = [ {file = "boto3-1.42.67-py3-none-any.whl", hash = "sha256:aa900216bdc48bbd0115ed7128a4baed5548c6a60673160a38df8a8566df57cd"}, {file = "boto3-1.42.67.tar.gz", hash = "sha256:d4123ceb3be36c5cb7ddccc7a7c43701e1fb6af612ef46e3b5d667daf5447d4b"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\""} [package.dependencies] botocore = ">=1.42.67,<1.43.0" @@ -966,6 +968,7 @@ files = [ {file = "botocore-1.42.67-py3-none-any.whl", hash = "sha256:a94317d2ce83deae230964beb2729639455de65595d0154f285b0ccfd29780cd"}, {file = "botocore-1.42.67.tar.gz", hash = "sha256:ee307f30fcb798d244fb35a87847b274e1e1f72cd5f7f2e31bd1826df0c45295"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\""} [package.dependencies] jmespath = ">=0.7.1,<2.0.0" @@ -1083,6 +1086,7 @@ files = [ {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, ] +markers = {main = "extra == \"datadog\""} [[package]] name = "cffi" @@ -1091,6 +1095,7 @@ description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" groups = ["main", "dev"] +markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -1177,7 +1182,6 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] -markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1331,6 +1335,7 @@ files = [ {file = "charset_normalizer-3.4.5-py3-none-any.whl", hash = "sha256:9db5e3fcdcee89a78c04dffb3fe33c79f77bd741a624946db2591c81b2fc85b0"}, {file = "charset_normalizer-3.4.5.tar.gz", hash = "sha256:95adae7b6c42a6c5b5b559b1a99149f090a57128155daeea91732c8d970d8644"}, ] +markers = {main = "extra == \"datadog\""} [[package]] name = "click" @@ -1503,63 +1508,59 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" -version = "48.0.1" +version = "50.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.9" groups = ["main", "dev"] files = [ - {file = "cryptography-48.0.1-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:3e4a1a3232eef2e6c732827d5722db29a0cc8b27af2a4d865b094cf954be9ca1"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:32143b24adb918f078134e1e230f1eb8cc04886b92c28b5f0041aaf3e5699225"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0d27a5696721ef7a672b8c810f6aded391058e0b9486e63e6d93baf765da691"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb86ce1af36fe65041b6db9a8bb064ee621a7e5fded0f80d475ec243477cd242"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b024e784ad6c077ee0147b35ea9cbfc1e34e1fd4c1dcca214c2794d73a12df08"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3752f2dbc8f07a30aad2932c986cea495b03bb554887828225da104f732852b6"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:bd81490cd5801d755cf97bb68ac191f14b708470b1c7cf4580f669b9c9264cd8"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:66fd0771e7b9c6dcd44cf1120690d2338d16d72795cf40cae2786a39eba65429"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:3fd2ca57062b241c856670b073487d2e86c4637937ca5601e48f97bf8e11fc8f"}, - {file = "cryptography-48.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:0ee6ea481db1ab889cba043ec1eda17bb9c1ea79db6722f779c3667f9f70322f"}, - {file = "cryptography-48.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f2ceef93cb096aa3c4cc4b5c94ca6131f9196d28c64d6111533402a9b2054d41"}, - {file = "cryptography-48.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bd3f92d76217892b15df84ca256c2c113d386fdda7a7d8691aeeced976507c6"}, - {file = "cryptography-48.0.1-cp311-abi3-win32.whl", hash = "sha256:b9a32b876490d66c8bcc9963ef220199569748434ab01a9d6aaeabf88e7f5158"}, - {file = "cryptography-48.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:39489bfca54c7a1f6b297efcd8bc608ab92d16c4ca631b0cad4da46724588b24"}, - {file = "cryptography-48.0.1-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:f817adc181390bd54f2f700107a7419040fb7c1bdf2fc26f36551a06a68c3345"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d5d30989c6917b478b5817902e85fddaea2261efa8648383d965381ccb9e1ac4"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:df637c05205ea7c1d7fbcbe54bbfea648a52951155f997af13d895d0ecc96991"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:869c3b8a53bfe27147832df48b32adadf558249d50e76cb3769d40e986b13265"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:e361afba8918070d376df76f408a4f67fec0ee9cff81a99e48fe9a233ef59e17"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:d069066deead00ac7f090be101be875a06855908f7ec004c27b8fefb4acfb411"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:09f73a725d582cef64b91281a322cd798d14a33b2b6f2b7ad9531dc336d84c02"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:15254441469dd6bf027039453288e2072124f8b6603563f5d759e1c9b69273fa"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:8ace4507d1e6533c125f4fac754f8bb8b6a74c08e92179dabd7e16571a3efbf3"}, - {file = "cryptography-48.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:b4e391975f038e66432328639620a4aff2d307513b004f1ca06d6225bced815c"}, - {file = "cryptography-48.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42fcd8e26fe555d9b3577a135f5091fefa0aa4e99129c23fb56787a1bd4ada72"}, - {file = "cryptography-48.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1400da5e32a43253392277eac7490a60e497d810a63dd5608d71bbd7af507c9"}, - {file = "cryptography-48.0.1-cp314-cp314t-win32.whl", hash = "sha256:0df56b056bc17c1b7d6821dfa65216e62bd232d8ab05eb3db44e71d235651471"}, - {file = "cryptography-48.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:9de21387aa95e2a895823d0745b430bed4f33503ba9ab5e0b5311f33e37d66d2"}, - {file = "cryptography-48.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:4fdc69f8e4316bcf0c8c8ec1f26f285d12e8142d88d96c876a59a03be3f6ae67"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48fe40804d4caa2288f24e70ca8c64c42dd826da0ad7e4f1b41b2128d679e6c8"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:86be3b1b0b6bf09482fb50a979c508d2950ed95f5621ec77f4e385962006b83a"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:4ab0a343c807bbcd90c971cd1ecf072937cd01847a9e002bef88fb47ac6be577"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9621de99d2da096006b629979efd8ae7eb2d8b822488d0c89ee4000c306c59b1"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:88c852a0ae366e262e5a1744b685e6a433dc8788dd2a277e418bf4904203609d"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:43c5835e2cb98c8733d86f57d6fc879b613f5c3478607281c3e36daffc6dd8a6"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:fe0180af5bf9236518a087e35bf2d9a347d5f5f51e63c579d683ddff424e3d46"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:b7a2d1a937a738a881737cec135a38bb61470589b17515b9f73f571d0ae10401"}, - {file = "cryptography-48.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b74ca3b8e5ecdd833bf6a002ca41b4793bb27fb8f1c06ffaf2643c9e9140e31b"}, - {file = "cryptography-48.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2c37f2461406063b417837f5f3daab668652acd82423efcd7f0a9f04be972de1"}, - {file = "cryptography-48.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:86fe77abb1bd87afb251d4d02ada7ecf53a32cee9b67d976abb2e45a13297475"}, - {file = "cryptography-48.0.1-cp39-abi3-win32.whl", hash = "sha256:6b2c0c3e6ccf3ade7750f836ef3ee36eea250cc467d45c256895573ac08cc6f1"}, - {file = "cryptography-48.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:9a49ca6c81417f6a5edb50375a60cccdd70fa0a91a5211829dbea74eba94d2ac"}, - {file = "cryptography-48.0.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:08a597acce1ff37f347400087776599e2348a3a8bc53b44120e463cd274efe4a"}, - {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:735824ec41b7f74a7c45fb1591349333e4c696cb6c044e5f46356e560143e4cd"}, - {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:92a46e1d638daa264ba2971c0b0489c9409787943efae4d60ffda3d091ef832c"}, - {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:7e234ac052af99f2700826a5c29ea99d9c1b1f80341cde62d11c8154dc8e0bd9"}, - {file = "cryptography-48.0.1-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:33842cf0888951cef5bc7ac724ab844a42044c1727b967b7f8997289a0464f92"}, - {file = "cryptography-48.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6184ca7b174f28d7c703f1290d4b297217c45355f77a98f67e9b7f14549ac54a"}, - {file = "cryptography-48.0.1.tar.gz", hash = "sha256:266f4ee051abb2f725b74ef8072b521ce1feacf685a3364fa6a6b45548db791a"}, + {file = "cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169"}, + {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f"}, + {file = "cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105"}, + {file = "cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef"}, + {file = "cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30"}, + {file = "cryptography-50.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d"}, + {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c"}, + {file = "cryptography-50.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c"}, + {file = "cryptography-50.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95"}, + {file = "cryptography-50.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269"}, + {file = "cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708"}, + {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47"}, + {file = "cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9"}, + {file = "cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7"}, + {file = "cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba"}, + {file = "cryptography-50.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5e34edd123674534acd70147f0ca331eaa2c74e6325fb2028c886aa26ba0b68c"}, + {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8eb5e1172eb569ea8a872796576e6a67c276351728b6455d5beb01242b027c6a"}, + {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:910d11e1a385c654bf738bf3e6b8e6ed5de0f5610fcae2be9e5b398d8081d20e"}, + {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:62598a8a57f815db4c6259a4e97d857dab56697e7de8e8ab02352ab74da1995d"}, + {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:07479a1cb08219ab719147e742e76090c9c773321959bb94946fffdd397a6437"}, + {file = "cryptography-50.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c99c003e088647b8a5b7c145d6f78c335f6348332b62e142d411c4b63d1460b9"}, + {file = "cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\""} [package.dependencies] cffi = {version = ">=2.0.0", markers = "platform_python_implementation != \"PyPy\""} @@ -1694,11 +1695,11 @@ files = [ [package.dependencies] bytecode = [ - {version = ">=0.17.0,<1", markers = "python_version >= \"3.14.0\""}, + {version = ">=0.13.0,<1", markers = "python_version < \"3.11.0\""}, {version = ">=0.16.0,<1", markers = "python_version >= \"3.13.0\" and python_version < \"3.14.0\""}, - {version = ">=0.15.1,<1", markers = "python_version ~= \"3.12.0\""}, + {version = ">=0.17.0,<1", markers = "python_version >= \"3.14.0\""}, {version = ">=0.14.0,<1", markers = "python_version ~= \"3.11.0\""}, - {version = ">=0.13.0,<1", markers = "python_version < \"3.11.0\""}, + {version = ">=0.15.1,<1", markers = "python_version ~= \"3.12.0\""}, ] envier = ">=0.6.1,<0.7.0" opentelemetry-api = ">=1,<2" @@ -1862,7 +1863,7 @@ description = "Fastest Python implementation of JSON schema" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"validation\" or extra == \"all\"" +markers = "extra == \"all\" or extra == \"validation\"" files = [ {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"}, {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"}, @@ -2088,6 +2089,7 @@ files = [ {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, ] +markers = {main = "extra == \"datadog\" or extra == \"valkey\""} [package.extras] all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] @@ -2353,7 +2355,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.03.6" +jsonschema-specifications = ">=2023.3.6" referencing = ">=0.28.4" rpds-py = ">=0.25.0" @@ -3373,6 +3375,7 @@ files = [ {file = "protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9"}, {file = "protobuf-7.35.1.tar.gz", hash = "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a"}, ] +markers = {main = "extra == \"kafka-consumer-protobuf\" or extra == \"valkey\""} [[package]] name = "publication" @@ -3405,11 +3408,11 @@ description = "C parser in Python" optional = false python-versions = ">=3.10" groups = ["main", "dev"] +markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"" files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] -markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""} [[package]] name = "pydantic" @@ -3422,7 +3425,7 @@ files = [ {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3563,7 +3566,7 @@ files = [ {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983"}, {file = "pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -3778,6 +3781,7 @@ files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\""} [package.dependencies] six = ">=1.5" @@ -4142,6 +4146,7 @@ files = [ {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, ] +markers = {main = "extra == \"datadog\""} [package.dependencies] certifi = ">=2023.5.7" @@ -4350,12 +4355,13 @@ files = [ {file = "s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:18e25d66fed509e3868dc1572b3f427ff947dd2c56f844a5bf09481ad3f3b2fe"}, {file = "s3transfer-0.16.0.tar.gz", hash = "sha256:8e990f13268025792229cd52fa10cb7163744bf56e719e0b9cb925ab79abf920"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\""} [package.dependencies] -botocore = ">=1.37.4,<2.0a.0" +botocore = ">=1.37.4,<2.0a0" [package.extras] -crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"] +crt = ["botocore[crt] (>=1.37.4,<2.0a0)"] [[package]] name = "scantree" @@ -4448,6 +4454,7 @@ files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\""} [[package]] name = "smmap" @@ -4819,7 +4826,7 @@ files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] typing-extensions = ">=4.12.0" @@ -4939,6 +4946,7 @@ files = [ {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"aws-sdk\" or extra == \"tracer\" or extra == \"datadog\""} [package.extras] brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] @@ -5152,7 +5160,7 @@ files = [ {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}, {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}, ] -markers = {main = "extra == \"tracer\" or extra == \"all\" or extra == \"datamasking\" or extra == \"datadog\""} +markers = {main = "extra == \"all\" or extra == \"datamasking\" or extra == \"tracer\" or extra == \"datadog\""} [[package]] name = "xenon" From 07a47aae2262cf05c75606583eac37c6a1a25b35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:35:21 +0200 Subject: [PATCH 43/76] chore(deps): bump aws-encryption-sdk from 4.0.5 to 4.0.6 (#8346) Bumps [aws-encryption-sdk](https://github.com/aws/aws-encryption-sdk-python) from 4.0.5 to 4.0.6. - [Release notes](https://github.com/aws/aws-encryption-sdk-python/releases) - [Changelog](https://github.com/aws/aws-encryption-sdk-python/blob/master/CHANGELOG.rst) - [Commits](https://github.com/aws/aws-encryption-sdk-python/compare/v4.0.5...v4.0.6) --- updated-dependencies: - dependency-name: aws-encryption-sdk dependency-version: 4.0.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 891909ab202..69cbaf241b6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -306,15 +306,15 @@ typeguard = "2.13.3" [[package]] name = "aws-encryption-sdk" -version = "4.0.5" +version = "4.0.6" description = "AWS Encryption SDK implementation for Python" optional = true python-versions = "*" groups = ["main"] markers = "extra == \"all\" or extra == \"datamasking\"" files = [ - {file = "aws_encryption_sdk-4.0.5-py2.py3-none-any.whl", hash = "sha256:3e6b76afb94c28730487dee71fa1bfc217fcdbab061733c220ff87b88630e40e"}, - {file = "aws_encryption_sdk-4.0.5.tar.gz", hash = "sha256:a36136181a4d63cbf0d7347d29786c80a4d74a07c79c88a8799e27b27a9c3fc1"}, + {file = "aws_encryption_sdk-4.0.6-py2.py3-none-any.whl", hash = "sha256:35f62f775a8d4a6cb677a4a8927bb19acb3da35308405213f668396ee6298ad4"}, + {file = "aws_encryption_sdk-4.0.6.tar.gz", hash = "sha256:ec03bfa2df64ef21417bd6ff749bb63e84149586a4f7fbe528ec6b443326ea9e"}, ] [package.dependencies] @@ -1095,7 +1095,6 @@ description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" groups = ["main", "dev"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -1182,6 +1181,7 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] +markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1561,6 +1561,7 @@ files = [ {file = "cryptography-50.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c99c003e088647b8a5b7c145d6f78c335f6348332b62e142d411c4b63d1460b9"}, {file = "cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9"}, ] +markers = {main = "extra == \"all\" or extra == \"datamasking\""} [package.dependencies] cffi = {version = ">=2.0.0", markers = "platform_python_implementation != \"PyPy\""} @@ -3408,11 +3409,11 @@ description = "C parser in Python" optional = false python-versions = ">=3.10" groups = ["main", "dev"] -markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"" files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] +markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""} [[package]] name = "pydantic" From ff0c33008586e569aa13520ea7ce29380d2e3f57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:39:22 +0200 Subject: [PATCH 44/76] chore(deps-dev): bump gitpython from 3.1.50 to 3.1.57 (#8363) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.50 to 3.1.57. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.50...3.1.57) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.57 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 69cbaf241b6..eaf80ca0b49 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1920,14 +1920,14 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.50" +version = "3.1.57" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "gitpython-3.1.50-py3-none-any.whl", hash = "sha256:d352abe2908d07355014abdd21ddf798c2a961469239afec4962e9da884858f9"}, - {file = "gitpython-3.1.50.tar.gz", hash = "sha256:80da2d12504d52e1f998772dc5baf6e553f8d2fcfe1fcc226c9d9a2ee3372dcc"}, + {file = "gitpython-3.1.57-py3-none-any.whl", hash = "sha256:4ccf7d73c10f5c9e76043fbb2675ac5a1b3ff5b41e648f56bcbed5f63792ecaf"}, + {file = "gitpython-3.1.57.tar.gz", hash = "sha256:c493ec57c0ef6b19743798b6a5af859c71814b524e7e6f97baa2f8e658961488"}, ] [package.dependencies] @@ -1935,7 +1935,7 @@ gitdb = ">=4.0.1,<5" [package.extras] doc = ["sphinx (>=7.4.7,<8)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy (==1.18.2) ; python_version >= \"3.9\"", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] +test = ["basedpyright (==1.39.9) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy (==1.18.2) ; python_version >= \"3.9\"", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] [[package]] name = "griffe" From f6d72e8abf5faca6d0d310d5e123cf7e12e02dbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:44:11 +0200 Subject: [PATCH 45/76] chore(deps): bump aws-cdk-lib from 2.223.0 to 2.253.0 in /layer_v3 (#8360) Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.223.0 to 2.253.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.223.0...v2.253.0) --- updated-dependencies: - dependency-name: aws-cdk-lib dependency-version: 2.253.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- layer_v3/poetry.lock | 119 +++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 72 deletions(-) diff --git a/layer_v3/poetry.lock b/layer_v3/poetry.lock index 79d0e9ccd06..7c33f06a244 100644 --- a/layer_v3/poetry.lock +++ b/layer_v3/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. [[package]] name = "attrs" @@ -14,75 +14,75 @@ files = [ [[package]] name = "aws-cdk-asset-awscli-v1" -version = "2.2.242" +version = "2.2.273" description = "A library that contains the AWS CLI for use in Lambda Layers" optional = false python-versions = "~=3.9" groups = ["main"] files = [ - {file = "aws_cdk_asset_awscli_v1-2.2.242-py3-none-any.whl", hash = "sha256:d1001bf56a12f7d1162d4211003d1e8f72a213159465e2d0e1c598cc0ea44aad"}, - {file = "aws_cdk_asset_awscli_v1-2.2.242.tar.gz", hash = "sha256:a957d679a118f4375307ed90b9aed7127c5c1402989438060eae4ab29ab0d13f"}, + {file = "aws_cdk_asset_awscli_v1-2.2.273-py3-none-any.whl", hash = "sha256:1a0994afa7b48f63b580603be64c7a99d19ed6777bdf81d3c2435d8b43cf0d71"}, + {file = "aws_cdk_asset_awscli_v1-2.2.273.tar.gz", hash = "sha256:6580dad3416e53712db434f81add6fb4a314e1a80f9c57cc42606df1f64c8e0f"}, ] [package.dependencies] -jsii = ">=1.112.0,<2.0.0" +jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" -typeguard = ">=2.13.3,<4.3.0" +typeguard = "2.13.3" [[package]] name = "aws-cdk-asset-node-proxy-agent-v6" -version = "2.1.0" +version = "2.1.2" description = "@aws-cdk/asset-node-proxy-agent-v6" optional = false -python-versions = "~=3.8" +python-versions = "~=3.9" groups = ["main"] files = [ - {file = "aws_cdk.asset_node_proxy_agent_v6-2.1.0-py3-none-any.whl", hash = "sha256:24a388b69a44d03bae6dbf864c4e25ba650d4b61c008b4568b94ffbb9a69e40e"}, - {file = "aws_cdk_asset_node_proxy_agent_v6-2.1.0.tar.gz", hash = "sha256:1f292c0631f86708ba4ee328b3a2b229f7e46ea1c79fbde567ee9eb119c2b0e2"}, + {file = "aws_cdk_asset_node_proxy_agent_v6-2.1.2-py3-none-any.whl", hash = "sha256:1028bff16fdb87b8c82404e9b48f32ed383429dece84067f47379c4049da5da4"}, + {file = "aws_cdk_asset_node_proxy_agent_v6-2.1.2.tar.gz", hash = "sha256:1340588dd351dcae37e07188f39075364f73ccde6ed9468c1184b06ada4af665"}, ] [package.dependencies] -jsii = ">=1.103.1,<2.0.0" +jsii = ">=1.129.0,<2.0.0" publication = ">=0.0.3" -typeguard = ">=2.13.3,<5.0.0" +typeguard = "2.13.3" [[package]] name = "aws-cdk-cloud-assembly-schema" -version = "48.18.0" +version = "53.28.0" description = "Schema for the protocol between CDK framework and CDK CLI" optional = false -python-versions = "~=3.9" +python-versions = "~=3.10" groups = ["main"] files = [ - {file = "aws_cdk_cloud_assembly_schema-48.18.0-py3-none-any.whl", hash = "sha256:12b193fde580828d8c4909cfa62e1f83977fe20d0aa448c7e7e353f8e21e1b68"}, - {file = "aws_cdk_cloud_assembly_schema-48.18.0.tar.gz", hash = "sha256:dc8d1bbe09bca45d675fa7d5c59fd7c073ed86865fc97dc985c6a4caf1016b42"}, + {file = "aws_cdk_cloud_assembly_schema-53.28.0-py3-none-any.whl", hash = "sha256:c5de34f4a0d61eb48574a0264a9567175f601c27b4d053fb24ad1157c4ea0d99"}, + {file = "aws_cdk_cloud_assembly_schema-53.28.0.tar.gz", hash = "sha256:12e28dc44026e5f062041ba1450a510b1acddcfbe8358f73cfda8df993712d42"}, ] [package.dependencies] -jsii = ">=1.118.0,<2.0.0" +jsii = ">=1.131.0,<2.0.0" publication = ">=0.0.3" -typeguard = ">=2.13.3,<4.3.0" +typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.223.0" +version = "2.253.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["main"] files = [ - {file = "aws_cdk_lib-2.223.0-py3-none-any.whl", hash = "sha256:c6070a9449b2ce48987855ce273e65b9b18a134d98110ac86f23a393e1bf0b84"}, - {file = "aws_cdk_lib-2.223.0.tar.gz", hash = "sha256:8d2ea3c2754d1022db19f59e0558a9b23b26317a95b1327c502ca8afd94c5830"}, + {file = "aws_cdk_lib-2.253.0-py3-none-any.whl", hash = "sha256:58997c8a5af49d5328f5106468581a14235a1356dfe7574bb14656799594a2b5"}, + {file = "aws_cdk_lib-2.253.0.tar.gz", hash = "sha256:6db33e164f9afd6207698d382579bf62f762f14325f4b6d77643865e92448f20"}, ] [package.dependencies] -"aws-cdk.asset-awscli-v1" = "2.2.242" -"aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.0,<3.0.0" -"aws-cdk.cloud-assembly-schema" = ">=48.6.0,<49.0.0" -constructs = ">=10.0.0,<11.0.0" -jsii = ">=1.118.0,<2.0.0" +"aws-cdk.asset-awscli-v1" = "2.2.273" +"aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.1,<3.0.0" +"aws-cdk.cloud-assembly-schema" = ">=53.18.0,<54.0.0" +constructs = ">=10.5.0,<11.0.0" +jsii = ">=1.128.0,<2.0.0" publication = ">=0.0.3" -typeguard = ">=2.13.3,<4.3.0" +typeguard = "2.13.3" [[package]] name = "boto3" @@ -166,20 +166,19 @@ files = [ [[package]] name = "constructs" -version = "10.4.3" +version = "10.8.1" description = "A programming model for software-defined state" optional = false -python-versions = "~=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "constructs-10.4.3-py3-none-any.whl", hash = "sha256:43bbefa1ac1c044577d0b1a30648fe5b49557b8b95de2648186f6b909febf7f9"}, - {file = "constructs-10.4.3.tar.gz", hash = "sha256:bfe3657b0acb62af7aa1fda9a7e338ae5cae84ddf8f84f71125a2a3800d52ea0"}, + {file = "constructs-10.8.1-py3-none-any.whl", hash = "sha256:f71297db64723889147c82de46dcacaa76b120f856d5b5ac5f65abb22ea88355"}, + {file = "constructs-10.8.1.tar.gz", hash = "sha256:9f6e4eb1f6b8b1ac8dcbc85457dcbb1e3f9bd93bbeef03154f6cc7fbbba74b06"}, ] [package.dependencies] -jsii = ">=1.118.0,<2.0.0" +jsii = ">=1.139.0,<2.0.0" publication = ">=0.0.3" -typeguard = ">=2.13.3,<4.3.0" [[package]] name = "exceptiongroup" @@ -200,26 +199,6 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} [package.extras] test = ["pytest (>=6)"] -[[package]] -name = "importlib-resources" -version = "6.5.2" -description = "Read resources from Python packages" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec"}, - {file = "importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "zipp (>=3.17)"] -type = ["pytest-mypy"] - [[package]] name = "iniconfig" version = "2.3.0" @@ -246,23 +225,22 @@ files = [ [[package]] name = "jsii" -version = "1.119.0" +version = "1.139.0" description = "Python client for jsii runtime" optional = false -python-versions = "~=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "jsii-1.119.0-py3-none-any.whl", hash = "sha256:9203200ed5289ecc6198783513cbd7abef53d4f6eac0046181d647fa56eda6ab"}, - {file = "jsii-1.119.0.tar.gz", hash = "sha256:9f87508908bfa51dd9aac59fdbbeff347ae76377758ea5e5f83f149052211514"}, + {file = "jsii-1.139.0-py3-none-any.whl", hash = "sha256:11468f767c6da698ed9888a04352850af33ccccfec7656475626caf36fca8bbb"}, + {file = "jsii-1.139.0.tar.gz", hash = "sha256:163c5d3ec00fd4ec89a33b9097f20a6f27626dd69d6875a8f7cc7577b8021ad0"}, ] [package.dependencies] -attrs = ">=21.2,<26.0" -cattrs = ">=1.8,<25.4" -importlib_resources = ">=5.2.0" +attrs = ">=21.2,<27.0" +cattrs = ">=1.8,<27.0" publication = ">=0.0.3" python-dateutil = "*" -typeguard = ">=2.13.3,<4.5.0" +typeguard = "2.13.3" typing_extensions = ">=3.8,<5.0" [[package]] @@ -372,10 +350,10 @@ files = [ ] [package.dependencies] -botocore = ">=1.37.4,<2.0a.0" +botocore = ">=1.37.4,<2.0a0" [package.extras] -crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"] +crt = ["botocore[crt] (>=1.37.4,<2.0a0)"] [[package]] name = "six" @@ -444,22 +422,19 @@ files = [ [[package]] name = "typeguard" -version = "4.2.1" +version = "2.13.3" description = "Run-time type checker for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.5.3" groups = ["main"] files = [ - {file = "typeguard-4.2.1-py3-none-any.whl", hash = "sha256:7da3bd46e61f03e0852f8d251dcbdc2a336aa495d7daff01e092b55327796eb8"}, - {file = "typeguard-4.2.1.tar.gz", hash = "sha256:c556a1b95948230510070ca53fa0341fb0964611bd05d598d87fb52115d65fee"}, + {file = "typeguard-2.13.3-py3-none-any.whl", hash = "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1"}, + {file = "typeguard-2.13.3.tar.gz", hash = "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.10.0", markers = "python_version < \"3.13\""} - [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage[toml] (>=7)", "mypy (>=1.2.0) ; platform_python_implementation != \"PyPy\"", "pytest (>=7)"] +doc = ["sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["mypy ; platform_python_implementation != \"PyPy\"", "pytest", "typing-extensions"] [[package]] name = "typing-extensions" From 90298f59a0036b8549914700a430200799b33e6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:46:25 +0200 Subject: [PATCH 46/76] chore(deps): bump the github-actions group across 1 directory with 9 updates (#8357) Bumps the github-actions group with 9 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `7.0.0` | `7.0.1` | | [actions/setup-node](https://github.com/actions/setup-node) | `6.4.0` | `7.0.0` | | [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) | `6.2.1` | `6.2.3` | | [actions/setup-go](https://github.com/actions/setup-go) | `6.5.0` | `7.0.0` | | [ossf/scorecard-action](https://github.com/ossf/scorecard-action) | `2.4.3` | `2.4.4` | | [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.36.3` | `4.37.3` | | [actions/setup-python](https://github.com/actions/setup-python) | `6.3.0` | `7.0.0` | | [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.14.0` | `1.14.1` | | [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) | `7.5.1` | `7.6.0` | Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1) Updates `actions/setup-node` from 6.4.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020) Updates `aws-actions/configure-aws-credentials` from 6.2.1 to 6.2.3 - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/254c19bd240aabef8777f48595e9d2d7b972184b...e6de054238d6b7531b4efff3b6587d9aade6a06c) Updates `actions/setup-go` from 6.5.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/924ae3a1cded613372ab5595356fb5720e22ba16...b7ad1dad31e06c5925ef5d2fc7ad053ef454303e) Updates `ossf/scorecard-action` from 2.4.3 to 2.4.4 - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/4eaacf0543bb3f2c246792bd56e8cdeffafb205a...2d1146689b8cda280b9bc96326124645441f03bc) Updates `github/codeql-action/upload-sarif` from 4.36.3 to 4.37.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/54f647b7e1bb85c95cddabcd46b0c578ec92bc1a...e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81) Updates `actions/setup-python` from 6.3.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/ece7cb06caefa5fff74198d8649806c4678c61a1...5fda3b95a4ea91299a34e894583c3862153e4b97) Updates `pypa/gh-action-pypi-publish` from 1.14.0 to 1.14.1 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/cef221092ed1bacb1cc03d23a2d87d1d172e277b...ba38be9e461d3875417946c167d0b5f3d385a247) Updates `release-drafter/release-drafter` from 7.5.1 to 7.6.0 - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/4d75298e00d9e34c483e5ff8c68d0ea1c1940c1e...eada3c96a64734dd381cfbda23511034e328ddb0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/setup-node dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: aws-actions/configure-aws-credentials dependency-version: 6.2.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/setup-go dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: ossf/scorecard-action dependency-version: 2.4.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/upload-sarif dependency-version: 4.37.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/setup-python dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: pypa/gh-action-pypi-publish dependency-version: 1.14.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: release-drafter/release-drafter dependency-version: 7.6.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .github/workflows/bootstrap_region.yml | 10 ++++----- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/layer_govcloud.yml | 6 ++--- .../workflows/layer_govcloud_python313.yml | 6 ++--- .github/workflows/layer_govcloud_verify.yml | 6 ++--- .github/workflows/layers_partition_verify.yml | 4 ++-- .github/workflows/layers_partitions.yml | 4 ++-- .github/workflows/ossf_scorecard.yml | 6 ++--- .github/workflows/pre-release.yml | 16 +++++++------- .github/workflows/publish_v3_layer.yml | 8 +++---- .github/workflows/quality_check.yml | 4 ++-- .github/workflows/quality_check_docs.yml | 4 ++-- .../quality_code_cdk_constructor.yml | 4 ++-- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release-v3.yml | 22 +++++++++---------- .../reusable_deploy_v3_layer_stack.yml | 8 +++---- .github/workflows/reusable_deploy_v3_sar.yml | 8 +++---- .../workflows/reusable_publish_changelog.yml | 2 +- .github/workflows/reusable_publish_docs.yml | 6 ++--- .github/workflows/run-e2e-tests.yml | 8 +++---- .github/workflows/secure_workflows.yml | 2 +- .github/workflows/update_ssm.yml | 2 +- 23 files changed, 71 insertions(+), 71 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index 5f4ed90a940..fafa01fbc1a 100644 --- a/.github/workflows/bootstrap_region.yml +++ b/.github/workflows/bootstrap_region.yml @@ -44,18 +44,18 @@ jobs: environment: layer-${{ inputs.environment }} steps: - name: checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ github.sha }} - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "22" - name: Setup dependencies uses: aws-powertools/actions/.github/actions/cached-node-modules@4bf64a4072489399fbf39b78f558eeeed6767189 - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c with: aws-region: ${{ inputs.region }} role-to-assume: ${{ secrets.REGION_IAM_ROLE }} @@ -96,14 +96,14 @@ jobs: steps: - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: aws-region: us-east-1 role-to-assume: ${{ secrets.REGION_IAM_ROLE }} mask-aws-account-id: true - id: go-setup name: Setup Go - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: '>=1.23.0' - id: go-env diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 252d7d2ca98..377e2bdbe2a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 4d0770f3a4a..aa2c90007c0 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -20,6 +20,6 @@ jobs: pull-requests: write steps: - name: 'Checkout Repository' - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: 'Dependency Review' uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 diff --git a/.github/workflows/layer_govcloud.yml b/.github/workflows/layer_govcloud.yml index 0c7d51bc72c..bcb0005308d 100644 --- a/.github/workflows/layer_govcloud.yml +++ b/.github/workflows/layer_govcloud.yml @@ -60,7 +60,7 @@ jobs: environment: Prod (Readonly) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -118,7 +118,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 @@ -188,7 +188,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-west-1 diff --git a/.github/workflows/layer_govcloud_python313.yml b/.github/workflows/layer_govcloud_python313.yml index 9d09050d613..285ed0081ea 100644 --- a/.github/workflows/layer_govcloud_python313.yml +++ b/.github/workflows/layer_govcloud_python313.yml @@ -55,7 +55,7 @@ jobs: environment: Prod (Readonly) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -108,7 +108,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 @@ -173,7 +173,7 @@ jobs: SHA=$(jq -r '.Content.CodeSha256' '${{ matrix.layer }}_${{ matrix.arch }}.json') test "$(openssl dgst -sha256 -binary ${{ matrix.layer }}_${{ matrix.arch }}.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1 - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-west-1 diff --git a/.github/workflows/layer_govcloud_verify.yml b/.github/workflows/layer_govcloud_verify.yml index 23cccc7b9d5..373029036db 100644 --- a/.github/workflows/layer_govcloud_verify.yml +++ b/.github/workflows/layer_govcloud_verify.yml @@ -40,7 +40,7 @@ jobs: environment: Prod (Readonly) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -71,7 +71,7 @@ jobs: environment: GovCloud Prod (East) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 @@ -103,7 +103,7 @@ jobs: environment: GovCloud Prod (West) steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-gov-east-1 diff --git a/.github/workflows/layers_partition_verify.yml b/.github/workflows/layers_partition_verify.yml index c3701ca6179..4500a8a0ee9 100644 --- a/.github/workflows/layers_partition_verify.yml +++ b/.github/workflows/layers_partition_verify.yml @@ -88,7 +88,7 @@ jobs: - x86_64 steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -138,7 +138,7 @@ jobs: run: | echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT" - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }} aws-region: ${{ matrix.region}} diff --git a/.github/workflows/layers_partitions.yml b/.github/workflows/layers_partitions.yml index 31818c7d61d..3d6246e5197 100644 --- a/.github/workflows/layers_partitions.yml +++ b/.github/workflows/layers_partitions.yml @@ -85,7 +85,7 @@ jobs: - x86_64 steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -150,7 +150,7 @@ jobs: run: | echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT" - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }} aws-region: ${{ matrix.region}} diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index eecaa99f832..1914df80a33 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -22,12 +22,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4 with: results_file: results.sarif results_format: sarif @@ -43,6 +43,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3 + uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 with: sarif_file: results.sarif diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index e58c2d0c569..0f45bbfa381 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -59,7 +59,7 @@ jobs: artifact_name: ${{ steps.seal_source_code.outputs.artifact_name }} RELEASE_VERSION: ${{ steps.release_version.outputs.RELEASE_VERSION }} steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -99,7 +99,7 @@ jobs: contents: read steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -115,7 +115,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.14" cache: "poetry" @@ -140,7 +140,7 @@ jobs: attestation_hashes: ${{ steps.encoded_hash.outputs.attestation_hashes }} steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -153,7 +153,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.14" cache: "poetry" @@ -209,7 +209,7 @@ jobs: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} steps: # NOTE: we need actions/checkout in order to use our local actions (e.g., ./.github/actions) - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -221,7 +221,7 @@ jobs: - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 + uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 # Creates a PR with the latest version we've just released # since our trunk is protected against any direct pushes from automation @@ -233,7 +233,7 @@ jobs: runs-on: ubuntu-latest steps: # NOTE: we need actions/checkout to authenticate and configure git first - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} diff --git a/.github/workflows/publish_v3_layer.yml b/.github/workflows/publish_v3_layer.yml index 41bea487d57..456533b055e 100644 --- a/.github/workflows/publish_v3_layer.yml +++ b/.github/workflows/publish_v3_layer.yml @@ -108,7 +108,7 @@ jobs: working-directory: ./layer_v3 steps: - name: checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -123,11 +123,11 @@ jobs: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 pipx inject poetry git+https://github.com/python-poetry/poetry-plugin-export@8c83d26603ca94f2e203bfded7b6d7f530960e06 # v1.8.0 - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "18.20.4" - name: Setup python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} cache: "pip" @@ -264,7 +264,7 @@ jobs: pages: none steps: - name: Checkout repository # reusable workflows start clean, so we need to checkout again - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml index f894553b79a..d434dbc841e 100644 --- a/.github/workflows/quality_check.yml +++ b/.github/workflows/quality_check.yml @@ -52,11 +52,11 @@ jobs: permissions: contents: read # checkout code only steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install poetry run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/quality_check_docs.yml b/.github/workflows/quality_check_docs.yml index afc3ed9f05a..2506412fc5d 100644 --- a/.github/workflows/quality_check_docs.yml +++ b/.github/workflows/quality_check_docs.yml @@ -35,9 +35,9 @@ jobs: permissions: contents: read # checkout code only steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: 3.14 - name: Install doc generation dependencies diff --git a/.github/workflows/quality_code_cdk_constructor.yml b/.github/workflows/quality_code_cdk_constructor.yml index 5982d7dc1bf..cedb82b82bc 100644 --- a/.github/workflows/quality_code_cdk_constructor.yml +++ b/.github/workflows/quality_code_cdk_constructor.yml @@ -42,11 +42,11 @@ jobs: run: working-directory: ./layer_v3/layer_constructors steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install poetry run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} cache: "poetry" diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index ea31f077e5c..6f9d3cf5cd7 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -27,4 +27,4 @@ jobs: permissions: contents: write # create release in draft mode steps: - - uses: release-drafter/release-drafter@4d75298e00d9e34c483e5ff8c68d0ea1c1940c1e # v7.5.1 + - uses: release-drafter/release-drafter@eada3c96a64734dd381cfbda23511034e328ddb0 # v7.6.0 diff --git a/.github/workflows/release-v3.yml b/.github/workflows/release-v3.yml index f5588fad0ae..a4d9e36937d 100644 --- a/.github/workflows/release-v3.yml +++ b/.github/workflows/release-v3.yml @@ -89,7 +89,7 @@ jobs: RELEASE_VERSION="${RELEASE_TAG_VERSION:1}" echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "$GITHUB_OUTPUT" - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -124,7 +124,7 @@ jobs: contents: read steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -140,7 +140,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.14" cache: "poetry" @@ -165,7 +165,7 @@ jobs: attestation_hashes: ${{ steps.encoded_hash.outputs.attestation_hashes }} steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -178,7 +178,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.14" cache: "poetry" @@ -234,7 +234,7 @@ jobs: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} steps: # NOTE: we need actions/checkout in order to use our local actions (e.g., ./.github/actions) - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -246,12 +246,12 @@ jobs: - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 + uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 # PyPi test maintenance affected us numerous times, leaving for history purposes # - name: Upload to PyPi test # if: ${{ !inputs.skip_pypi }} - # uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 + # uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 # with: # repository-url: https://test.pypi.org/legacy/ @@ -268,7 +268,7 @@ jobs: contents: write steps: # NOTE: we need actions/checkout to authenticate and configure git first - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -312,7 +312,7 @@ jobs: runs-on: ubuntu-latest steps: # NOTE: we need actions/checkout to authenticate and configure git first - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -368,7 +368,7 @@ jobs: env: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} - name: Restore sealed source code diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index b6e2840e082..ef0bb9a5cc2 100644 --- a/.github/workflows/reusable_deploy_v3_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v3_layer_stack.yml @@ -142,7 +142,7 @@ jobs: has_arm64_support: "true" steps: - name: checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -157,17 +157,17 @@ jobs: pipx install git+https://github.com/python-poetry/poetry@bd500dd3bdfaec3de6894144c9cedb3a9358be84 # v2.0.1 pipx inject poetry git+https://github.com/python-poetry/poetry-plugin-export@8c83d26603ca94f2e203bfded7b6d7f530960e06 # v1.8.0 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} mask-aws-account-id: true - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "18.20.4" - name: Setup python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} cache: "pip" diff --git a/.github/workflows/reusable_deploy_v3_sar.yml b/.github/workflows/reusable_deploy_v3_sar.yml index ba2af3bb190..f72519ecc5d 100644 --- a/.github/workflows/reusable_deploy_v3_sar.yml +++ b/.github/workflows/reusable_deploy_v3_sar.yml @@ -75,7 +75,7 @@ jobs: python-version: ["3.10","3.11","3.12","3.13","3.14"] steps: - name: checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ env.RELEASE_COMMIT }} @@ -87,7 +87,7 @@ jobs: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} @@ -98,7 +98,7 @@ jobs: # we then jump to our specific SAR Account with the correctly scoped IAM Role # this allows us to have a single trail when a release occurs for a given layer (beta+prod+SAR beta+SAR prod) - name: AWS credentials SAR role - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 id: aws-credentials-sar-role with: aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} @@ -109,7 +109,7 @@ jobs: role-to-assume: ${{ secrets.AWS_SAR_V3_ROLE_ARN }} mask-aws-account-id: true - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: ${{ env.NODE_VERSION }} - name: Download artifact diff --git a/.github/workflows/reusable_publish_changelog.yml b/.github/workflows/reusable_publish_changelog.yml index eb862970d4f..cb7d62285f3 100644 --- a/.github/workflows/reusable_publish_changelog.yml +++ b/.github/workflows/reusable_publish_changelog.yml @@ -26,7 +26,7 @@ jobs: pull-requests: write # create PR steps: - name: Checkout repository # reusable workflows start clean, so we need to checkout again - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - name: "Generate latest changelog" diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 27b4b9642b0..6507e4922f9 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -42,12 +42,12 @@ jobs: permissions: id-token: write # trade JWT token for AWS credentials in AWS Docs account steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 ref: ${{ inputs.git_ref }} - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.12" - name: Install doc generation dependencies @@ -68,7 +68,7 @@ jobs: env: BRANCH: ${{ inputs.git_ref }} - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 10ac5126934..ce1457abc91 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -52,17 +52,17 @@ jobs: if: ${{ github.actor != 'dependabot[bot]' && github.repository == 'aws-powertools/powertools-lambda-python' }} steps: - name: "Checkout" - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install poetry run: pipx install poetry - name: "Use Python" - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.version }} architecture: "x64" cache: "poetry" - name: Setup Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "20.10.0" - name: Install CDK CLI @@ -72,7 +72,7 @@ jobs: - name: Install dependencies run: make dev-quality-code - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: ${{ secrets.AWS_TEST_ROLE_ARN }} aws-region: ${{ env.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index 00f0b3069a3..25d88bf8d09 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -30,7 +30,7 @@ jobs: contents: read # checkout code and subsequently GitHub action workflows steps: - name: Checkout code - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Ensure 3rd party workflows have SHA pinned uses: zgosalvez/github-actions-ensure-sha-pinned-actions@3db98c0363e2fa5df3e1c4c471777a7c10b24cc9 # v5.0.5 with: diff --git a/.github/workflows/update_ssm.yml b/.github/workflows/update_ssm.yml index 056f2674d88..c71eafa1d86 100644 --- a/.github/workflows/update_ssm.yml +++ b/.github/workflows/update_ssm.yml @@ -89,7 +89,7 @@ jobs: run: | echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT" - id: creds - uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1 + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets[format('{0}', steps.transform.outputs.CONVERTED_REGION)] }} From a563cf06cb457799d9ee8f6a17698f5a90247eac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:47:53 +0200 Subject: [PATCH 47/76] chore(deps-dev): bump aws-cdk from 2.1129.0 to 2.1130.0 in the aws-cdk group (#8339) chore(deps-dev): bump aws-cdk in the aws-cdk group Bumps the aws-cdk group with 1 update: [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `aws-cdk` from 2.1129.0 to 2.1130.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1130.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1130.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index e8b56763f3b..6f1be92be0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,13 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1129.0" + "aws-cdk": "^2.1130.0" } }, "node_modules/aws-cdk": { - "version": "2.1129.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1129.0.tgz", - "integrity": "sha512-M0EWbjeKW+baUsirjtKuWh7w/9dPxF8taEi2hqo9ecCjGeQxV1dzyosJf+caR3Jh7dFyyT3J8zEtRb/cU971Rw==", + "version": "2.1130.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1130.0.tgz", + "integrity": "sha512-LgSKHFTGhoT/lML48uiYIpdSHCwZLvUx/uZu5MqcZjh+OwWzM8nCxXY+OjKG3yASlx5JxeulXm4sRaUYo48qFQ==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index b43ac00bdbd..55619510bcc 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1129.0" + "aws-cdk": "^2.1130.0" } } From 4c4b98f7194bece5b3ca9028313ed99225f854fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:49:04 +0200 Subject: [PATCH 48/76] chore(deps): bump pymdown-extensions from 10.21.3 to 11.0 in /docs (#8358) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.21.3 to 11.0. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.21.3...11.0) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: '11.0' dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- docs/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 441befb4538..dfb60bc395e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -324,9 +324,9 @@ pygments==2.19.2 \ --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b # via mkdocs-material -pymdown-extensions==10.21.3 \ - --hash=sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354 \ - --hash=sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6 +pymdown-extensions==11.0 \ + --hash=sha256:8269cef0247f9e2d0a62fcea10860aba05c1cbab5470fd4b63230b96434dc589 \ + --hash=sha256:fbc4acb641814fa9d17521bbd21a5240ef739a662f11c06330c4b78c93e954d6 # via # mkdocs-material # mkdocstrings From 94b84a3e0cf3733c9092417f98e9019702339ac8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:51:41 +0200 Subject: [PATCH 49/76] chore(deps): bump mkdocstrings-python from 1.19.0 to 2.0.5 (#8344) Bumps [mkdocstrings-python](https://github.com/mkdocstrings/python) from 1.19.0 to 2.0.5. - [Release notes](https://github.com/mkdocstrings/python/releases) - [Changelog](https://github.com/mkdocstrings/python/blob/main/CHANGELOG.md) - [Commits](https://github.com/mkdocstrings/python/compare/1.19.0...2.0.5) --- updated-dependencies: - dependency-name: mkdocstrings-python dependency-version: 2.0.5 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 45 +++++---------------------------------------- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 41 deletions(-) diff --git a/poetry.lock b/poetry.lock index eaf80ca0b49..1e7bbf0495b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1937,41 +1937,6 @@ gitdb = ">=4.0.1,<5" doc = ["sphinx (>=7.4.7,<8)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] test = ["basedpyright (==1.39.9) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy (==1.18.2) ; python_version >= \"3.9\"", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] -[[package]] -name = "griffe" -version = "2.0.0" -description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." -optional = false -python-versions = ">=3.10" -groups = ["dev"] -files = [ - {file = "griffe-2.0.0-py3-none-any.whl", hash = "sha256:5418081135a391c3e6e757a7f3f156f1a1a746cc7b4023868ff7d5e2f9a980aa"}, - {file = "griffe-2.0.0.tar.gz", hash = "sha256:c68979cd8395422083a51ea7cf02f9c119d889646d99b7b656ee43725de1b80f"}, -] - -[package.dependencies] -griffecli = "2.0.0" -griffelib = "2.0.0" - -[package.extras] -pypi = ["griffelib[pypi] (==2.0.0)"] - -[[package]] -name = "griffecli" -version = "2.0.0" -description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." -optional = false -python-versions = ">=3.10" -groups = ["dev"] -files = [ - {file = "griffecli-2.0.0-py3-none-any.whl", hash = "sha256:9f7cd9ee9b21d55e91689358978d2385ae65c22f307a63fb3269acf3f21e643d"}, - {file = "griffecli-2.0.0.tar.gz", hash = "sha256:312fa5ebb4ce6afc786356e2d0ce85b06c1c20d45abc42d74f0cda65e159f6ef"}, -] - -[package.dependencies] -colorama = ">=0.4" -griffelib = "2.0.0" - [[package]] name = "griffelib" version = "2.0.0" @@ -2860,18 +2825,18 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] [[package]] name = "mkdocstrings-python" -version = "1.19.0" +version = "2.0.5" description = "A Python handler for mkdocstrings." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mkdocstrings_python-1.19.0-py3-none-any.whl", hash = "sha256:395c1032af8f005234170575cc0c5d4d20980846623b623b35594281be4a3059"}, - {file = "mkdocstrings_python-1.19.0.tar.gz", hash = "sha256:917aac66cf121243c11db5b89f66b0ded6c53ec0de5318ff5e22424eb2f2e57c"}, + {file = "mkdocstrings_python-2.0.5-py3-none-any.whl", hash = "sha256:30c837bbff016549f659fcba6539ac351303f0fd7e713c89a040611072236e9d"}, + {file = "mkdocstrings_python-2.0.5.tar.gz", hash = "sha256:3a4d92556ad39637e88af94a5374213af9a8e3040c3824ceaed04b486c017594"}, ] [package.dependencies] -griffe = ">=1.13" +griffelib = ">=2.0" mkdocs-autorefs = ">=1.4" mkdocstrings = ">=0.30" typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} @@ -5217,4 +5182,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "76b052fac1e517cf35f1c4ffea334118266db8464384a5c7dad9211439985034" +content-hash = "08e37143f0927393aa997ebc6fe2a3324415f29d9086f6ba4f8d3a0815db7e42" diff --git a/pyproject.toml b/pyproject.toml index 4178dca4616..b6485f7ff20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,7 +124,7 @@ testcontainers = { extras = ["redis"], version = ">=3.7.1,<5.0.0" } multiprocess = "^0.70.16" boto3-stubs = {extras = ["appconfig", "appconfigdata", "cloudformation", "cloudwatch", "dynamodb", "lambda", "logs", "s3", "secretsmanager", "ssm", "xray"], version = "^1.34.139"} nox = ">=2024.4.15,<2027.0.0" -mkdocstrings-python = "^1.13.0" +mkdocstrings-python = ">=1.13,<3.0" mkdocs-llmstxt = ">=0.2,<0.5" avro = "^1.12.0" protobuf = ">=6.30.2,<8.0.0" From 074150f785f9c090603133e942feaae673cbe943 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:55:03 +0200 Subject: [PATCH 50/76] chore(deps): bump valkey-glide from 2.4.1 to 2.5.0 (#8345) Bumps [valkey-glide](https://github.com/valkey-io/valkey-glide) from 2.4.1 to 2.5.0. - [Release notes](https://github.com/valkey-io/valkey-glide/releases) - [Changelog](https://github.com/valkey-io/valkey-glide/blob/main/CHANGELOG.md) - [Commits](https://github.com/valkey-io/valkey-glide/compare/v2.4.1...v2.5.0) --- updated-dependencies: - dependency-name: valkey-glide dependency-version: 2.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 131 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 43 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1e7bbf0495b..77986c7abce 100644 --- a/poetry.lock +++ b/poetry.lock @@ -29,6 +29,7 @@ markers = {main = "extra == \"valkey\""} [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" +trio = {version = ">=0.32.0", optional = true, markers = "python_version >= \"3.10\" and extra == \"trio\""} typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] @@ -116,7 +117,7 @@ files = [ {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"}, {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"}, ] -markers = {main = "extra == \"all\" or extra == \"datamasking\""} +markers = {main = "extra == \"valkey\" or extra == \"all\" or extra == \"datamasking\""} [[package]] name = "avro" @@ -1181,7 +1182,7 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] -markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\""} +markers = {main = "(extra == \"all\" or extra == \"datamasking\" or extra == \"valkey\") and (platform_python_implementation != \"PyPy\" or extra == \"valkey\")", dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -2055,7 +2056,7 @@ files = [ {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, ] -markers = {main = "extra == \"datadog\" or extra == \"valkey\""} +markers = {main = "extra == \"valkey\" or extra == \"datadog\""} [package.extras] all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] @@ -3250,6 +3251,22 @@ files = [ importlib-metadata = ">=6.0,<8.8.0" typing-extensions = ">=4.5.0" +[[package]] +name = "outcome" +version = "1.3.0.post0" +description = "Capture the outcome of Python function calls." +optional = true +python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"valkey\"" +files = [ + {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"}, + {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"}, +] + +[package.dependencies] +attrs = ">=19.2.0" + [[package]] name = "packaging" version = "26.0" @@ -3378,7 +3395,7 @@ files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] -markers = {main = "(extra == \"all\" or extra == \"datamasking\") and platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""} +markers = {main = "(extra == \"all\" or extra == \"datamasking\" or extra == \"valkey\") and (platform_python_implementation != \"PyPy\" or extra == \"valkey\") and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""} [[package]] name = "pydantic" @@ -4447,6 +4464,19 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"valkey\"" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "soupsieve" version = "2.8.4" @@ -4603,6 +4633,28 @@ files = [ {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, ] +[[package]] +name = "trio" +version = "0.33.0" +description = "A friendly Python library for async concurrency and I/O" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"valkey\"" +files = [ + {file = "trio-0.33.0-py3-none-any.whl", hash = "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b"}, + {file = "trio-0.33.0.tar.gz", hash = "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970"}, +] + +[package.dependencies] +attrs = ">=23.2.0" +cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +idna = "*" +outcome = "*" +sniffio = ">=1.3.0" +sortedcontainers = "*" + [[package]] name = "ty" version = "0.0.49" @@ -4922,54 +4974,47 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "valkey-glide" -version = "2.4.1" +version = "2.5.0" description = "Valkey GLIDE Async client. Supports Valkey and Redis OSS." optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"valkey\"" files = [ - {file = "valkey_glide-2.4.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:91c7ab69c121b28a21b3e36a084a792dfc21be7221a667c535dc7f36d4fb0e4b"}, - {file = "valkey_glide-2.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:68a4fa31431927f43d1fe7a34809ed3cde9a437d7ac7ec5af51871e4cf272edb"}, - {file = "valkey_glide-2.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f37d059d71520ac1bd25469cd4b67d87ea8cab995cc25af48d83d19469fd3048"}, - {file = "valkey_glide-2.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:927b85451f54e56e6469c321cf672f7ce47c597bf1c480dd1925f07d8c6b1971"}, - {file = "valkey_glide-2.4.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:d7285d03c2df040f26874b7f4ae96f040da2daecc9a34fa99da6f4e6ce5149c8"}, - {file = "valkey_glide-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d2e82b74127897ccb7a957ad455787816a75fdc8c60a5e8004aef65ea93e99c"}, - {file = "valkey_glide-2.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4094128cb07e06e87013b7afab1e9388f8f5aeebe48ea6cbd54de15bd772e644"}, - {file = "valkey_glide-2.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f8dc0f3a36adb1cbe4e167972ca4758acdfed6baf58a4db94bbb713df56c8f5"}, - {file = "valkey_glide-2.4.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:5f8df64f6a4f0fd7203113103101fdf0aaa7ff0e7557312611de11ab89c6db75"}, - {file = "valkey_glide-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b45e35f44c17e88f8cd8082f8d8061a9763238c44ef20b11b615f6d87235864a"}, - {file = "valkey_glide-2.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf812b498925a30abab6e1a9f82f5eb821e967904fe7724729b2c82c47e29edf"}, - {file = "valkey_glide-2.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:214e2faca98966eea3eaf9e09de616862423815a5059843a9884125e2427a344"}, - {file = "valkey_glide-2.4.1-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:c18976553ba663c03f7cc18c7e6075f4cbd2236c18b051e3d55bb213c6c44cb4"}, - {file = "valkey_glide-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:43006e19cd63d66051263fa34a8ad47ba7d08a199585689b3f12f56ed6c9a005"}, - {file = "valkey_glide-2.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b652a2a62aad87738e8f0e0aa5bf660ba91449c9fdb88550ccbc42e5fec08fe7"}, - {file = "valkey_glide-2.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd27d26947fd9f1b6e9eaf0abce4bccfde779c1e618b310c4d725424b609793"}, - {file = "valkey_glide-2.4.1-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:91fb7ff97acdabc8f641255b548a48627bb731e65037b1126745bf8a0022e87d"}, - {file = "valkey_glide-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d49a2537c2de44b0fc57691b1ae6c3d6f481e6f7f7eb879c0d28921d0aaec67d"}, - {file = "valkey_glide-2.4.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cded9f14e448da5a96f61c066395f2c7e2846f2afe74cacc8634da0ae0c3425f"}, - {file = "valkey_glide-2.4.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f249ab5bd0d69befe35897cf51a8fc9e01e9c8c9fe03087a68e6fe6d3e31d0d"}, - {file = "valkey_glide-2.4.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:87bf55231a35a786e93485b7d82c5775a287f969d2e0a16c99e877ac2460e29e"}, - {file = "valkey_glide-2.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6409985596b9f8adddbc62c0b5d1e192ce6467b0436d8d6a49dcaa3272fec4be"}, - {file = "valkey_glide-2.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eea949cba7fe3601d6dcd8e757885dfbf8af1b2654b1c81e5f64772bfa12c3f"}, - {file = "valkey_glide-2.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11d9ca55a7aab773ecb8fbad4efd186862ea4c911c9c522317eb2b10343ae567"}, - {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ade719b52a8a0c28f14792dd4fe9db718afce8e5a22e8289ffb430639744e419"}, - {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a29269ced9078b14c1de1c76412854021ca3acdad6476d89ea491a5cf7ddcae0"}, - {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1346846af82620def2303ef6085a31174ac80873931e455d29e1368c1ac7e359"}, - {file = "valkey_glide-2.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ad2f883ce828c4cbb892d472c9b3e21e714fc217f5a1ca80cfad110484d87a4"}, - {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:775df9c7421a187c41caf003e4af5f073ed7e4b8abe50f8b9bec712cb03e12bf"}, - {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0d87f21c77004240189cc3c5aab156966487afd81ffdee04225a52c7bd7132e4"}, - {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44376ef5fe7a25287095b073d8abde510a50b1ead0143662394b3da9717863ef"}, - {file = "valkey_glide-2.4.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a59cc0a21d7a8b1b3caeb299f23817429b5fe6579bd4cb016382e6b7a10de984"}, - {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f3ae6328f0e0a2e887791516192c881060f9407381bc8a80d288a48bd4351795"}, - {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0bcb83d35908ca34078785402b64dbf37073d5ff23d9da4890d93c2b3f09dc7"}, - {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdce17dc0aea468f17a85b92ac433bb91834e0c72c9d9530d81508186d4a9bea"}, - {file = "valkey_glide-2.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4ffe9c6b9b86a1064ac538d6ae4f85dffa56c9286400c82bc77eccc7286f0b4"}, - {file = "valkey_glide-2.4.1.tar.gz", hash = "sha256:f1155d84156d11b90488aa67e90102f0bf98a45314f5b99308ac9074c05f7241"}, + {file = "valkey_glide-2.5.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:10bd8e942f7bd462cca4e8578f67c4e32d246cf42a736da89c5b6e55c1198e27"}, + {file = "valkey_glide-2.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d207e8d3ebaa7f434a73b4f29b46296c44d4277c93c6e0ce2db0c0a4037f4715"}, + {file = "valkey_glide-2.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8a04a8f00ccbaea1d43c933dacfaefc0779608e0f306053b7bc2c9a6ec71a22"}, + {file = "valkey_glide-2.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee93ffd52845e5620774a65f43d751c9076505c9e29ea51263fcbc512893af1"}, + {file = "valkey_glide-2.5.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:df59c58ac08d66c4e730e7bab9f7e37c9cf30ca0e5b3ffa80f7e68abb0bfcc7b"}, + {file = "valkey_glide-2.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:40d67ea9bef44065809432e2a34193ada5a2a64b959f1f7b7572c5a055bdcb2d"}, + {file = "valkey_glide-2.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c4231e4290e06405729fd2b0c94febd6db861fe1a88e205627353d70e799473"}, + {file = "valkey_glide-2.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:284439b63dae97bc5dfa5266e39e9ba0868db9235932778599daa90b56fba2b2"}, + {file = "valkey_glide-2.5.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:95bc800473d5795e3db5eb9f64892cc0c4b79a4580320d51c90799f05ca815b9"}, + {file = "valkey_glide-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ea98b2b44bbfdfdc4fa6149b16136f67c59dd46e51f4e45c29136307c3177a3a"}, + {file = "valkey_glide-2.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9db2235a3190ec0b5bf3997c518a6c642f5e44c3a3c1ed70817ce5fc48815e6"}, + {file = "valkey_glide-2.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7893d63a3424ea43f9e2ab7ce2e31d628dea765f0ada09ab1b50b426f55d3863"}, + {file = "valkey_glide-2.5.0-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:cc6146d78545a85da2757ba0ac9d636b90fabdb45cc1a864f1c808381de942c5"}, + {file = "valkey_glide-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d8feb2a5ace38d1d88ba5c650b10273c5d862a55b0b5006d227aadd91e7c31e7"}, + {file = "valkey_glide-2.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bc80db5b2c191550ed716d28018520c7decc7853a2c2104c2d3654da3cd920e"}, + {file = "valkey_glide-2.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afecb53f774e7e376a757cda124bc08734b072cfdfcf703111b26afab5c24d2d"}, + {file = "valkey_glide-2.5.0-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:4a86f8451c5f8aa69f822782ba0ab64c77d8f6267844e2479b3267853dd076a5"}, + {file = "valkey_glide-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97b1d1bde85abf9783952e65b134368d0a575b5978b73c60fdde1d69d6bc6a69"}, + {file = "valkey_glide-2.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2d442a9aa0a2685023850950d76acaa689df1581f3028468c965e71b9009a83"}, + {file = "valkey_glide-2.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c90d9bb9c49059f0ddd8b50b1e84e924c7a8bd261be82376ab09cefbbf2b233"}, + {file = "valkey_glide-2.5.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:eca2618c59301ffd093108714ef09e69d67b4f8745ad65b7fd5514d378d3b6be"}, + {file = "valkey_glide-2.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19ccc9654f3e2da628fc7c6c15377a8f54046c73ab064530823649108a72fdef"}, + {file = "valkey_glide-2.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc0a0fe39b1cadf81b15b91051f6101913bdb4b78d986d20a4dace152921f3c"}, + {file = "valkey_glide-2.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60315782ada98d4d49ae842535d5045b6e2d40366c05be3d49c9c4563f9012cf"}, + {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:1bc0913efd997ed94136aac04d89fa73bb40525292a0182493c8c47bf24839b9"}, + {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d6c8127a6661d866c7fabb1830e6d8943536921e9f80033c6f095fdcec0ba28"}, + {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19a54a25fefa9e5839d0237625bf23e5f84df6a50eadac06181a9a99fb02e6c2"}, + {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47663a0432097746c3fc13f2e890280c003bfff7924f48f4f65c416750f4f368"}, + {file = "valkey_glide-2.5.0.tar.gz", hash = "sha256:21a9c037107af5ba3cdb27ed126abc02c75f9690dd6e82272f2a91042f4b8a2e"}, ] [package.dependencies] -anyio = ">=4.9.0" +anyio = {version = ">=4.9.0", extras = ["trio"]} +cffi = ">=1.0.0" protobuf = ">=3.20" sniffio = "*" typing-extensions = {version = ">=4.8.0", markers = "python_version < \"3.11\""} From ec8cd725a1b4f394ba37383346370c18d9dd8176 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:59:19 +0200 Subject: [PATCH 51/76] chore(deps-dev): bump types-requests from 2.33.0.20260518 to 2.33.0.20260712 (#8343) chore(deps-dev): bump types-requests Bumps [types-requests](https://github.com/python/typeshed) from 2.33.0.20260518 to 2.33.0.20260712. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-version: 2.33.0.20260712 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 77986c7abce..5e4a774d6bb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4784,14 +4784,14 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.33.0.20260518" +version = "2.33.0.20260712" description = "Typing stubs for requests" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_requests-2.33.0.20260518-py3-none-any.whl", hash = "sha256:626d697d1adaaff76e2044dc8c5c051d8f21abc157bdfe204a75558076fe0bf0"}, - {file = "types_requests-2.33.0.20260518.tar.gz", hash = "sha256:df7bd3bfe0ca8402dfb841e7d9be714bb5578203283d66d7dc4ef69343449a5e"}, + {file = "types_requests-2.33.0.20260712-py3-none-any.whl", hash = "sha256:de027e28c171d3da529689cbfa023b0b4eab188c8dfa22fd834eebd2cee6e7bb"}, + {file = "types_requests-2.33.0.20260712.tar.gz", hash = "sha256:2141b67ab534a5c5cd2dac5034f2a35f42e699c5bf185eee608c5246a069d7fb"}, ] [package.dependencies] From a12993833f183128e5f718e2b886ed752d8eeddc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:06:00 +0200 Subject: [PATCH 52/76] chore(deps-dev): bump pymdown-extensions from 10.21.3 to 11.0 (#8359) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.21.3 to 11.0. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.21.3...11.0) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: '11.0' dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5e4a774d6bb..3b76b62f619 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3596,14 +3596,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.21.3" +version = "11.0" description = "Extension pack for Python Markdown." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pymdown_extensions-10.21.3-py3-none-any.whl", hash = "sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6"}, - {file = "pymdown_extensions-10.21.3.tar.gz", hash = "sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354"}, + {file = "pymdown_extensions-11.0-py3-none-any.whl", hash = "sha256:fbc4acb641814fa9d17521bbd21a5240ef739a662f11c06330c4b78c93e954d6"}, + {file = "pymdown_extensions-11.0.tar.gz", hash = "sha256:8269cef0247f9e2d0a62fcea10860aba05c1cbab5470fd4b63230b96434dc589"}, ] [package.dependencies] From 957dde27b6481b061644122886fd176745442b61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Aug 2026 14:44:13 +0100 Subject: [PATCH 53/76] chore(deps-dev): bump pymdown-extensions from 11.0 to 11.0.1 (#8371) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 11.0 to 11.0.1. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/11.0...11.0.1) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: 11.0.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 3b76b62f619..9572f5d571b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3596,14 +3596,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "11.0" +version = "11.0.1" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pymdown_extensions-11.0-py3-none-any.whl", hash = "sha256:fbc4acb641814fa9d17521bbd21a5240ef739a662f11c06330c4b78c93e954d6"}, - {file = "pymdown_extensions-11.0.tar.gz", hash = "sha256:8269cef0247f9e2d0a62fcea10860aba05c1cbab5470fd4b63230b96434dc589"}, + {file = "pymdown_extensions-11.0.1-py3-none-any.whl", hash = "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2"}, + {file = "pymdown_extensions-11.0.1.tar.gz", hash = "sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0"}, ] [package.dependencies] From 4aae60981c556c352cad389ea0750f32dc662992 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Aug 2026 14:47:16 +0100 Subject: [PATCH 54/76] chore(deps-dev): bump gitpython from 3.1.57 to 3.1.58 (#8369) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.57 to 3.1.58. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.58 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9572f5d571b..ebf01c0c3a3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1921,14 +1921,14 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.57" +version = "3.1.58" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "gitpython-3.1.57-py3-none-any.whl", hash = "sha256:4ccf7d73c10f5c9e76043fbb2675ac5a1b3ff5b41e648f56bcbed5f63792ecaf"}, - {file = "gitpython-3.1.57.tar.gz", hash = "sha256:c493ec57c0ef6b19743798b6a5af859c71814b524e7e6f97baa2f8e658961488"}, + {file = "gitpython-3.1.58-py3-none-any.whl", hash = "sha256:d331e722577f0fd7fc1f857419b3ecc07af66282b933d2a4d95f84a042fdd50f"}, + {file = "gitpython-3.1.58.tar.gz", hash = "sha256:621416df10ef3fd0e19fabf9172ddeed0fa704d353d04f194eec56a625a95b22"}, ] [package.dependencies] From 29e07ef1b6687ca4c30adf3ab00951f1a9931ef5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Aug 2026 14:49:25 +0100 Subject: [PATCH 55/76] chore(deps): bump gitpython from 3.1.57 to 3.1.58 in /docs (#8368) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.57 to 3.1.58. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.58 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- docs/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index dfb60bc395e..b62a378ce26 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -139,9 +139,9 @@ gitdb==4.0.12 \ --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf # via gitpython -gitpython==3.1.57 \ - --hash=sha256:4ccf7d73c10f5c9e76043fbb2675ac5a1b3ff5b41e648f56bcbed5f63792ecaf \ - --hash=sha256:c493ec57c0ef6b19743798b6a5af859c71814b524e7e6f97baa2f8e658961488 +gitpython==3.1.58 \ + --hash=sha256:621416df10ef3fd0e19fabf9172ddeed0fa704d353d04f194eec56a625a95b22 \ + --hash=sha256:d331e722577f0fd7fc1f857419b3ecc07af66282b933d2a4d95f84a042fdd50f # via mkdocs-git-revision-date-plugin griffe==1.13.0 \ --hash=sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0 \ From 8de9a2809f92338b34edd1674061e062c83bca19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Aug 2026 14:50:44 +0100 Subject: [PATCH 56/76] chore(deps): bump pymdown-extensions from 11.0 to 11.0.1 in /docs (#8370) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 11.0 to 11.0.1. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/11.0...11.0.1) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: 11.0.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- docs/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index b62a378ce26..7a856dd6795 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -324,9 +324,9 @@ pygments==2.19.2 \ --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b # via mkdocs-material -pymdown-extensions==11.0 \ - --hash=sha256:8269cef0247f9e2d0a62fcea10860aba05c1cbab5470fd4b63230b96434dc589 \ - --hash=sha256:fbc4acb641814fa9d17521bbd21a5240ef739a662f11c06330c4b78c93e954d6 +pymdown-extensions==11.0.1 \ + --hash=sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2 \ + --hash=sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0 # via # mkdocs-material # mkdocstrings From dccd8502793a2408804dc0af95e94556bb06449b Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 10 Aug 2026 11:28:56 +0100 Subject: [PATCH 57/76] feat: promote circuit breaker to GA (#8373) --- .../utilities/circuit_breaker/__init__.py | 29 +++++++++++++++ .../base.py | 10 +++--- .../circuit_breaker.py | 10 +++--- .../config.py | 2 +- .../exceptions.py | 2 +- .../circuit_breaker/persistence/__init__.py | 15 ++++++++ .../persistence/base.py | 6 ++-- .../persistence/dynamodb.py | 10 +++--- .../persistence/record.py | 2 +- .../states.py | 0 .../circuit_breaker_alpha/__init__.py | 35 ------------------- .../persistence/__init__.py | 15 -------- .../circuit_breaker/circuit_breaker.md | 2 ++ docs/api_doc/circuit_breaker/config.md | 2 ++ docs/api_doc/circuit_breaker/exceptions.md | 2 ++ docs/api_doc/circuit_breaker/persistence.md | 2 ++ docs/api_doc/circuit_breaker/states.md | 2 ++ .../circuit_breaker_alpha/circuit_breaker.md | 2 -- docs/api_doc/circuit_breaker_alpha/config.md | 2 -- .../circuit_breaker_alpha/exceptions.md | 2 -- .../circuit_breaker_alpha/persistence.md | 2 -- docs/api_doc/circuit_breaker_alpha/states.md | 2 -- docs/utilities/circuit_breaker.md | 21 ++++------- .../getting_started_with_circuit_breaker.py | 4 +-- .../src/working_with_callback.py | 4 +-- .../src/working_with_composite_primary_key.py | 4 +-- .../src/working_with_metrics.py | 4 +-- .../src/working_without_callback.py | 4 +-- .../templates/sam.yaml | 0 .../__init__.py | 0 .../conftest.py | 10 +++--- .../test_circuit_breaker.py | 8 ++--- .../test_dynamodb_persistence.py | 12 +++---- .../_fastjsonschema/test_validator.py | 3 +- .../__init__.py | 0 .../test_config_and_states.py | 8 ++--- 36 files changed, 113 insertions(+), 125 deletions(-) create mode 100644 aws_lambda_powertools/utilities/circuit_breaker/__init__.py rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/base.py (96%) rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/circuit_breaker.py (90%) rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/config.py (98%) rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/exceptions.py (96%) create mode 100644 aws_lambda_powertools/utilities/circuit_breaker/persistence/__init__.py rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/persistence/base.py (97%) rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/persistence/dynamodb.py (96%) rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/persistence/record.py (95%) rename aws_lambda_powertools/utilities/{circuit_breaker_alpha => circuit_breaker}/states.py (100%) delete mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py delete mode 100644 aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py create mode 100644 docs/api_doc/circuit_breaker/circuit_breaker.md create mode 100644 docs/api_doc/circuit_breaker/config.md create mode 100644 docs/api_doc/circuit_breaker/exceptions.md create mode 100644 docs/api_doc/circuit_breaker/persistence.md create mode 100644 docs/api_doc/circuit_breaker/states.md delete mode 100644 docs/api_doc/circuit_breaker_alpha/circuit_breaker.md delete mode 100644 docs/api_doc/circuit_breaker_alpha/config.md delete mode 100644 docs/api_doc/circuit_breaker_alpha/exceptions.md delete mode 100644 docs/api_doc/circuit_breaker_alpha/persistence.md delete mode 100644 docs/api_doc/circuit_breaker_alpha/states.md rename examples/{circuit_breaker_alpha => circuit_breaker}/src/getting_started_with_circuit_breaker.py (83%) rename examples/{circuit_breaker_alpha => circuit_breaker}/src/working_with_callback.py (87%) rename examples/{circuit_breaker_alpha => circuit_breaker}/src/working_with_composite_primary_key.py (80%) rename examples/{circuit_breaker_alpha => circuit_breaker}/src/working_with_metrics.py (88%) rename examples/{circuit_breaker_alpha => circuit_breaker}/src/working_without_callback.py (90%) rename examples/{circuit_breaker_alpha => circuit_breaker}/templates/sam.yaml (100%) rename tests/functional/{circuit_breaker_alpha => circuit_breaker}/__init__.py (100%) rename tests/functional/{circuit_breaker_alpha => circuit_breaker}/conftest.py (90%) rename tests/functional/{circuit_breaker_alpha => circuit_breaker}/test_circuit_breaker.py (98%) rename tests/functional/{circuit_breaker_alpha => circuit_breaker}/test_dynamodb_persistence.py (96%) rename tests/unit/{circuit_breaker_alpha => circuit_breaker}/__init__.py (100%) rename tests/unit/{circuit_breaker_alpha => circuit_breaker}/test_config_and_states.py (93%) diff --git a/aws_lambda_powertools/utilities/circuit_breaker/__init__.py b/aws_lambda_powertools/utilities/circuit_breaker/__init__.py new file mode 100644 index 00000000000..ffe5ce3cb7a --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker/__init__.py @@ -0,0 +1,29 @@ +""" +Circuit Breaker utility for protecting unhealthy downstream dependencies. +""" + +from aws_lambda_powertools.utilities.circuit_breaker.circuit_breaker import circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker.exceptions import ( + CircuitBreakerConfigError, + CircuitBreakerError, + CircuitBreakerOpenError, + CircuitBreakerPersistenceError, +) +from aws_lambda_powertools.utilities.circuit_breaker.states import ( + CircuitInfo, + CircuitState, + CircuitTransition, +) + +__all__ = ( + "circuit_breaker", + "CircuitBreakerConfig", + "CircuitInfo", + "CircuitState", + "CircuitTransition", + "CircuitBreakerError", + "CircuitBreakerOpenError", + "CircuitBreakerConfigError", + "CircuitBreakerPersistenceError", +) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py b/aws_lambda_powertools/utilities/circuit_breaker/base.py similarity index 96% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py rename to aws_lambda_powertools/utilities/circuit_breaker/base.py index 88fcedf61fe..f0375885d18 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/base.py +++ b/aws_lambda_powertools/utilities/circuit_breaker/base.py @@ -15,17 +15,17 @@ import uuid from typing import TYPE_CHECKING, Any -from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerOpenError -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState, CircuitTransition +from aws_lambda_powertools.utilities.circuit_breaker.exceptions import CircuitBreakerOpenError +from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitState, CircuitTransition if TYPE_CHECKING: from collections.abc import Callable - from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig - from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( + from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig + from aws_lambda_powertools.utilities.circuit_breaker.persistence.base import ( CircuitBreakerPersistenceLayer, ) - from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo + from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitInfo logger = logging.getLogger(__name__) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/circuit_breaker.py b/aws_lambda_powertools/utilities/circuit_breaker/circuit_breaker.py similarity index 90% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/circuit_breaker.py rename to aws_lambda_powertools/utilities/circuit_breaker/circuit_breaker.py index de4e66b0680..f0d65542607 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/circuit_breaker.py +++ b/aws_lambda_powertools/utilities/circuit_breaker/circuit_breaker.py @@ -12,14 +12,14 @@ from aws_lambda_powertools.shared import constants from aws_lambda_powertools.shared.functions import strtobool -from aws_lambda_powertools.utilities.circuit_breaker_alpha.base import CircuitBreakerHandler -from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker.base import CircuitBreakerHandler +from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig from aws_lambda_powertools.warnings import PowertoolsUserWarning if TYPE_CHECKING: from collections.abc import Callable - from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( + from aws_lambda_powertools.utilities.circuit_breaker.persistence.base import ( CircuitBreakerPersistenceLayer, ) @@ -73,8 +73,8 @@ def circuit_breaker( ------- **Protect a payment backend, buffering rejected requests** - from aws_lambda_powertools.utilities.circuit_breaker_alpha import circuit_breaker, CircuitInfo - from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + from aws_lambda_powertools.utilities.circuit_breaker import circuit_breaker, CircuitInfo + from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py b/aws_lambda_powertools/utilities/circuit_breaker/config.py similarity index 98% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py rename to aws_lambda_powertools/utilities/circuit_breaker/config.py index 398ff33d6e2..7ee1259a697 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/config.py +++ b/aws_lambda_powertools/utilities/circuit_breaker/config.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING -from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerConfigError +from aws_lambda_powertools.utilities.circuit_breaker.exceptions import CircuitBreakerConfigError if TYPE_CHECKING: from collections.abc import Iterable diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/exceptions.py b/aws_lambda_powertools/utilities/circuit_breaker/exceptions.py similarity index 96% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/exceptions.py rename to aws_lambda_powertools/utilities/circuit_breaker/exceptions.py index cf3c350fc83..063cf5f9c4a 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/exceptions.py +++ b/aws_lambda_powertools/utilities/circuit_breaker/exceptions.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo + from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitInfo class CircuitBreakerError(Exception): diff --git a/aws_lambda_powertools/utilities/circuit_breaker/persistence/__init__.py b/aws_lambda_powertools/utilities/circuit_breaker/persistence/__init__.py new file mode 100644 index 00000000000..3669d207b26 --- /dev/null +++ b/aws_lambda_powertools/utilities/circuit_breaker/persistence/__init__.py @@ -0,0 +1,15 @@ +""" +Persistence layers for the Circuit Breaker utility. +""" + +from aws_lambda_powertools.utilities.circuit_breaker.persistence.base import CircuitBreakerPersistenceLayer +from aws_lambda_powertools.utilities.circuit_breaker.persistence.dynamodb import ( + CircuitBreakerDynamoDBPersistence, +) +from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord + +__all__ = ( + "CircuitBreakerPersistenceLayer", + "CircuitBreakerDynamoDBPersistence", + "CircuitStateRecord", +) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py b/aws_lambda_powertools/utilities/circuit_breaker/persistence/base.py similarity index 97% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py rename to aws_lambda_powertools/utilities/circuit_breaker/persistence/base.py index a4ca7e1985b..c7dc05c637f 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/base.py +++ b/aws_lambda_powertools/utilities/circuit_breaker/persistence/base.py @@ -15,11 +15,11 @@ from typing import TYPE_CHECKING, NamedTuple from aws_lambda_powertools.shared.cache_dict import LRUDict -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState +from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitState if TYPE_CHECKING: - from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig + from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig logger = logging.getLogger(__name__) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py b/aws_lambda_powertools/utilities/circuit_breaker/persistence/dynamodb.py similarity index 96% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py rename to aws_lambda_powertools/utilities/circuit_breaker/persistence/dynamodb.py index edcbf502ab5..3b1f36aa9f3 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/dynamodb.py +++ b/aws_lambda_powertools/utilities/circuit_breaker/persistence/dynamodb.py @@ -15,13 +15,13 @@ from botocore.exceptions import ClientError from aws_lambda_powertools.shared import constants, user_agent -from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerConfigError -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( +from aws_lambda_powertools.utilities.circuit_breaker.exceptions import CircuitBreakerConfigError +from aws_lambda_powertools.utilities.circuit_breaker.persistence.base import ( CircuitBreakerExistingLockError, CircuitBreakerPersistenceLayer, ) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState +from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitState from aws_lambda_powertools.warnings import PowertoolsUserWarning if TYPE_CHECKING: @@ -75,7 +75,7 @@ class CircuitBreakerDynamoDBPersistence(CircuitBreakerPersistenceLayer): ------- **Create a DynamoDB-backed circuit breaker store** - from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( + from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py b/aws_lambda_powertools/utilities/circuit_breaker/persistence/record.py similarity index 95% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py rename to aws_lambda_powertools/utilities/circuit_breaker/persistence/record.py index ec48737810f..55b486099cd 100644 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/record.py +++ b/aws_lambda_powertools/utilities/circuit_breaker/persistence/record.py @@ -6,7 +6,7 @@ from dataclasses import dataclass -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo, CircuitState +from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitInfo, CircuitState @dataclass diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/states.py b/aws_lambda_powertools/utilities/circuit_breaker/states.py similarity index 100% rename from aws_lambda_powertools/utilities/circuit_breaker_alpha/states.py rename to aws_lambda_powertools/utilities/circuit_breaker/states.py diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py deleted file mode 100644 index e931245f9d0..00000000000 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Circuit Breaker utility for protecting unhealthy downstream dependencies. - -!!! warning "Alpha / experimental" - This utility is published under the `_alpha` namespace while we collect - feedback. The public API may change in a backwards-incompatible way before it - is promoted to GA. Pin your version and follow the tracking discussion before - relying on it in production. -""" - -from aws_lambda_powertools.utilities.circuit_breaker_alpha.circuit_breaker import circuit_breaker -from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig -from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import ( - CircuitBreakerConfigError, - CircuitBreakerError, - CircuitBreakerOpenError, - CircuitBreakerPersistenceError, -) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import ( - CircuitInfo, - CircuitState, - CircuitTransition, -) - -__all__ = ( - "circuit_breaker", - "CircuitBreakerConfig", - "CircuitInfo", - "CircuitState", - "CircuitTransition", - "CircuitBreakerError", - "CircuitBreakerOpenError", - "CircuitBreakerConfigError", - "CircuitBreakerPersistenceError", -) diff --git a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py b/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py deleted file mode 100644 index 18704bff793..00000000000 --- a/aws_lambda_powertools/utilities/circuit_breaker_alpha/persistence/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Persistence layers for the Circuit Breaker utility. -""" - -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import CircuitBreakerPersistenceLayer -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.dynamodb import ( - CircuitBreakerDynamoDBPersistence, -) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord - -__all__ = ( - "CircuitBreakerPersistenceLayer", - "CircuitBreakerDynamoDBPersistence", - "CircuitStateRecord", -) diff --git a/docs/api_doc/circuit_breaker/circuit_breaker.md b/docs/api_doc/circuit_breaker/circuit_breaker.md new file mode 100644 index 00000000000..2cb6f9b712e --- /dev/null +++ b/docs/api_doc/circuit_breaker/circuit_breaker.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker.circuit_breaker diff --git a/docs/api_doc/circuit_breaker/config.md b/docs/api_doc/circuit_breaker/config.md new file mode 100644 index 00000000000..28c7f208022 --- /dev/null +++ b/docs/api_doc/circuit_breaker/config.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker.config diff --git a/docs/api_doc/circuit_breaker/exceptions.md b/docs/api_doc/circuit_breaker/exceptions.md new file mode 100644 index 00000000000..72ff6a993b2 --- /dev/null +++ b/docs/api_doc/circuit_breaker/exceptions.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker.exceptions diff --git a/docs/api_doc/circuit_breaker/persistence.md b/docs/api_doc/circuit_breaker/persistence.md new file mode 100644 index 00000000000..aeabefdfa0c --- /dev/null +++ b/docs/api_doc/circuit_breaker/persistence.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker.persistence diff --git a/docs/api_doc/circuit_breaker/states.md b/docs/api_doc/circuit_breaker/states.md new file mode 100644 index 00000000000..215886daa74 --- /dev/null +++ b/docs/api_doc/circuit_breaker/states.md @@ -0,0 +1,2 @@ + +::: aws_lambda_powertools.utilities.circuit_breaker.states diff --git a/docs/api_doc/circuit_breaker_alpha/circuit_breaker.md b/docs/api_doc/circuit_breaker_alpha/circuit_breaker.md deleted file mode 100644 index 824b40225bc..00000000000 --- a/docs/api_doc/circuit_breaker_alpha/circuit_breaker.md +++ /dev/null @@ -1,2 +0,0 @@ - -::: aws_lambda_powertools.utilities.circuit_breaker_alpha.circuit_breaker diff --git a/docs/api_doc/circuit_breaker_alpha/config.md b/docs/api_doc/circuit_breaker_alpha/config.md deleted file mode 100644 index 20b548082c1..00000000000 --- a/docs/api_doc/circuit_breaker_alpha/config.md +++ /dev/null @@ -1,2 +0,0 @@ - -::: aws_lambda_powertools.utilities.circuit_breaker_alpha.config diff --git a/docs/api_doc/circuit_breaker_alpha/exceptions.md b/docs/api_doc/circuit_breaker_alpha/exceptions.md deleted file mode 100644 index 283374e42e5..00000000000 --- a/docs/api_doc/circuit_breaker_alpha/exceptions.md +++ /dev/null @@ -1,2 +0,0 @@ - -::: aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions diff --git a/docs/api_doc/circuit_breaker_alpha/persistence.md b/docs/api_doc/circuit_breaker_alpha/persistence.md deleted file mode 100644 index f865dfd10f0..00000000000 --- a/docs/api_doc/circuit_breaker_alpha/persistence.md +++ /dev/null @@ -1,2 +0,0 @@ - -::: aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence diff --git a/docs/api_doc/circuit_breaker_alpha/states.md b/docs/api_doc/circuit_breaker_alpha/states.md deleted file mode 100644 index c6f232a0e28..00000000000 --- a/docs/api_doc/circuit_breaker_alpha/states.md +++ /dev/null @@ -1,2 +0,0 @@ - -::: aws_lambda_powertools.utilities.circuit_breaker_alpha.states diff --git a/docs/utilities/circuit_breaker.md b/docs/utilities/circuit_breaker.md index b2117f7316b..ab219c942c3 100644 --- a/docs/utilities/circuit_breaker.md +++ b/docs/utilities/circuit_breaker.md @@ -5,13 +5,6 @@ description: Utility -!!! warning "Alpha / experimental" - This utility ships under the **`circuit_breaker_alpha`** namespace while we collect - feedback. The public API may change in a backwards-incompatible way before it is - promoted to GA, at which point the import path becomes `circuit_breaker`. Pin your - Powertools version and follow the tracking discussion before relying on it in - production. - The circuit breaker utility stops sending traffic to an unhealthy downstream dependency, giving it room to recover while you decide what happens to the rejected requests. ## Key features @@ -99,7 +92,7 @@ You **can** use a single DynamoDB table for all your circuits. Already have a si === "AWS Serverless Application Model (SAM) example" ```yaml hl_lines="3-15 24-29 32-33" - --8<-- "examples/circuit_breaker_alpha/templates/sam.yaml" + --8<-- "examples/circuit_breaker/templates/sam.yaml" ``` ### Circuit breaker in action @@ -109,7 +102,7 @@ The common case is the `@circuit_breaker` decorator wrapping the function that m === "getting_started_with_circuit_breaker.py" ```python hl_lines="3-6 9 19 27" - --8<-- "examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py" + --8<-- "examples/circuit_breaker/src/getting_started_with_circuit_breaker.py" ``` !!! note "Wrap the downstream call, not the whole handler" @@ -137,7 +130,7 @@ Register an `on_circuit_open` callback to decide what happens to a rejected requ === "working_with_callback.py" ```python hl_lines="6 24-28 31-35" - --8<-- "examples/circuit_breaker_alpha/src/working_with_callback.py" + --8<-- "examples/circuit_breaker/src/working_with_callback.py" ``` !!! info "Why a callback instead of built-in S3/SQS sinks?" @@ -152,7 +145,7 @@ If you don't register a callback, an open circuit raises `CircuitBreakerOpenErro === "working_without_callback.py" ```python hl_lines="5 16-22 38-43" - --8<-- "examples/circuit_breaker_alpha/src/working_without_callback.py" + --8<-- "examples/circuit_breaker/src/working_without_callback.py" ``` ## Configuration @@ -211,7 +204,7 @@ Register an `on_transition` hook to be notified whenever the circuit changes sta === "working_with_metrics.py" ```python hl_lines="3 12-21 26" - --8<-- "examples/circuit_breaker_alpha/src/working_with_metrics.py" + --8<-- "examples/circuit_breaker/src/working_with_metrics.py" ``` Any exception raised inside the hook is swallowed and logged, so a misbehaving metric call can never break the protected request. @@ -234,14 +227,14 @@ Set **`POWERTOOLS_CIRCUIT_BREAKER_DISABLED`**{: .copyMe} to a truthy value to by #### Using a composite primary key -Use the `sort_key_attr` parameter when your table is configured with a composite primary key _(hash+range key)_, as in a single-table design. +Use the `sort_key_attr` parameter when your table is configured with a composite primary key *(hash+range key)*, as in a single-table design. When enabled, the circuit name is saved in the sort key instead, and the partition key defaults to `circuit_breaker#{LAMBDA_FUNCTION_NAME}` — this **namespaces circuits per function** so two functions can use the same circuit name without sharing state. (Without `sort_key_attr`, the default remains partition-key-only with the circuit name as the partition key.) Set `static_pk_value` to a fixed value (as below) when you instead want **multiple functions to share the same circuit** — for example, every function guarding the same downstream dependency should trip together. ```python hl_lines="12-14" ---8<-- "examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py" +--8<-- "examples/circuit_breaker/src/working_with_composite_primary_key.py" ``` ??? note "Click to expand and learn how table items would look like" diff --git a/examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py b/examples/circuit_breaker/src/getting_started_with_circuit_breaker.py similarity index 83% rename from examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py rename to examples/circuit_breaker/src/getting_started_with_circuit_breaker.py index ad9a4de1066..d97ff2bf235 100644 --- a/examples/circuit_breaker_alpha/src/getting_started_with_circuit_breaker.py +++ b/examples/circuit_breaker/src/getting_started_with_circuit_breaker.py @@ -1,7 +1,7 @@ import os -from aws_lambda_powertools.utilities.circuit_breaker_alpha import circuit_breaker -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( +from aws_lambda_powertools.utilities.circuit_breaker import circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/examples/circuit_breaker_alpha/src/working_with_callback.py b/examples/circuit_breaker/src/working_with_callback.py similarity index 87% rename from examples/circuit_breaker_alpha/src/working_with_callback.py rename to examples/circuit_breaker/src/working_with_callback.py index d2b97ad6ac5..5725ac32a9b 100644 --- a/examples/circuit_breaker_alpha/src/working_with_callback.py +++ b/examples/circuit_breaker/src/working_with_callback.py @@ -3,8 +3,8 @@ import boto3 -from aws_lambda_powertools.utilities.circuit_breaker_alpha import CircuitInfo, circuit_breaker -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( +from aws_lambda_powertools.utilities.circuit_breaker import CircuitInfo, circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py b/examples/circuit_breaker/src/working_with_composite_primary_key.py similarity index 80% rename from examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py rename to examples/circuit_breaker/src/working_with_composite_primary_key.py index d2ef0ae9a17..0bceacdd9fa 100644 --- a/examples/circuit_breaker_alpha/src/working_with_composite_primary_key.py +++ b/examples/circuit_breaker/src/working_with_composite_primary_key.py @@ -1,7 +1,7 @@ import os -from aws_lambda_powertools.utilities.circuit_breaker_alpha import circuit_breaker -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( +from aws_lambda_powertools.utilities.circuit_breaker import circuit_breaker +from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/examples/circuit_breaker_alpha/src/working_with_metrics.py b/examples/circuit_breaker/src/working_with_metrics.py similarity index 88% rename from examples/circuit_breaker_alpha/src/working_with_metrics.py rename to examples/circuit_breaker/src/working_with_metrics.py index f37f1b68351..8129e91f36e 100644 --- a/examples/circuit_breaker_alpha/src/working_with_metrics.py +++ b/examples/circuit_breaker/src/working_with_metrics.py @@ -1,11 +1,11 @@ import os from aws_lambda_powertools.metrics import MetricUnit, single_metric -from aws_lambda_powertools.utilities.circuit_breaker_alpha import ( +from aws_lambda_powertools.utilities.circuit_breaker import ( CircuitTransition, circuit_breaker, ) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( +from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/examples/circuit_breaker_alpha/src/working_without_callback.py b/examples/circuit_breaker/src/working_without_callback.py similarity index 90% rename from examples/circuit_breaker_alpha/src/working_without_callback.py rename to examples/circuit_breaker/src/working_without_callback.py index a5f166438c8..2ac205333ad 100644 --- a/examples/circuit_breaker_alpha/src/working_without_callback.py +++ b/examples/circuit_breaker/src/working_without_callback.py @@ -1,11 +1,11 @@ import os -from aws_lambda_powertools.utilities.circuit_breaker_alpha import ( +from aws_lambda_powertools.utilities.circuit_breaker import ( CircuitBreakerConfig, CircuitBreakerOpenError, circuit_breaker, ) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( +from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/examples/circuit_breaker_alpha/templates/sam.yaml b/examples/circuit_breaker/templates/sam.yaml similarity index 100% rename from examples/circuit_breaker_alpha/templates/sam.yaml rename to examples/circuit_breaker/templates/sam.yaml diff --git a/tests/functional/circuit_breaker_alpha/__init__.py b/tests/functional/circuit_breaker/__init__.py similarity index 100% rename from tests/functional/circuit_breaker_alpha/__init__.py rename to tests/functional/circuit_breaker/__init__.py diff --git a/tests/functional/circuit_breaker_alpha/conftest.py b/tests/functional/circuit_breaker/conftest.py similarity index 90% rename from tests/functional/circuit_breaker_alpha/conftest.py rename to tests/functional/circuit_breaker/conftest.py index 297c088750b..30925dfc5e8 100644 --- a/tests/functional/circuit_breaker_alpha/conftest.py +++ b/tests/functional/circuit_breaker/conftest.py @@ -4,14 +4,14 @@ import pytest -import aws_lambda_powertools.utilities.circuit_breaker_alpha.base as base_module -from aws_lambda_powertools.utilities.circuit_breaker_alpha.base import CircuitBreakerHandler -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.base import ( +import aws_lambda_powertools.utilities.circuit_breaker.base as base_module +from aws_lambda_powertools.utilities.circuit_breaker.base import CircuitBreakerHandler +from aws_lambda_powertools.utilities.circuit_breaker.persistence.base import ( CircuitBreakerExistingLockError, CircuitBreakerPersistenceLayer, ) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState +from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitState class FakePersistence(CircuitBreakerPersistenceLayer): diff --git a/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py b/tests/functional/circuit_breaker/test_circuit_breaker.py similarity index 98% rename from tests/functional/circuit_breaker_alpha/test_circuit_breaker.py rename to tests/functional/circuit_breaker/test_circuit_breaker.py index 8a6daf7c17f..1db372ee900 100644 --- a/tests/functional/circuit_breaker_alpha/test_circuit_breaker.py +++ b/tests/functional/circuit_breaker/test_circuit_breaker.py @@ -6,16 +6,16 @@ import pytest -import aws_lambda_powertools.utilities.circuit_breaker_alpha.base as base_module -from aws_lambda_powertools.utilities.circuit_breaker_alpha import ( +import aws_lambda_powertools.utilities.circuit_breaker.base as base_module +from aws_lambda_powertools.utilities.circuit_breaker import ( CircuitBreakerConfig, CircuitBreakerOpenError, CircuitState, CircuitTransition, circuit_breaker, ) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerError -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker.exceptions import CircuitBreakerError +from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord # All tests disable the local read cache (max_age=0) so each call re-reads the fake store. diff --git a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py b/tests/functional/circuit_breaker/test_dynamodb_persistence.py similarity index 96% rename from tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py rename to tests/functional/circuit_breaker/test_dynamodb_persistence.py index c395d663cad..ac67bfd0897 100644 --- a/tests/functional/circuit_breaker_alpha/test_dynamodb_persistence.py +++ b/tests/functional/circuit_breaker/test_dynamodb_persistence.py @@ -5,12 +5,12 @@ from botocore.config import Config from botocore.stub import Stubber -from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig -from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import CircuitBreakerConfigError -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence import ( +from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker.exceptions import CircuitBreakerConfigError +from aws_lambda_powertools.utilities.circuit_breaker.persistence import ( CircuitBreakerDynamoDBPersistence, ) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitState +from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitState from aws_lambda_powertools.warnings import PowertoolsUserWarning TABLE_NAME = "CircuitBreakerState" @@ -196,7 +196,7 @@ def test_item_to_record_minimal_item(persistence): def test_record_to_item_full_record(persistence): """Cover _record_to_item with all fields set (lines 124-139).""" - from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord + from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord record = CircuitStateRecord( name="payment", @@ -219,7 +219,7 @@ def test_record_to_item_full_record(persistence): def test_record_to_item_minimal_record(persistence): """Cover _record_to_item with optional fields as None (branch misses on lines 131-137).""" - from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord + from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord record = CircuitStateRecord(name="payment", state=CircuitState.CLOSED) item = persistence._record_to_item(record) diff --git a/tests/functional/validator/_fastjsonschema/test_validator.py b/tests/functional/validator/_fastjsonschema/test_validator.py index d29efd09cae..e14bc5e01c1 100644 --- a/tests/functional/validator/_fastjsonschema/test_validator.py +++ b/tests/functional/validator/_fastjsonschema/test_validator.py @@ -77,12 +77,13 @@ def test_validate_accept_schema_custom_format( ) -@pytest.mark.parametrize("invalid_format", [None, False, {}, [], object]) +@pytest.mark.parametrize("invalid_format", [object, 123, 1.5, True]) def test_validate_invalid_custom_format( eventbridge_schema_registry_cloudtrail_v2_s3, eventbridge_cloudtrail_s3_head_object_event, invalid_format, ): + # formats must be a mapping; anything we can't look a format name up in fails to compile with pytest.raises(exceptions.InvalidSchemaFormatError): validate( event=eventbridge_cloudtrail_s3_head_object_event, diff --git a/tests/unit/circuit_breaker_alpha/__init__.py b/tests/unit/circuit_breaker/__init__.py similarity index 100% rename from tests/unit/circuit_breaker_alpha/__init__.py rename to tests/unit/circuit_breaker/__init__.py diff --git a/tests/unit/circuit_breaker_alpha/test_config_and_states.py b/tests/unit/circuit_breaker/test_config_and_states.py similarity index 93% rename from tests/unit/circuit_breaker_alpha/test_config_and_states.py rename to tests/unit/circuit_breaker/test_config_and_states.py index 602f7f4c9d7..03700dc91d3 100644 --- a/tests/unit/circuit_breaker_alpha/test_config_and_states.py +++ b/tests/unit/circuit_breaker/test_config_and_states.py @@ -4,13 +4,13 @@ import pytest -from aws_lambda_powertools.utilities.circuit_breaker_alpha.config import CircuitBreakerConfig -from aws_lambda_powertools.utilities.circuit_breaker_alpha.exceptions import ( +from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig +from aws_lambda_powertools.utilities.circuit_breaker.exceptions import ( CircuitBreakerConfigError, CircuitBreakerOpenError, ) -from aws_lambda_powertools.utilities.circuit_breaker_alpha.persistence.record import CircuitStateRecord -from aws_lambda_powertools.utilities.circuit_breaker_alpha.states import CircuitInfo, CircuitState +from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord +from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitInfo, CircuitState def test_circuit_state_serializes_to_plain_string(): From ad15c7adfaf0c09b6247a427082749e1d34d3952 Mon Sep 17 00:00:00 2001 From: Vishwak Date: Mon, 10 Aug 2026 03:37:05 -0700 Subject: [PATCH 58/76] fix(tracer): declare in_subsegment_async as an async context manager (#8367) BaseProvider.in_subsegment_async was decorated with @contextmanager and annotated to return Generator[BaseSegment, None, None], declaring a synchronous context manager. It is entered with async with by Tracer._decorate_async_function, by the documented escape hatch for concurrent async functions, and by the default X-Ray provider. Remove the decorator and annotate the return type as AbstractAsyncContextManager[BaseSegment] so correct code type checks without a cast. No runtime change, the abstract method body is only a docstring. Closes #8365 Co-authored-by: Leandro Damascena --- aws_lambda_powertools/tracing/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/tracing/base.py b/aws_lambda_powertools/tracing/base.py index 8469c075222..a448126eb88 100644 --- a/aws_lambda_powertools/tracing/base.py +++ b/aws_lambda_powertools/tracing/base.py @@ -14,6 +14,7 @@ import numbers import traceback from collections.abc import Generator, Sequence + from contextlib import AbstractAsyncContextManager class BaseSegment(abc.ABC): @@ -99,8 +100,7 @@ def in_subsegment(self, name=None, **kwargs) -> Generator[BaseSegment, None, Non """ @abc.abstractmethod - @contextmanager - def in_subsegment_async(self, name=None, **kwargs) -> Generator[BaseSegment, None, None]: + def in_subsegment_async(self, name=None, **kwargs) -> AbstractAsyncContextManager[BaseSegment]: """Return a subsegment async context manger. Parameters From 715012fe0b998d18cb639b4a5b5d8e99543296e3 Mon Sep 17 00:00:00 2001 From: debaditya <82204129+DebadityaHait@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:36:23 +0530 Subject: [PATCH 59/76] fix(event_handler): omit Content-Type header from OpenAPI (#8374) Co-authored-by: Leandro Damascena --- .../event_handler/openapi/schema_generator.py | 10 ++++++-- .../_pydantic/test_openapi_params.py | 24 ++++++++++++++++--- .../test_openapi_validation_middleware.py | 21 ++++++++++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/schema_generator.py b/aws_lambda_powertools/event_handler/openapi/schema_generator.py index 6334a3b53cc..096780996f9 100644 --- a/aws_lambda_powertools/event_handler/openapi/schema_generator.py +++ b/aws_lambda_powertools/event_handler/openapi/schema_generator.py @@ -174,9 +174,15 @@ def _build_operation_parameters( continue if _is_pydantic_model_param(field_info): - parameters.extend(_expand_pydantic_model_parameters(field_info)) + generated_parameters = _expand_pydantic_model_parameters(field_info) else: - parameters.append(_create_regular_parameter(param, model_name_map, field_mapping)) + generated_parameters = [_create_regular_parameter(param, model_name_map, field_mapping)] + + parameters.extend( + parameter + for parameter in generated_parameters + if not (parameter["in"] == "header" and parameter["name"].lower() == "content-type") + ) return parameters diff --git a/tests/functional/event_handler/_pydantic/test_openapi_params.py b/tests/functional/event_handler/_pydantic/test_openapi_params.py index 18087a228d1..40722bb838b 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_params.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_params.py @@ -1,7 +1,7 @@ import json from dataclasses import dataclass from datetime import datetime -from typing import List, Optional, Tuple +from typing import List, Literal, Optional, Tuple import pytest from pydantic import BaseModel, Field @@ -915,6 +915,24 @@ def mixed_body_endpoint(user_data: Annotated[UserData, Body(media_type="applicat assert "application/json" in request_body.content +def test_openapi_excludes_content_type_header_parameter(): + """Content-Type is described by requestBody content, not an OpenAPI header parameter.""" + app = APIGatewayRestResolver(enable_validation=True) + + @app.patch("/json-patch") + def json_patch( + operations: Annotated[list[dict], Body(media_type="application/json-patch+json")], + content_type: Annotated[Literal["application/json-patch+json"], Header(alias="Content-Type")], + ): + return {"status": "updated"} + + schema = app.get_openapi_schema() + patch_op = schema.paths["/json-patch"].patch + + assert "application/json-patch+json" in patch_op.requestBody.content + assert all(parameter.name.lower() != "content-type" for parameter in patch_op.parameters or []) + + def test_openapi_form_parameter_edge_cases(): """Test Form parameters with various edge cases.""" @@ -986,7 +1004,7 @@ def get_items(params: Annotated[QueryParams, Query()]): def test_openapi_pydantic_header_with_alias(): - """Test that Pydantic field aliases work correctly in Header parameters""" + """Test that Pydantic header aliases are emitted, except Content-Type.""" app = APIGatewayRestResolver() class HeaderParams(BaseModel): @@ -1003,7 +1021,7 @@ def test_handler(headers: Annotated[HeaderParams, Header()]): # Check that aliases are used as parameter names param_names = [param.name for param in get_operation.parameters] - assert "content-type" in param_names + assert "content-type" not in param_names assert "user-agent" in param_names assert "content_type" not in param_names # Original field name should not be used assert "user_agent" not in param_names diff --git a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py index 16639665c8c..aee94e80b14 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py @@ -59,6 +59,27 @@ def handler(user_id: int): assert any(text in result["body"] for text in ["type_error.integer", "int_parsing"]) +def test_content_type_header_validation_remains_enabled(gw_event): + """Content-Type header validation remains available when it is omitted from the OpenAPI schema.""" + app = APIGatewayRestResolver(enable_validation=True) + + @app.patch("/json-patch") + def json_patch( + operations: Annotated[list[dict], Body(media_type="application/json-patch+json")], + content_type: Annotated[Literal["application/json-patch+json"], Header(alias="Content-Type")], + ): + return {"status": "updated"} + + gw_event["httpMethod"] = "PATCH" + gw_event["path"] = "/json-patch" + gw_event["headers"]["Content-Type"] = "application/json" + gw_event["body"] = '[{"op": "replace"}]' + + result = app(gw_event, {}) + + assert result["statusCode"] == 422 + + def test_validate_pydantic_query_params(gw_event): """Test that Pydantic models in Query parameters are validated correctly""" From 8315c13f6faeda29e240f83f90b4913d2d20d1be Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 13:22:42 +0100 Subject: [PATCH 60/76] chore(ci): layer docs update (#8376) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> --- CHANGELOG.md | 35 +- docs/includes/_layer_homepage_arm64.md | 290 ++++++++--------- docs/includes/_layer_homepage_x86.md | 300 +++++++++--------- examples/build_recipes/cdk/basic/app.py | 2 +- .../stacks/powertools_cdk_stack.py | 2 +- .../build_recipes/sam/multi-env/template.yaml | 2 +- .../sam/with-layers/template.yaml | 4 +- examples/homepage/install/arm64/amplify.txt | 4 +- examples/homepage/install/arm64/cdk_arm64.py | 2 +- .../homepage/install/arm64/pulumi_arm64.py | 2 +- examples/homepage/install/arm64/sam.yaml | 2 +- .../homepage/install/arm64/serverless.yml | 2 +- examples/homepage/install/arm64/terraform.tf | 2 +- examples/homepage/install/x86_64/amplify.txt | 4 +- examples/homepage/install/x86_64/cdk_x86.py | 2 +- .../homepage/install/x86_64/pulumi_x86.py | 2 +- examples/homepage/install/x86_64/sam.yaml | 2 +- .../homepage/install/x86_64/serverless.yml | 2 +- examples/homepage/install/x86_64/terraform.tf | 2 +- examples/logger/sam/template.yaml | 2 +- examples/metrics/sam/template.yaml | 2 +- examples/metrics_datadog/sam/template.yaml | 2 +- examples/tracer/sam/template.yaml | 2 +- 23 files changed, 352 insertions(+), 319 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab85a6c9792..6f1f07e1bc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,44 @@ # Unreleased + +## [v3.34.0] - 2026-08-10 +## Bug Fixes + +* **event_handler:** omit Content-Type header from OpenAPI ([#8374](https://github.com/aws-powertools/powertools-lambda-python/issues/8374)) + +## Maintenance + +* version bump + + ## [v3.31.1] - 2026-07-13 +## Bug Fixes + +* EventBridgeEvent data class ([#8301](https://github.com/aws-powertools/powertools-lambda-python/issues/8301)) +* **circuit_breaker:** make probe election per-thread and synchronize local counters ([#8323](https://github.com/aws-powertools/powertools-lambda-python/issues/8323)) +* **circuit_breaker:** normalize handled/ignored exceptions to a validated tuple at construction ([#8319](https://github.com/aws-powertools/powertools-lambda-python/issues/8319)) +* **event_handler:** resolve dependency injection failure with arbitrary return types ([#8334](https://github.com/aws-powertools/powertools-lambda-python/issues/8334)) +* **event_source:** mypy strict mode compliance ([#8332](https://github.com/aws-powertools/powertools-lambda-python/issues/8332)) +* **parser:** fix DynamoDB Stream Lambda invocation record model ([#8321](https://github.com/aws-powertools/powertools-lambda-python/issues/8321)) + +## Features + +* **circuit_breaker:** support composite primary key in DynamoDB persistence ([#8316](https://github.com/aws-powertools/powertools-lambda-python/issues/8316)) + ## Maintenance * version bump * **data-masking:** bump encryption sdk version ([#8335](https://github.com/aws-powertools/powertools-lambda-python/issues/8335)) +* **deps:** bump soupsieve from 2.7 to 2.8.4 in /docs ([#8328](https://github.com/aws-powertools/powertools-lambda-python/issues/8328)) +* **deps:** bump the github-actions group across 1 directory with 8 updates ([#8327](https://github.com/aws-powertools/powertools-lambda-python/issues/8327)) +* **deps:** bump protobuf from 7.34.1 to 7.35.1 ([#8312](https://github.com/aws-powertools/powertools-lambda-python/issues/8312)) +* **deps-dev:** bump types-python-dateutil from 2.9.0.20260508 to 2.9.0.20260518 ([#8311](https://github.com/aws-powertools/powertools-lambda-python/issues/8311)) +* **deps-dev:** bump aws-cdk from 2.1128.1 to 2.1129.0 in the aws-cdk group ([#8324](https://github.com/aws-powertools/powertools-lambda-python/issues/8324)) +* **deps-dev:** bump soupsieve from 2.7 to 2.8.4 ([#8329](https://github.com/aws-powertools/powertools-lambda-python/issues/8329)) +* **deps-dev:** bump requests from 2.33.1 to 2.34.2 ([#8313](https://github.com/aws-powertools/powertools-lambda-python/issues/8313)) +* **deps-dev:** bump filelock from 3.29.0 to 3.29.7 ([#8314](https://github.com/aws-powertools/powertools-lambda-python/issues/8314)) @@ -7771,7 +7803,8 @@ * Merge pull request [#5](https://github.com/aws-powertools/powertools-lambda-python/issues/5) from jfuss/feat/python38 -[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.31.1...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.34.0...HEAD +[v3.34.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.31.1...v3.34.0 [v3.31.1]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.31.0...v3.31.1 [v3.31.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.30.0...v3.31.0 [v3.30.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.29.0...v3.30.0 diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index e722e169fb7..c80ebf9abb2 100644 --- a/docs/includes/_layer_homepage_arm64.md +++ b/docs/includes/_layer_homepage_arm64.md @@ -6,168 +6,168 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:37**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:37**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:37**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:37**{: .copyMe} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 86daee00793..6c5961b2d0b 100644 --- a/docs/includes/_layer_homepage_x86.md +++ b/docs/includes/_layer_homepage_x86.md @@ -5,173 +5,173 @@ | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:37**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:37**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:36**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:37**{: .copyMe} | diff --git a/examples/build_recipes/cdk/basic/app.py b/examples/build_recipes/cdk/basic/app.py index 018888bdf1d..fe43b6dd479 100644 --- a/examples/build_recipes/cdk/basic/app.py +++ b/examples/build_recipes/cdk/basic/app.py @@ -24,7 +24,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37", ) # Lambda Function diff --git a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py index 565807a226b..7e1e6be5796 100644 --- a/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py +++ b/examples/build_recipes/cdk/multi-stack/stacks/powertools_cdk_stack.py @@ -47,7 +47,7 @@ def _create_powertools_layer(self) -> _lambda.ILayerVersion: return _lambda.LayerVersion.from_layer_version_arn( self, "PowertoolsLayer", - layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37", ) def _create_dynamodb_table(self) -> dynamodb.Table: diff --git a/examples/build_recipes/sam/multi-env/template.yaml b/examples/build_recipes/sam/multi-env/template.yaml index 415bb0cbe09..9bb9e85feae 100644 --- a/examples/build_recipes/sam/multi-env/template.yaml +++ b/examples/build_recipes/sam/multi-env/template.yaml @@ -61,7 +61,7 @@ Resources: CodeUri: src/ Handler: app.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37 - !Ref DependenciesLayer Events: ApiEvent: diff --git a/examples/build_recipes/sam/with-layers/template.yaml b/examples/build_recipes/sam/with-layers/template.yaml index b349cf55236..c572f89d293 100644 --- a/examples/build_recipes/sam/with-layers/template.yaml +++ b/examples/build_recipes/sam/with-layers/template.yaml @@ -31,7 +31,7 @@ Resources: CodeUri: src/app/ Handler: app_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37 - !Ref DependenciesLayer Events: ApiEvent: @@ -50,7 +50,7 @@ Resources: CodeUri: src/worker/ Handler: worker_sam_layer.lambda_handler Layers: - - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:36 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:37 - !Ref DependenciesLayer Events: SQSEvent: diff --git a/examples/homepage/install/arm64/amplify.txt b/examples/homepage/install/arm64/amplify.txt index 20a4ff29e6d..3041343f94c 100644 --- a/examples/homepage/install/arm64/amplify.txt +++ b/examples/homepage/install/arm64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/arm64/cdk_arm64.py b/examples/homepage/install/arm64/cdk_arm64.py index ba9d76f2e43..30977127c57 100644 --- a/examples/homepage/install/arm64/cdk_arm64.py +++ b/examples/homepage/install/arm64/cdk_arm64.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/arm64/pulumi_arm64.py b/examples/homepage/install/arm64/pulumi_arm64.py index 834bab0506b..2f502d4d413 100644 --- a/examples/homepage/install/arm64/pulumi_arm64.py +++ b/examples/homepage/install/arm64/pulumi_arm64.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/arm64/sam.yaml b/examples/homepage/install/arm64/sam.yaml index 7def81c290f..6e76d90e197 100644 --- a/examples/homepage/install/arm64/sam.yaml +++ b/examples/homepage/install/arm64/sam.yaml @@ -9,4 +9,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37 diff --git a/examples/homepage/install/arm64/serverless.yml b/examples/homepage/install/arm64/serverless.yml index 477ef56591e..06c437f6be1 100644 --- a/examples/homepage/install/arm64/serverless.yml +++ b/examples/homepage/install/arm64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37 diff --git a/examples/homepage/install/arm64/terraform.tf b/examples/homepage/install/arm64/terraform.tf index b90a20cbcfe..a6ac2ac56a6 100644 --- a/examples/homepage/install/arm64/terraform.tf +++ b/examples/homepage/install/arm64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:36"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:37"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") diff --git a/examples/homepage/install/x86_64/amplify.txt b/examples/homepage/install/x86_64/amplify.txt index cdfc77196e3..74a47656dd9 100644 --- a/examples/homepage/install/x86_64/amplify.txt +++ b/examples/homepage/install/x86_64/amplify.txt @@ -6,7 +6,7 @@ ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 ❯ amplify push -y @@ -17,5 +17,5 @@ General information - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes -? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 ? Do you want to edit the local lambda function now? No diff --git a/examples/homepage/install/x86_64/cdk_x86.py b/examples/homepage/install/x86_64/cdk_x86.py index 8480c9ea0ae..1b09ee48ce4 100644 --- a/examples/homepage/install/x86_64/cdk_x86.py +++ b/examples/homepage/install/x86_64/cdk_x86.py @@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/x86_64/pulumi_x86.py b/examples/homepage/install/x86_64/pulumi_x86.py index e4f42647e25..b74df328c0d 100644 --- a/examples/homepage/install/x86_64/pulumi_x86.py +++ b/examples/homepage/install/x86_64/pulumi_x86.py @@ -22,7 +22,7 @@ pulumi.Output.concat( "arn:aws:lambda:", aws.get_region_output().name, - ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml index 6ce13861171..85cb40ad532 100644 --- a/examples/homepage/install/x86_64/sam.yaml +++ b/examples/homepage/install/x86_64/sam.yaml @@ -8,4 +8,4 @@ Resources: Runtime: python3.12 Handler: app.lambda_handler Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml index a510b046023..2183bda869c 100644 --- a/examples/homepage/install/x86_64/serverless.yml +++ b/examples/homepage/install/x86_64/serverless.yml @@ -10,4 +10,4 @@ functions: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf index 19938fa6979..2b9703883bb 100644 --- a/examples/homepage/install/x86_64/terraform.tf +++ b/examples/homepage/install/x86_64/terraform.tf @@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.12" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 98bfce6f2c5..a4c3125c76b 100644 --- a/examples/logger/sam/template.yaml +++ b/examples/logger/sam/template.yaml @@ -14,7 +14,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index 729590594d9..a90e5e0fc1d 100644 --- a/examples/metrics/sam/template.yaml +++ b/examples/metrics/sam/template.yaml @@ -16,7 +16,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 Resources: CaptureLambdaHandlerExample: diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml index 53e8469b8f5..38870c8c88e 100644 --- a/examples/metrics_datadog/sam/template.yaml +++ b/examples/metrics_datadog/sam/template.yaml @@ -20,7 +20,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 # Find the latest Layer version in the Datadog official documentation # Datadog SDK diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml index 9dfdff730e2..82fcc82b2ff 100644 --- a/examples/tracer/sam/template.yaml +++ b/examples/tracer/sam/template.yaml @@ -13,7 +13,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37 Resources: CaptureLambdaHandlerExample: From 90a1484a19b7456e904778b0693533b8b5eb9df2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 13:24:11 +0100 Subject: [PATCH 61/76] chore(ci): bump version to 3.34.0 (#8375) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Leandro Damascena --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index 1162b589e36..f82ba509c24 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "3.31.1" +VERSION = "3.34.0" diff --git a/pyproject.toml b/pyproject.toml index b6485f7ff20..31ca7daccbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "3.31.1" +version = "3.34.0" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From e196da5b4e6fad6a6bb01b584b04264f8f537b4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 08:03:05 +0100 Subject: [PATCH 62/76] chore(deps): bump fastjsonschema from 2.21.2 to 2.22.1 (#8382) Bumps [fastjsonschema](https://github.com/horejsek/python-fastjsonschema) from 2.21.2 to 2.22.1. - [Changelog](https://github.com/horejsek/python-fastjsonschema/blob/master/CHANGELOG.txt) - [Commits](https://github.com/horejsek/python-fastjsonschema/compare/v2.21.2...v2.22.1) --- updated-dependencies: - dependency-name: fastjsonschema dependency-version: 2.22.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index ebf01c0c3a3..75c19918e5a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1860,15 +1860,15 @@ testing = ["hatch", "pre-commit", "pytest", "tox"] [[package]] name = "fastjsonschema" -version = "2.21.2" +version = "2.22.1" description = "Fastest Python implementation of JSON schema" optional = true -python-versions = "*" +python-versions = ">=3.10" groups = ["main"] markers = "extra == \"all\" or extra == \"validation\"" files = [ - {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"}, - {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"}, + {file = "fastjsonschema-2.22.1-py3-none-any.whl", hash = "sha256:cf377ff5c9a6f4f3125fb35f75a2c5767bd824ffbcf62c209a93cd48d1453999"}, + {file = "fastjsonschema-2.22.1.tar.gz", hash = "sha256:0b83d1ce8d7845b959dcb20e1a5c3c8883b6541d9c52ab02cce5166b75ec805f"}, ] [package.extras] From bbacdb0f1cb0143a6e0c93609a01de25679c8c19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 08:22:43 +0100 Subject: [PATCH 63/76] chore(deps): bump redis from 8.0.1 to 8.1.0 (#8379) Bumps [redis](https://github.com/redis/redis-py) from 8.0.1 to 8.1.0. - [Release notes](https://github.com/redis/redis-py/releases) - [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES) - [Commits](https://github.com/redis/redis-py/compare/v8.0.1...v8.1.0) --- updated-dependencies: - dependency-name: redis dependency-version: 8.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 75c19918e5a..65080340ae5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3955,14 +3955,14 @@ toml = ["tomli (>=2.0.1)"] [[package]] name = "redis" -version = "8.0.1" +version = "8.1.0" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "redis-8.0.1-py3-none-any.whl", hash = "sha256:47daa35a058c23468d6437f17a8c76882cb316b838ef763036af99b96cedd743"}, - {file = "redis-8.0.1.tar.gz", hash = "sha256:afc5a7a2f5a084f5b1880dec548dd45be17db7e43c82a30d84f952aefb05cfb0"}, + {file = "redis-8.1.0-py3-none-any.whl", hash = "sha256:a4fe1aac3d3b3cc791d4b3d5931c5a956045dc951ee74d1c913ee3ac4d2ee9fb"}, + {file = "redis-8.1.0.tar.gz", hash = "sha256:6e1a19beef9225c83efd689c7e6b7da2d5215b1f42cd13b7fc3714d0a09c7b25"}, ] markers = {main = "extra == \"redis\""} From c8175ef1c182704e6e5e5686c49f7a793aad4f19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 08:24:37 +0100 Subject: [PATCH 64/76] chore(deps): bump the github-actions group with 4 updates (#8383) Bumps the github-actions group with 4 updates: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action), [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish), [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) and [zgosalvez/github-actions-ensure-sha-pinned-actions](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions). Updates `github/codeql-action/upload-sarif` from 4.37.3 to 4.37.6 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81...5595ccaf912efad79be6eef63a5619ff05969be3) Updates `pypa/gh-action-pypi-publish` from 1.14.1 to 1.14.2 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/ba38be9e461d3875417946c167d0b5f3d385a247...dc37677b2e1c63e2034f94d8a5b11f265b73ba33) Updates `release-drafter/release-drafter` from 7.6.0 to 7.7.0 - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/eada3c96a64734dd381cfbda23511034e328ddb0...34d80673e067bdc0c24568d3af899c216adcfaa9) Updates `zgosalvez/github-actions-ensure-sha-pinned-actions` from 5.0.5 to 5.0.6 - [Release notes](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions/releases) - [Commits](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions/compare/3db98c0363e2fa5df3e1c4c471777a7c10b24cc9...46cfe808a5f1588656ef299eedd0ce2fd7ec0dcc) --- updated-dependencies: - dependency-name: github/codeql-action/upload-sarif dependency-version: 4.37.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: pypa/gh-action-pypi-publish dependency-version: 1.14.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: release-drafter/release-drafter dependency-version: 7.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: zgosalvez/github-actions-ensure-sha-pinned-actions dependency-version: 5.0.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .github/workflows/ossf_scorecard.yml | 2 +- .github/workflows/pre-release.yml | 2 +- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release-v3.yml | 4 ++-- .github/workflows/secure_workflows.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index 1914df80a33..a7d647fde0f 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -43,6 +43,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 with: sarif_file: results.sarif diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 0f45bbfa381..8e4e0fb75c8 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -221,7 +221,7 @@ jobs: - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} - uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 # Creates a PR with the latest version we've just released # since our trunk is protected against any direct pushes from automation diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 6f9d3cf5cd7..a80f2273a05 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -27,4 +27,4 @@ jobs: permissions: contents: write # create release in draft mode steps: - - uses: release-drafter/release-drafter@eada3c96a64734dd381cfbda23511034e328ddb0 # v7.6.0 + - uses: release-drafter/release-drafter@34d80673e067bdc0c24568d3af899c216adcfaa9 # v7.7.0 diff --git a/.github/workflows/release-v3.yml b/.github/workflows/release-v3.yml index a4d9e36937d..45e0ccb862d 100644 --- a/.github/workflows/release-v3.yml +++ b/.github/workflows/release-v3.yml @@ -246,12 +246,12 @@ jobs: - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} - uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 # PyPi test maintenance affected us numerous times, leaving for history purposes # - name: Upload to PyPi test # if: ${{ !inputs.skip_pypi }} - # uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 + # uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 # with: # repository-url: https://test.pypi.org/legacy/ diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index 25d88bf8d09..728c632d5cb 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Ensure 3rd party workflows have SHA pinned - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@3db98c0363e2fa5df3e1c4c471777a7c10b24cc9 # v5.0.5 + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@46cfe808a5f1588656ef299eedd0ce2fd7ec0dcc # v5.0.6 with: allowlist: | slsa-framework/slsa-github-generator From 8099ba834743fc34876eed87203121c6d39d7152 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 08:41:14 +0100 Subject: [PATCH 65/76] chore(deps): bump mkdocs-material from 9.7.6 to 9.7.7 (#8381) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.7.6 to 9.7.7. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.7.6...9.7.7) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.7.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/requirements.in | 2 +- docs/requirements.txt | 67 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/docs/requirements.in b/docs/requirements.in index 7457559b3e3..6664e88d346 100644 --- a/docs/requirements.in +++ b/docs/requirements.in @@ -1,4 +1,4 @@ mkdocs-git-revision-date-plugin==0.3.2 mkdocstrings-python==1.19.0 mkdocs-llmstxt==0.5.0 -mkdocs-material==9.7.6 +mkdocs-material==9.7.7 diff --git a/docs/requirements.txt b/docs/requirements.txt index 7a856dd6795..c75a0a3cfc9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -283,15 +283,15 @@ mkdocs-get-deps==0.2.0 \ # via mkdocs mkdocs-git-revision-date-plugin==0.3.2 \ --hash=sha256:2e67956cb01823dd2418e2833f3623dee8604cdf223bddd005fe36226a56f6ef - # via -r requirements.in + # via -r docs/requirements.in mkdocs-llmstxt==0.5.0 \ --hash=sha256:753c699913d2d619a9072604b26b6dc9f5fb6d257d9b107857f80c8a0b787533 \ --hash=sha256:b2fa9e6d68df41d7467e948a4745725b6c99434a36b36204857dbd7bb3dfe041 - # via -r requirements.in -mkdocs-material==9.7.6 \ - --hash=sha256:00bdde50574f776d328b1862fe65daeaf581ec309bd150f7bff345a098c64a69 \ - --hash=sha256:71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba - # via -r requirements.in + # via -r docs/requirements.in +mkdocs-material==9.7.7 \ + --hash=sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f \ + --hash=sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855 + # via -r docs/requirements.in mkdocs-material-extensions==1.3.1 \ --hash=sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443 \ --hash=sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 @@ -303,7 +303,7 @@ mkdocstrings==0.30.0 \ mkdocstrings-python==1.19.0 \ --hash=sha256:395c1032af8f005234170575cc0c5d4d20980846623b623b35594281be4a3059 \ --hash=sha256:917aac66cf121243c11db5b89f66b0ded6c53ec0de5318ff5e22424eb2f2e57c - # via -r requirements.in + # via -r docs/requirements.in packaging==25.0 \ --hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \ --hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f @@ -415,10 +415,61 @@ soupsieve==2.8.4 \ --hash=sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e \ --hash=sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65 # via beautifulsoup4 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 + # via mdformat typing-extensions==4.14.0 \ --hash=sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4 \ --hash=sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af - # via beautifulsoup4 + # via + # beautifulsoup4 + # mkdocstrings-python urllib3==2.7.0 \ --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 From 8bf68fa9d22956b819dbd1811b603429d86cc1fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 08:43:59 +0100 Subject: [PATCH 66/76] chore(deps-dev): bump testcontainers from 4.14.2 to 4.15.0 (#8380) Bumps [testcontainers](https://github.com/testcontainers/testcontainers-python) from 4.14.2 to 4.15.0. - [Release notes](https://github.com/testcontainers/testcontainers-python/releases) - [Changelog](https://github.com/testcontainers/testcontainers-python/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-python/compare/testcontainers-v4.14.2...testcontainers-v4.15.0) --- updated-dependencies: - dependency-name: testcontainers dependency-version: 4.15.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/poetry.lock b/poetry.lock index 65080340ae5..7f4a6ae8a52 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4521,14 +4521,14 @@ dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] [[package]] name = "testcontainers" -version = "4.14.2" +version = "4.15.0" description = "Python library for throwaway instances of anything that can run in a Docker container" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "testcontainers-4.14.2-py3-none-any.whl", hash = "sha256:0d0522c3cd8f8d9627cda41f7a6b51b639fa57bdc492923c045117933c668d68"}, - {file = "testcontainers-4.14.2.tar.gz", hash = "sha256:1340ccf16fe3acd9389a6c9e1d9ab21d9fe99a8afdf8165f89c3e69c1967d239"}, + {file = "testcontainers-4.15.0-py3-none-any.whl", hash = "sha256:8796c14e76604031ad39cf0ed3b8e9806283a1fbf5270965c2b1c594caa31b74"}, + {file = "testcontainers-4.15.0.tar.gz", hash = "sha256:085cde086337632e19002719460b7b80bbab2bdd51bb3ea04f77d0de96504706"}, ] [package.dependencies] @@ -4546,8 +4546,9 @@ azurite = ["azure-storage-blob (>=12)"] chroma = ["chromadb-client (>=1)"] clickhouse = ["clickhouse-driver"] cosmosdb = ["azure-cosmos (>=4)"] -db2 = ["ibm-db-sa ; platform_machine != \"aarch64\" and platform_machine != \"arm64\"", "sqlalchemy (>=2)"] -generic = ["httpx", "redis (>=7)"] +cratedb = ["httpx", "sqlalchemy-cratedb"] +db2 = ["ibm-db-sa ; platform_machine != \"aarch64\" and platform_machine != \"arm64\"", "sqlalchemy"] +generic = ["httpx", "redis (>=7)", "sqlalchemy"] google = ["google-cloud-datastore (>=2)", "google-cloud-pubsub (>=2)"] influxdb = ["influxdb (>=5)", "influxdb-client (>=1)"] k3s = ["kubernetes", "pyyaml (>=6.0.3)"] @@ -4556,19 +4557,19 @@ localstack = ["boto3 (>=1)"] mailpit = ["cryptography"] minio = ["minio (>=7)"] mongodb = ["pymongo (>=4)"] -mssql = ["pymssql (>=2)", "sqlalchemy (>=2)"] -mysql = ["pymysql[rsa] (>=1)", "sqlalchemy (>=2)"] +mssql = ["pymssql (>=2)", "sqlalchemy"] +mysql = ["pymysql[rsa] (>=1)", "sqlalchemy"] nats = ["nats-py (>=2)"] neo4j = ["neo4j (>=6)"] openfga = ["openfga-sdk"] opensearch = ["opensearch-py (>=3) ; python_version < \"4.0\""] -oracle = ["oracledb (>=3)", "sqlalchemy (>=2)"] -oracle-free = ["oracledb (>=3)", "sqlalchemy (>=2)"] +oracle = ["oracledb (>=3)", "sqlalchemy"] +oracle-free = ["oracledb (>=3)", "sqlalchemy"] qdrant = ["qdrant-client (>=1)"] rabbitmq = ["pika (>=1)"] redis = ["redis (>=7)"] registry = ["bcrypt (>=5)"] -scylla = ["cassandra-driver (>=3)"] +scylla = ["cassandra-driver (>=3) ; python_version < \"3.14\""] selenium = ["selenium (>=4)"] sftp = ["cryptography"] test-module-import = ["httpx"] From 8db13c761d6f592a4e26dab74035af29412d6634 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 08:46:09 +0100 Subject: [PATCH 67/76] chore(deps-dev): bump aws-cdk from 2.1130.0 to 2.1135.1 in the aws-cdk group (#8378) chore(deps-dev): bump aws-cdk in the aws-cdk group Bumps the aws-cdk group with 1 update: [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `aws-cdk` from 2.1130.0 to 2.1135.1 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1135.1/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1135.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6f1be92be0e..3a9b1de6b24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,13 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1130.0" + "aws-cdk": "^2.1135.1" } }, "node_modules/aws-cdk": { - "version": "2.1130.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1130.0.tgz", - "integrity": "sha512-LgSKHFTGhoT/lML48uiYIpdSHCwZLvUx/uZu5MqcZjh+OwWzM8nCxXY+OjKG3yASlx5JxeulXm4sRaUYo48qFQ==", + "version": "2.1135.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1135.1.tgz", + "integrity": "sha512-g1jcMfWlyYtGamFJ/kPBOCuchl3NfwTF2UwOLTIDN0nJbGm84EAO+c8DlYnaemM8UmKFkdoq4BGdmiNL5nHWwA==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 55619510bcc..47d70c3bbbc 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1130.0" + "aws-cdk": "^2.1135.1" } } From bc63354ec77201a0ab5b5fcfc285abcb277fa2be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:54:52 +0100 Subject: [PATCH 68/76] chore(deps): bump mkdocs-material from 9.7.6 to 9.7.7 (#8394) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.7.6 to 9.7.7. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.7.6...9.7.7) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.7.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7f4a6ae8a52..092b4c16046 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2759,14 +2759,14 @@ mdformat = ">=0.7.21" [[package]] name = "mkdocs-material" -version = "9.7.6" +version = "9.7.7" description = "Documentation that simply works" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "mkdocs_material-9.7.6-py3-none-any.whl", hash = "sha256:71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba"}, - {file = "mkdocs_material-9.7.6.tar.gz", hash = "sha256:00bdde50574f776d328b1862fe65daeaf581ec309bd150f7bff345a098c64a69"}, + {file = "mkdocs_material-9.7.7-py3-none-any.whl", hash = "sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f"}, + {file = "mkdocs_material-9.7.7.tar.gz", hash = "sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855"}, ] [package.dependencies] From bb51178e798363f0cce71c39df92960b0c5582a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:04:47 +0100 Subject: [PATCH 69/76] chore(deps): bump valkey-glide from 2.5.0 to 2.5.1 (#8396) Bumps [valkey-glide](https://github.com/valkey-io/valkey-glide) from 2.5.0 to 2.5.1. - [Release notes](https://github.com/valkey-io/valkey-glide/releases) - [Changelog](https://github.com/valkey-io/valkey-glide/blob/main/CHANGELOG.md) - [Commits](https://github.com/valkey-io/valkey-glide/compare/v2.5.0...v2.5.1) --- updated-dependencies: - dependency-name: valkey-glide dependency-version: 2.5.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 60 ++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/poetry.lock b/poetry.lock index 092b4c16046..a4772744a7b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4975,42 +4975,42 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "valkey-glide" -version = "2.5.0" +version = "2.5.1" description = "Valkey GLIDE Async client. Supports Valkey and Redis OSS." optional = true python-versions = ">=3.9" groups = ["main"] markers = "extra == \"valkey\"" files = [ - {file = "valkey_glide-2.5.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:10bd8e942f7bd462cca4e8578f67c4e32d246cf42a736da89c5b6e55c1198e27"}, - {file = "valkey_glide-2.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d207e8d3ebaa7f434a73b4f29b46296c44d4277c93c6e0ce2db0c0a4037f4715"}, - {file = "valkey_glide-2.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8a04a8f00ccbaea1d43c933dacfaefc0779608e0f306053b7bc2c9a6ec71a22"}, - {file = "valkey_glide-2.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee93ffd52845e5620774a65f43d751c9076505c9e29ea51263fcbc512893af1"}, - {file = "valkey_glide-2.5.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:df59c58ac08d66c4e730e7bab9f7e37c9cf30ca0e5b3ffa80f7e68abb0bfcc7b"}, - {file = "valkey_glide-2.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:40d67ea9bef44065809432e2a34193ada5a2a64b959f1f7b7572c5a055bdcb2d"}, - {file = "valkey_glide-2.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c4231e4290e06405729fd2b0c94febd6db861fe1a88e205627353d70e799473"}, - {file = "valkey_glide-2.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:284439b63dae97bc5dfa5266e39e9ba0868db9235932778599daa90b56fba2b2"}, - {file = "valkey_glide-2.5.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:95bc800473d5795e3db5eb9f64892cc0c4b79a4580320d51c90799f05ca815b9"}, - {file = "valkey_glide-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ea98b2b44bbfdfdc4fa6149b16136f67c59dd46e51f4e45c29136307c3177a3a"}, - {file = "valkey_glide-2.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9db2235a3190ec0b5bf3997c518a6c642f5e44c3a3c1ed70817ce5fc48815e6"}, - {file = "valkey_glide-2.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7893d63a3424ea43f9e2ab7ce2e31d628dea765f0ada09ab1b50b426f55d3863"}, - {file = "valkey_glide-2.5.0-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:cc6146d78545a85da2757ba0ac9d636b90fabdb45cc1a864f1c808381de942c5"}, - {file = "valkey_glide-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d8feb2a5ace38d1d88ba5c650b10273c5d862a55b0b5006d227aadd91e7c31e7"}, - {file = "valkey_glide-2.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bc80db5b2c191550ed716d28018520c7decc7853a2c2104c2d3654da3cd920e"}, - {file = "valkey_glide-2.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afecb53f774e7e376a757cda124bc08734b072cfdfcf703111b26afab5c24d2d"}, - {file = "valkey_glide-2.5.0-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:4a86f8451c5f8aa69f822782ba0ab64c77d8f6267844e2479b3267853dd076a5"}, - {file = "valkey_glide-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97b1d1bde85abf9783952e65b134368d0a575b5978b73c60fdde1d69d6bc6a69"}, - {file = "valkey_glide-2.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2d442a9aa0a2685023850950d76acaa689df1581f3028468c965e71b9009a83"}, - {file = "valkey_glide-2.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c90d9bb9c49059f0ddd8b50b1e84e924c7a8bd261be82376ab09cefbbf2b233"}, - {file = "valkey_glide-2.5.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:eca2618c59301ffd093108714ef09e69d67b4f8745ad65b7fd5514d378d3b6be"}, - {file = "valkey_glide-2.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19ccc9654f3e2da628fc7c6c15377a8f54046c73ab064530823649108a72fdef"}, - {file = "valkey_glide-2.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc0a0fe39b1cadf81b15b91051f6101913bdb4b78d986d20a4dace152921f3c"}, - {file = "valkey_glide-2.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60315782ada98d4d49ae842535d5045b6e2d40366c05be3d49c9c4563f9012cf"}, - {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:1bc0913efd997ed94136aac04d89fa73bb40525292a0182493c8c47bf24839b9"}, - {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d6c8127a6661d866c7fabb1830e6d8943536921e9f80033c6f095fdcec0ba28"}, - {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19a54a25fefa9e5839d0237625bf23e5f84df6a50eadac06181a9a99fb02e6c2"}, - {file = "valkey_glide-2.5.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47663a0432097746c3fc13f2e890280c003bfff7924f48f4f65c416750f4f368"}, - {file = "valkey_glide-2.5.0.tar.gz", hash = "sha256:21a9c037107af5ba3cdb27ed126abc02c75f9690dd6e82272f2a91042f4b8a2e"}, + {file = "valkey_glide-2.5.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d66f47bbc5cea7155b0b3ca002043bfd950c09a9ac08e10923a6bcb0a3aa0a1c"}, + {file = "valkey_glide-2.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:47a666862faa47766d4c4814203c3b9f9a8cb466200fd5f71e330eef6ed0d8f1"}, + {file = "valkey_glide-2.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecd82dab35f30d96785b1405ebe3a6931dd858c8f26a0b7a12b46609e75212"}, + {file = "valkey_glide-2.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44435ed9fdb6322a4b167c9f56fdc0145a1fab4736dd2659165bbb5358d3a68f"}, + {file = "valkey_glide-2.5.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:d9bbf26f9ea2b72ef0b8541dfefa479a82a69bdec77fce917192a262893edfda"}, + {file = "valkey_glide-2.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94256d3335f4c31f19ad1ff02447d9eecd94b8c9e8d51c7b77811277c957e807"}, + {file = "valkey_glide-2.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d46a9903acb1204deefad88162ac77404f052c7d51ab9d5851d2335ed2fda1e8"}, + {file = "valkey_glide-2.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e5c17169d07564f0cc23b78c4904c8e03063c8750d8ccf413d229ce9a3092d5"}, + {file = "valkey_glide-2.5.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:75da4cb54fe6a0e03a78681237545aa0638dd5a6dd0ff51af6ff4cacf9f99443"}, + {file = "valkey_glide-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:787010bbce1b8f270ae5d74ca8af15bca3bbc625e1a5467fb01025864bc4e792"}, + {file = "valkey_glide-2.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de2e202a8376c6b67735bd589ce0e46683f8a782fcb1745b0b44cce768e13856"}, + {file = "valkey_glide-2.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ab1c7ce52b098fcb0ee6223136a024fc90a8ae1c600db298c30c044d1b47ee2"}, + {file = "valkey_glide-2.5.1-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:55c87ecc3146480adaddf42d659b688089ca417596208ca9df5c2249c8f9e6fe"}, + {file = "valkey_glide-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae6b0cedd3d2aafdc53c460bdfe4d0319d10301fd2128a56d41486e49de88dfe"}, + {file = "valkey_glide-2.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8a3c5298899ea18fc7e40438643e2f8ee15955fe9bba66ce5daf3dfd29462f2"}, + {file = "valkey_glide-2.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb5e0094d576ce99a2453c9fdd923f70732db6f4b59a722c27c420343d96b75d"}, + {file = "valkey_glide-2.5.1-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:1bc5d0e0241aa5b78c398b981fe19801e36c09572c1dac69286a9a3c817e0b35"}, + {file = "valkey_glide-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec658ed7770c05f3ea431ca1301e47d0a24cf27c4c23ca30eb030f7e0ac7488d"}, + {file = "valkey_glide-2.5.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2cdb26952b650e25af4a14360f65364b8015e49e2967779ba850c9e62c1f237"}, + {file = "valkey_glide-2.5.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:696635581f0692f640b94021b4cfbc2ec01108f6ae02f25dfea3cfdaa98331de"}, + {file = "valkey_glide-2.5.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:f5e733adc4718b93c5b228de7e543a6641e231d5839202ce7b22487e079059e7"}, + {file = "valkey_glide-2.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ffd8f0fdb6ef982161a2350ad1562e5e345bea263b81304c7282f3385deac20"}, + {file = "valkey_glide-2.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6b81727c4d7a3b49f10172787296c87d6ef8d729fb958de358b278d5a6c563f"}, + {file = "valkey_glide-2.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12fff287f02caa9302d7c64d0520c3cee86e0f952ec55a537a4f9378889265d7"}, + {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f656ef6e722d6ab4a28bc66e36ef616dff28622bc712c41f4172ac1e7c4826d8"}, + {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:65b2add9f19a2e48080130ee968af45dc14e8457b5db20262703a4604afc478b"}, + {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9b725afe94f0515e296003942d6c96c5090a956f2217f6305dc87fa14dfa51"}, + {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a131c08951b865f753f1bd42f7db19c6a96e7c4faf9dc78718f8909fc95eb8b4"}, + {file = "valkey_glide-2.5.1.tar.gz", hash = "sha256:b2efb23c987a995ad6ce2a72616996638137dd2504ac262bdd6c045378394090"}, ] [package.dependencies] From cdab6db98c5495e5e143bada19574236cf9d637b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:16:07 +0100 Subject: [PATCH 70/76] chore(deps-dev): bump aws-cdk from 2.1135.1 to 2.1136.0 in the aws-cdk group (#8392) chore(deps-dev): bump aws-cdk in the aws-cdk group Bumps the aws-cdk group with 1 update: [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `aws-cdk` from 2.1135.1 to 2.1136.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1136.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1136.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3a9b1de6b24..cda2d626edd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,13 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1135.1" + "aws-cdk": "^2.1136.0" } }, "node_modules/aws-cdk": { - "version": "2.1135.1", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1135.1.tgz", - "integrity": "sha512-g1jcMfWlyYtGamFJ/kPBOCuchl3NfwTF2UwOLTIDN0nJbGm84EAO+c8DlYnaemM8UmKFkdoq4BGdmiNL5nHWwA==", + "version": "2.1136.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1136.0.tgz", + "integrity": "sha512-n6kCL9R9uuvb7WXEwiSs3rYGwnTy9AHHmxOT5Pj5/++E4PYz2bLDXIxzoiOMIj5maoyC52PTe/0GezFV+O0ILQ==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 47d70c3bbbc..d429b6b453c 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.1135.1" + "aws-cdk": "^2.1136.0" } } From f8867f04677f6f6fab33b2e1aed4fced2a249c7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:17:54 +0100 Subject: [PATCH 71/76] chore(deps): bump the github-actions group across 1 directory with 3 updates (#8401) Bumps the github-actions group with 3 updates in the / directory: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action), [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) and [zgosalvez/github-actions-ensure-sha-pinned-actions](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions). Updates `github/codeql-action/upload-sarif` from 4.37.6 to 4.37.8 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28) Updates `docker/setup-buildx-action` from 4.2.0 to 4.3.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/bb05f3f5519dd87d3ba754cc423b652a5edd6d2c...37fe631027851001ddb9b187196cc803df7f5f0e) Updates `zgosalvez/github-actions-ensure-sha-pinned-actions` from 5.0.6 to 5.0.7 - [Release notes](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions/releases) - [Commits](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions/compare/46cfe808a5f1588656ef299eedd0ce2fd7ec0dcc...c5fc58bd0be7a4b94b73ce40250322d5b838a108) --- updated-dependencies: - dependency-name: github/codeql-action/upload-sarif dependency-version: 4.37.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: docker/setup-buildx-action dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: zgosalvez/github-actions-ensure-sha-pinned-actions dependency-version: 5.0.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .github/workflows/ossf_scorecard.yml | 2 +- .github/workflows/publish_v3_layer.yml | 2 +- .github/workflows/quality_code_cdk_constructor.yml | 2 +- .github/workflows/secure_workflows.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index a7d647fde0f..430767741d7 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -43,6 +43,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: sarif_file: results.sarif diff --git a/.github/workflows/publish_v3_layer.yml b/.github/workflows/publish_v3_layer.yml index 456533b055e..ab2f43285e5 100644 --- a/.github/workflows/publish_v3_layer.yml +++ b/.github/workflows/publish_v3_layer.yml @@ -146,7 +146,7 @@ jobs: - name: Set up Docker Buildx id: builder - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 with: driver: docker platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/quality_code_cdk_constructor.yml b/.github/workflows/quality_code_cdk_constructor.yml index cedb82b82bc..4dd9a631c51 100644 --- a/.github/workflows/quality_code_cdk_constructor.yml +++ b/.github/workflows/quality_code_cdk_constructor.yml @@ -57,7 +57,7 @@ jobs: # NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM) - name: Set up Docker Buildx id: builder - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 with: driver: docker platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index 728c632d5cb..b21adc7f5df 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Ensure 3rd party workflows have SHA pinned - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@46cfe808a5f1588656ef299eedd0ce2fd7ec0dcc # v5.0.6 + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@c5fc58bd0be7a4b94b73ce40250322d5b838a108 # v5.0.7 with: allowlist: | slsa-framework/slsa-github-generator From 937f0fe96bd8eda38c36834fe911a61ffff5b41b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:21:13 +0100 Subject: [PATCH 72/76] chore(deps-dev): bump aws-cdk-aws-lambda-python-alpha from 2.259.0a0 to 2.266.0a0 (#8395) chore(deps-dev): bump aws-cdk-aws-lambda-python-alpha Bumps [aws-cdk-aws-lambda-python-alpha](https://github.com/aws/aws-cdk) from 2.259.0a0 to 2.266.0a0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/commits) --- updated-dependencies: - dependency-name: aws-cdk-aws-lambda-python-alpha dependency-version: 2.265.0a0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 52 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/poetry.lock b/poetry.lock index a4772744a7b..95eb2dbefae 100644 --- a/poetry.lock +++ b/poetry.lock @@ -138,20 +138,19 @@ zstandard = ["zstandard"] [[package]] name = "aws-cdk-asset-awscli-v1" -version = "2.2.282" +version = "2.2.292" description = "A library that contains the AWS CLI for use in Lambda Layers" optional = false -python-versions = "~=3.10" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "aws_cdk_asset_awscli_v1-2.2.282-py3-none-any.whl", hash = "sha256:24139da0eb1be59f8cfda22c6343d51e8d50bb89b5052b049cfab92683de7790"}, - {file = "aws_cdk_asset_awscli_v1-2.2.282.tar.gz", hash = "sha256:f86e61653927f77fb235b5ec148c955c610117430c869d182c8b20f7e07e2df2"}, + {file = "aws_cdk_asset_awscli_v1-2.2.292-py3-none-any.whl", hash = "sha256:01cfb33e2913df2d63448b0954ea4ed1bcb1d064514b4b7aa266eda915e8ebfc"}, + {file = "aws_cdk_asset_awscli_v1-2.2.292.tar.gz", hash = "sha256:06da203eeaecbbbf5f1ecd3b12140104e6a59b6a7f6182cfbda5c5deda4b6344"}, ] [package.dependencies] -jsii = ">=1.130.0,<2.0.0" +jsii = ">=1.139.0,<2.0.0" publication = ">=0.0.3" -typeguard = "2.13.3" [[package]] name = "aws-cdk-asset-node-proxy-agent-v6" @@ -250,60 +249,57 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-lambda-python-alpha" -version = "2.259.0a0" +version = "2.266.0a0" description = "The CDK Construct Library for AWS Lambda in Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "aws_cdk_aws_lambda_python_alpha-2.259.0a0-py3-none-any.whl", hash = "sha256:6ab839026a26fd9e9c7d0df04e08dbbfe32e9a22d89726175e165e2b5da268f2"}, - {file = "aws_cdk_aws_lambda_python_alpha-2.259.0a0.tar.gz", hash = "sha256:5d061cb7ba7a76e5699e7a0cc1aaa2ba329d5242ddf945a79eda717c287d2e09"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.266.0a0-py3-none-any.whl", hash = "sha256:be7c34c7296d9e6c478df9065510b2013a52d27629be6d90b4c9221043e71077"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.266.0a0.tar.gz", hash = "sha256:eb7bb2890c722dc7d49851c61f8df8f7dd339a9135216e8f007c5c5be1b05cdb"}, ] [package.dependencies] -aws-cdk-lib = ">=2.259.0,<3.0.0" +aws-cdk-lib = ">=2.266.0,<3.0.0" constructs = ">=10.5.0,<11.0.0" -jsii = ">=1.133.0,<2.0.0" +jsii = ">=1.139.0,<2.0.0" publication = ">=0.0.3" -typeguard = "2.13.3" [[package]] name = "aws-cdk-cloud-assembly-schema" -version = "54.2.0" +version = "54.21.0" description = "Schema for the protocol between CDK framework and CDK CLI" optional = false -python-versions = "~=3.10" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "aws_cdk_cloud_assembly_schema-54.2.0-py3-none-any.whl", hash = "sha256:a7038bffa1aaf3365b72147987396bcf0b9951c3b53b2eebfc181b7cb4227067"}, - {file = "aws_cdk_cloud_assembly_schema-54.2.0.tar.gz", hash = "sha256:2e3a05fca6a28f49811b7b011fce12b03dd0adb15c37a0ad2d1b16d8d66fe95a"}, + {file = "aws_cdk_cloud_assembly_schema-54.21.0-py3-none-any.whl", hash = "sha256:e5951260bb7ca20956240a96f90aa423c33467a5a37b40e338dd4e2c9c02fb0c"}, + {file = "aws_cdk_cloud_assembly_schema-54.21.0.tar.gz", hash = "sha256:bd66b07ab1a1570801219a3ad3e438a6853db284771cff7aa5e18935b2b3dd0c"}, ] [package.dependencies] -jsii = ">=1.132.0,<2.0.0" +jsii = ">=1.139.0,<2.0.0" publication = ">=0.0.3" -typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.260.0" +version = "2.267.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.260.0-py3-none-any.whl", hash = "sha256:41363a6fd72261ce64055b6c90538cf9b9ee2854faca7d2c56316656214f56ea"}, - {file = "aws_cdk_lib-2.260.0.tar.gz", hash = "sha256:94412d6539b543e898aa3a408a39c4d68be06c992938f8191d12f6ab44e546df"}, + {file = "aws_cdk_lib-2.267.0-py3-none-any.whl", hash = "sha256:83e269742e10069b5df80b2b99ec55ffb097f31cbf62317b6cf44eb63d4a9430"}, + {file = "aws_cdk_lib-2.267.0.tar.gz", hash = "sha256:2778f1befdda7401ad064d60f5442858c2dad2a1a87591264ca6f17da6ebd4a2"}, ] [package.dependencies] -"aws-cdk.asset-awscli-v1" = "2.2.282" +"aws-cdk.asset-awscli-v1" = "2.2.292" "aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.2,<3.0.0" -"aws-cdk.cloud-assembly-schema" = ">=54.0.0,<55.0.0" +"aws-cdk.cloud-assembly-schema" = ">=54.11.0,<55.0.0" constructs = ">=10.5.0,<11.0.0" -jsii = ">=1.133.0,<2.0.0" +jsii = ">=1.139.0,<2.0.0" publication = ">=0.0.3" -typeguard = "2.13.3" [[package]] name = "aws-encryption-sdk" @@ -2250,14 +2246,14 @@ files = [ [[package]] name = "jsii" -version = "1.135.0" +version = "1.140.0" description = "Python client for jsii runtime" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jsii-1.135.0-py3-none-any.whl", hash = "sha256:bfab0cc3f99bfbc13683af2afb8d62522af867fb826fc825ab6b27fe636bb087"}, - {file = "jsii-1.135.0.tar.gz", hash = "sha256:3d860404e9e350beae0bdae48b473173653bd2be3a901c620feb656b690f9c2f"}, + {file = "jsii-1.140.0-py3-none-any.whl", hash = "sha256:aa24f27d15d8d7db1ff32a9c56074bc87e728b30330ead97fb149419a3721a50"}, + {file = "jsii-1.140.0.tar.gz", hash = "sha256:454c874d963a862f6b90bc013c45a720e51292659f57249d9cae7cb2a189ec0e"}, ] [package.dependencies] From f704837b92c4eb1527899779ba89ec251d7222fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:52:10 +0100 Subject: [PATCH 73/76] chore(deps-dev): bump the dev-dependencies group across 1 directory with 5 updates (#8407) * chore(deps-dev): bump the dev-dependencies group across 1 directory with 5 updates Bumps the dev-dependencies group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [coverage](https://github.com/coveragepy/coveragepy) | `7.14.3` | `7.15.4` | | [pytest-benchmark](https://github.com/ionelmc/pytest-benchmark) | `5.2.3` | `5.3.0` | | [mypy](https://github.com/python/mypy) | `2.1.0` | `2.3.1` | | [ruff](https://github.com/astral-sh/ruff) | `0.15.19` | `0.16.4` | | [pytest-socket](https://github.com/miketheman/pytest-socket) | `0.8.0` | `0.8.1` | Updates `coverage` from 7.14.3 to 7.15.4 - [Release notes](https://github.com/coveragepy/coveragepy/releases) - [Changelog](https://github.com/coveragepy/coveragepy/blob/main/CHANGES.rst) - [Commits](https://github.com/coveragepy/coveragepy/compare/7.14.3...7.15.4) Updates `pytest-benchmark` from 5.2.3 to 5.3.0 - [Release notes](https://github.com/ionelmc/pytest-benchmark/releases) - [Changelog](https://github.com/ionelmc/pytest-benchmark/blob/master/CHANGELOG.rst) - [Commits](https://github.com/ionelmc/pytest-benchmark/compare/v5.2.3...v5.3.0) Updates `mypy` from 2.1.0 to 2.3.1 - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v2.1.0...v2.3.1) Updates `ruff` from 0.15.19 to 0.16.4 - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.15.19...0.16.4) Updates `pytest-socket` from 0.8.0 to 0.8.1 - [Release notes](https://github.com/miketheman/pytest-socket/releases) - [Changelog](https://github.com/miketheman/pytest-socket/blob/main/CHANGELOG.md) - [Commits](https://github.com/miketheman/pytest-socket/compare/0.8.0...0.8.1) --- updated-dependencies: - dependency-name: coverage dependency-version: 7.15.4 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: mypy dependency-version: 2.3.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: pytest-benchmark dependency-version: 5.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: pytest-socket dependency-version: 0.8.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: ruff dependency-version: 0.16.4 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] * chore: ignore new Ruff positional argument rule --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro --- poetry.lock | 703 ++++++++++++++++++++++++++++--------------------- pyproject.toml | 2 +- ruff.toml | 1 + 3 files changed, 408 insertions(+), 298 deletions(-) diff --git a/poetry.lock b/poetry.lock index 95eb2dbefae..6234daec8f2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -52,45 +52,69 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] [[package]] name = "ast-serialize" -version = "0.5.0" +version = "0.8.0" description = "Python bindings for mypy AST serialization" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash = "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb"}, - {file = "ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101"}, - {file = "ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d"}, - {file = "ast_serialize-0.5.0-cp39-abi3-win32.whl", hash = "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a"}, - {file = "ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash = "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590"}, - {file = "ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642"}, - {file = "ast_serialize-0.5.0.tar.gz", hash = "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6"}, + {file = "ast_serialize-0.8.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:3d822605fa7bb326ef868d25fafced7fc660fa46d9b90c02ea86d5e2f5d325f7"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:2efa40b068197d5efb62655b43baadb842ed71c4958cccd3e8b86a35726f0119"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:db1b957291bca08c7e72f43a12357b2948e20775d970e3fc3dac0aa3160ab725"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdc0d5b18ff8fb364e87923e47c0a91d0d69dbcaeaa274591f7fd26892cc3a3a"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9da7330f3e235bf7da89b8d39205c6350fc0c08a85379743f2df9fff87d6d980"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3186969ee66a9863b00acc6523ace44c56974eecb348a7ea4b228d9f0b80e19"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40a57b73731be45da4fa41430c4d5dc94a24b3a4faba7b9e069978c0402064ea"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5075b9da3ef807eda752502446dfecea3b381c4900b7e27a5d5f4f899eb39951"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:293cc1c5bfa741f8e3fbe8175b9c07beee487c9a6fdbb25a5acad9f1df2d30a9"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0910c3442a75216dde0f102d854ba2aaa71d2482e0ee213630b9bf29584fba3"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43dd6d596879bb1cb8a12cc9dae7bb10090a39a35883026c24f82488a195619a"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8c9d537f59e936392cfd3597789d1390304dd659efc3c486ce7f40fb6b8a9f53"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f0190a33d7f97c65e9069f7a7f40499eea6b5cbe260c558378109caf20ce934b"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:77308ae6c5cf5264cc0f01a7c556ec77a9e68eb1f61b093534d698139fdc3b14"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8d53a23f27e1ed3a36b2d26fd2a1a6228c8e85a1ed62ff7cdb44bd610769f20a"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa5e7cb08f96fed9121f77b224151e41caf88feab9d652bb46c78202b6fbeda"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-win32.whl", hash = "sha256:fa70ed4dea0bb18b30a1789c77baa701d0ef30c474f2ccabdea61e25623a8827"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d8b3c8eee4c1baef9d4e84d2a59a805501617127be42615cb48970b15b0892b6"}, + {file = "ast_serialize-0.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:ac4f0a83c55a9b782f79ad55a5247b7db123c1db405959791c2ef886e9710c9f"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:86b8a1e6d90467345356098b040150e82fbc26d24a7a202224b13dc1f6264ca0"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:39e92ff8e8cb45947fe9007174b2950e1fb098e6abd00266a13cd3bcf6675068"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85d8d18db5b2dfcb3b7e38a4d600ca35504c0ed8a6f75cd1c811e4ffe248a15"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9830ff7e764f74d9eefb01170c61a9f0fd2c027dac5fcb72e064decd57d56371"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6479d9722a4cd21b578f5478074c41e6169f04811996ec881655560f703a5bba"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a63bed264e818cd83eec11feed0f50aa162542b91132ef58afebc857182763a5"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d187197d234aa45d6cfa2b096be5f666e8cc2e7eb3722d0ab8926293cf5720c"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:2d39a56282cfcc0d8eeea37267c754be59c98d48505c23b1dae5c6011f3813dd"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7cc5f10386994c0f4844f1e6d6a97127e9b478660eb6dec2b257644f0acab64"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6102f2f985c2e542be85cd857678ec9356fefa792b93cadfadd31139f5696f27"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:3a8660fe66667b76a6e9dccd1d33e66b229fde3b308db991c041609226c005b6"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:e7266307e5fba39836edb79def8608887af48820508bff3c5f2941e1e04d1534"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca7e6fd1ad845d1cc649dc2ecd499db2f8f46af5bf8da7b70dd858774cc038b"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:2880350b13d3eae69a0d70bc1fb6c9bfaca4dbd0e20ba8cd1aa483080b56ff06"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:ab0f9a59f7d63d0d441b56b9a818b273705264352d5115cfee12e940e816d958"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:0485a25ef519c62e749ee3c1ad8070e591b380d67226349eb5a70b228dc1ac4a"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:bd84d60bca7079e741be4ac5dbe237751a59d7f6f9f0126b11880d63822cbe16"}, + {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:057769b5921336eb2d9124f2a731b42ed05ffdac559b840dbdf6f3937cf153dc"}, + {file = "ast_serialize-0.8.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:a02cbed7d8bfdcdee88edaac12bd50d53d9953aaa2e1852ef078625be5f1c0b5"}, + {file = "ast_serialize-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e1bd223df0f6c96b396975fa604cb33bce53d9b4a0185490be4c4a289f7c9c87"}, + {file = "ast_serialize-0.8.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ddd3b61f45c132da66c5476b281891e08c1fd87fbdabe8a6973e1622efc85f06"}, + {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f9caa63fad8241257ae401b5ff0a64026c6adb36b8e86cbe8782d9ea505daf6"}, + {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3926fa117b5e65019853a2969966d11c7175af377a3425991f3fe73784412405"}, + {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:485f1113af805e9e170b95ef993ca3fbd4f89c04bab25c58b4fc632d854801ab"}, + {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccebbed24f1281062d5852353c72c47502955926cfcb8345ffb3a44d87ff3d3"}, + {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:252f883290d1cdb728eb7fe1d9a7221b88af5a329aae0bc91ddee4dafb820331"}, + {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:96abc072ad29db8d02194afd47d68987322622787daceae82398d7b69f3ba2e6"}, + {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9118ad3e369727060b2696fc4078f250ecffca4248ba87f537f55cea9f9dce06"}, + {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f359df4bd921918af8bebd142a376c77511d7151cc8ba852760b587b5a4a54f3"}, + {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:e94f9121d13fa36cbf21314783c77d05ae3a0868decd18cf5233fdcc6de49ac8"}, + {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:54f95b486018d262bcb387a9afd96f0da74508b442762b80c769454a6fbb3ee3"}, + {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c38b915511e32bc718c49dbce98ff9af36bac0ad6a604f58000cd5e3aecdba7"}, + {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:9a2ef9cf12f2de4f1028c42c1dd7d775255e0fb3e5bb48896c97e35ef52366fe"}, + {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f18048fe9f6dd266bd577cdec48bdcecb74faaa01fe941324435483b013ed2a"}, + {file = "ast_serialize-0.8.0-cp39-abi3-win32.whl", hash = "sha256:31883542dd6c94d178f5db3d32fbd69c5eb88b3a7c018e7ac8cc0c45195ddbed"}, + {file = "ast_serialize-0.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:861794565b06337005c1447ef23103a3d5a627d08bdc827870d00d0b28ef5f51"}, + {file = "ast_serialize-0.8.0-cp39-abi3-win_arm64.whl", hash = "sha256:b2a5978662fd4db463dfb4b974d2b10ac6430b98f5333aabc7051909df3561d0"}, + {file = "ast_serialize-0.8.0.tar.gz", hash = "sha256:6c37c43e4004dfb42d321ddedc569dc17ff4259296f3af577c9ea46a809bc010"}, ] [[package]] @@ -1398,103 +1422,133 @@ typeguard = "2.13.3" [[package]] name = "coverage" -version = "7.14.3" +version = "7.15.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "coverage-7.14.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:360bec1f58e7243e3405d3bdf7a1a8115aa9b448d54dc7cd6f7b7e0e9406b62e"}, - {file = "coverage-7.14.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed68faa5e85de2f3e400bc3f122e5c82735a58c8bb24b9f63a2215954ba17b2d"}, - {file = "coverage-7.14.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:830c1fca669c572dec37ce9c838224ee45aac5be0f6961edf871e82e49d6537c"}, - {file = "coverage-7.14.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a64caee2193563601dbaaa55fe2dcf597debef04a2f8f1fa8a07aa4bb7ac7a1e"}, - {file = "coverage-7.14.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0096fd7559178f0cc9cf088f2dbd2a02ef85bacaa69732c633517286b4494610"}, - {file = "coverage-7.14.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6197e5a00183c11a8ce7c6abd18be1a9189fd8399084ffc95196f4f0db4f2137"}, - {file = "coverage-7.14.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7dfe427045520d6abca33687dfef767b4f635015893a1816c5decb12eb72ce18"}, - {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9a3f142070eb7b82fc4085a55d887396f9c4e21250bccebe2ba22502c45b9647"}, - {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64b2055bb6e0dc945af35cdeceb3633e6ed9273475ef3af85592410fd6803803"}, - {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1551b4caac3e3ec9f2bfcec6bf3776e01c0edbdd2e240431a50ca1a1aac72c27"}, - {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:583d50d59142f8549470bd6390471d0fe8b8c8d69d6a0f28ac71e05380cef640"}, - {file = "coverage-7.14.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0bb8a6bc7015efdf8a928753b25da1b9ca2d6f24ef04d2ee0688e486f32aae7"}, - {file = "coverage-7.14.3-cp310-cp310-win32.whl", hash = "sha256:d48400185564042287dc487c1f016a3397f18ab4f4c5d5ec36edc218f7ffa35b"}, - {file = "coverage-7.14.3-cp310-cp310-win_amd64.whl", hash = "sha256:eadea7aba74e40adee867a8c0eec17b820b061d308a4b014f7a0e118c2b0aa61"}, - {file = "coverage-7.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e574801e1d643561594aa021206c46d80b257e9853087090ba97bed8b0a509d3"}, - {file = "coverage-7.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f82b6bb7d75a2613e85d07cefa3a8c973d0544a8993337f6e2728e4a1e94c305"}, - {file = "coverage-7.14.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a2335ea5fed26af2e831094964fa3f8fae60b45f7e37fcc2d3b615b2add3ad87"}, - {file = "coverage-7.14.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fbb8c3a98e779013786ae01d229662aeacbc77100efbd3f2f245219ace5af700"}, - {file = "coverage-7.14.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac082660de8f429ba0ea363595abb838998570b9a7546777c60f413ab902bbde"}, - {file = "coverage-7.14.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ac012839ff7e396030f1e94e10553a431d14e4de2ab65cb3acb72bbd5628ca2"}, - {file = "coverage-7.14.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5952f8c1bda2a5347154450379316e6dfa4d934d62ca35f6784451e6f55074fb"}, - {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8cf0f2509acb4619e2471a1951089054dd58ebea7a912066d2ea56dd4c24ca4a"}, - {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2e41fd3aab806770008279a93879b0924b16247e09ab537c043d08bbca53b4ab"}, - {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f0a47095963cfe054e0df178daca95aec21e680d6076da807c3add28dfe920f7"}, - {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:a090cbf9521e78ffdb2fcf448b72902afe9f5923ff6a12d5c0d0120200348af9"}, - {file = "coverage-7.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d310baf69a4fbe8a098ce727e4808a34866ac718a6f759ae659cbd3221358bc"}, - {file = "coverage-7.14.3-cp311-cp311-win32.whl", hash = "sha256:74fdd718d88fe144f4579b8747873a07ec3f04cb837d5faec5a25d9e22fa31a8"}, - {file = "coverage-7.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:cc96aa922e21d4bc5d5ed3c915cef27dfcbc13686f47d5e378d647fbfba655a2"}, - {file = "coverage-7.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:c66f9f9d4f1e9712eb9b1de5310f881d4e2188cfcba5065e1a8490f38687f2c4"}, - {file = "coverage-7.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3d74ff26299c4879ce3a4d826f9d3d4d556fd285fde7bbce3c0ef5a8ab1cec24"}, - {file = "coverage-7.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:96150a9cf3468ea20f0bc5d0e21b3df8972c31480ef90fa7614b773cc6429665"}, - {file = "coverage-7.14.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:27d07a46500ba23515b838dbcf52512026af04090755cf6cc64166d88c9b9a1a"}, - {file = "coverage-7.14.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:621e13c6108234d7960aaf5762ab5c3c00f33c30c15af06dcbff0c73bf112727"}, - {file = "coverage-7.14.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b60ca6d8af70473491a15a343cbabab2e8f9ea66a4376e81c7aa24876a6f977"}, - {file = "coverage-7.14.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c90a7cdd5e380e1ce02f19792e2ac2fbfbf177e35a27e69fd3e873b30d895c0c"}, - {file = "coverage-7.14.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5d788e5fd55347eef06ca0732c77d04a264de67e8ff24631270cdff3767a60cf"}, - {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62c7f79db2851c95ef020e5d28b97afde3daf9f7febcd35b53e05638f729063f"}, - {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:90f7608aeb5d9b60b523b9fb2a4ee1973867cc4865a3f26fe6c7577073b70205"}, - {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1e3b91f9c4740aeb571ecf82e5e8d8e4ab62d34fcb5a5d4e5baa38c6f7d2857c"}, - {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c946099774a7699de03cbd0ff0a64e21aed4525eed9d959adde4afe6d15758ef"}, - {file = "coverage-7.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:16b206e521feb8b7133a45754643dead0538489cf8b783b90cf5f4e3299625fd"}, - {file = "coverage-7.14.3-cp312-cp312-win32.whl", hash = "sha256:ea3169c7116eb6cdf7608c6c7da9ecfcb3da40688e3a510fac2d1d2bafd6dc35"}, - {file = "coverage-7.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:7ea52fc08f007bcc494d4bb3df3851e95843d881860ba38fe2c64dc100db5e7d"}, - {file = "coverage-7.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:8cec0ad652ec57790970d817490105bd917d783c2f7b38d6b58a0ca312e1a336"}, - {file = "coverage-7.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:47968988b367990ae4ab17523790c38cd125e02c6bfd379b6022be2d40bdc38c"}, - {file = "coverage-7.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0ee68f5c34812780f3a7063382c0a9fcbb99985b7ddcdcaa626e4f3fb2e0783a"}, - {file = "coverage-7.14.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fa9e5c6857a7e80fa22ace5cf3550ae392bbfc322f1d8dd2d2d5a8be38cec027"}, - {file = "coverage-7.14.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:98a0859b0e98e43e1178a9402e19c8127766b14f7109a374d976e5a62c0e5c73"}, - {file = "coverage-7.14.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69918344541ed9c8368566c2adc03c0e33d4550d7faa87d1b35e49b6a3286ea9"}, - {file = "coverage-7.14.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b7f300ac92cd4b570724c8ffbbd0c130fee298d2447f41d5a3abf58976fae1de"}, - {file = "coverage-7.14.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11a7ec9f97ab950f4c5af62229befc7faf208fdbc0116d3902d7e306cf2c5abd"}, - {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a571bd889cd36c5922ce8e42e059f9d37d02301531d11374afa4c87a578625d5"}, - {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de76caefc8deabb0dd1678b6a980be97d14c8d87e213ac194dbf8b09e96d63fb"}, - {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d20a15c622194234161535459affa8f7905830391c9ccfa060d495dbfe3a1c7f"}, - {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b488bd4b23397db62e7a9459129d01ff06a846582a732efd24834b24a6ada498"}, - {file = "coverage-7.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a3693b4153394d265f44fb855fdc80e72403024d4d6f91c4871b334d028e4e0"}, - {file = "coverage-7.14.3-cp313-cp313-win32.whl", hash = "sha256:338b19131ab1a6b767b462bfcbaa692e7ae22f24463e39d49b02a83410ff6b37"}, - {file = "coverage-7.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:b3d77f7f196abdef7e01415de1bce09f216189e83e58159cfeef2b92d0464994"}, - {file = "coverage-7.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:e6230e688c7c3e65cedd41a774eb4ec221adc6bfee13768231015b702d5e4150"}, - {file = "coverage-7.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:605ab2b566a22bd94834529d66d295c364aba84afd3e5498285c7a524017b1fc"}, - {file = "coverage-7.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a3c2134809e80fac091bfed18a6991b5a5eb5df5ae32b17ac4f4f99864b73dd7"}, - {file = "coverage-7.14.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c02efd507227bde9969cab0db8f48890eb3b5dcad6afac57a4792df4133543ce"}, - {file = "coverage-7.14.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1bb93c2aa61d2a5b38f1526546d95cf4132cb681e541a337bf8dfd092be816e5"}, - {file = "coverage-7.14.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f502e948e03e866538048bba081c075caaa62e5bda6ea5b7432e45f587eb462a"}, - {file = "coverage-7.14.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9973ef2463f8e6cfb61a6324126bb3e17d67a85f22f58d856e583ea2e3ca6501"}, - {file = "coverage-7.14.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9be4e7d4c5ca0427889f8f9d614bd630c2be741b1de7699bca3b2b6c0e41003e"}, - {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a574912f3bde4b0619f6e97d01aa590b70998859244793769eb3a6df78ee56d3"}, - {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:e343fb086c9cd780b38622fea7c369acd64c1a0724312149b5d769c387a2b1f5"}, - {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:3c68df8e61f1e09633fefc7538297145623957a048534368c9d212782aa5e845"}, - {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3e5b550a128419373c2f6cec28a244207013ef15f5cbcff6a5ca09d1dfaaf027"}, - {file = "coverage-7.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2bfc4dd0a912329eccc7484a7d0b2a38032b38c40663b1e1ac595f10c457954b"}, - {file = "coverage-7.14.3-cp314-cp314-win32.whl", hash = "sha256:0423d64c013057a06e70f070f073cec4b0cbc7d2b27f3c7007292f2ff1d52965"}, - {file = "coverage-7.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:92c22e19ce64ca3f2ad751f16f14df1468b4c231bd6af97185063a9c292a0cb3"}, - {file = "coverage-7.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:41de778bd41780586e2b04912079c73089ab5d839624e28db3bdb26de638da92"}, - {file = "coverage-7.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8427f370ca67db4c975d2a26acfc0e5783ca0b52444dbc50278ace0f35445949"}, - {file = "coverage-7.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d8e88f335544a47e22ae2e45b344772925ec65166555c958720d5ed971880891"}, - {file = "coverage-7.14.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:beaab199b9e5ceaf5a225e16a9d4df136f2a1eae0a5c20de1e277c8a5225f388"}, - {file = "coverage-7.14.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3ff255799f5a1676c71c1c32ec01fd043aa09d57b3d95764b24992757184784"}, - {file = "coverage-7.14.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:878832eaac515b62decfa76965aed558775f86bf1fc8cca76993c0c84ae31aed"}, - {file = "coverage-7.14.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:611e62cb9386096d81b63e0a05330750268617231e7bd598e1fe77482a2c58a5"}, - {file = "coverage-7.14.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:02c41de2a88011b893050fc9830267d927a50a215f7ad5ec17349db7090ccf26"}, - {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:526ce9721116af23b1065089f0b75046fe521e7772ab94b641cd66b7a0421889"}, - {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e4ed44705ca4bead6fc977a8b741f2145608289b33c8a9b42a95d0f15aedbf4d"}, - {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2415902f385a23dcc4ccd26e0ba803249a169af6a930c003a4c715eeb9a5444e"}, - {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b75ee850fc2d7c831e883220c445b035f2224de2ba6103f1e56dbd237ab913f7"}, - {file = "coverage-7.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dc9b4e35e7c3920e925ba7f14886fd5fbe481232754624e832ddba66c7535635"}, - {file = "coverage-7.14.3-cp314-cp314t-win32.whl", hash = "sha256:7b27c822a8161afbe48e99f1adfb098d270ae7e0f7d7b0555ce110529bdb69cc"}, - {file = "coverage-7.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:39e1dbbb6ff2c338e0196a482558a792a1de3aa64261196f5cdb3da016ad9cda"}, - {file = "coverage-7.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:68520c90babfa2d560eca6d497921ed3a4f469623bd709733124491b2aa8ef3f"}, - {file = "coverage-7.14.3-py3-none-any.whl", hash = "sha256:fb7e18afb6e903c1a92401a2f0501ac277dca527bb9ca6fe1f691a8a0026a0e8"}, - {file = "coverage-7.14.3.tar.gz", hash = "sha256:1a7563a443f3d53fdeb040ec8c9f7466aed7ca3dc5891aa09d3ca3625fa4387f"}, + {file = "coverage-7.15.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0be6daac4cce6b8c8dc65886bae1b082ddbca4da8e5cbb5e15166acf253e264"}, + {file = "coverage-7.15.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b24e078eabcd6a9caa8b0713f9bc1eeb310bcc960a29d45a3b4fcd4b16d5b11d"}, + {file = "coverage-7.15.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cfe20cc8cf8821d4fe54f89106cbf06aa27f37b5bbe3535568065a81539b4150"}, + {file = "coverage-7.15.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:83cf06cdd687677742caff1a9134833b7a8b75f111519d2cb0e0ba1b9a851e15"}, + {file = "coverage-7.15.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8fa4de68e2a752468ff14b4e15db7def689a71be759e826a31ccecbef69c5fd0"}, + {file = "coverage-7.15.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4dff9daa47d83120c3ec38ce921214242944a832aa04e903e50b5b7ebac8972d"}, + {file = "coverage-7.15.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a093fd37229918976f602aa07aa59e0973cde82186f220c8e197f721f5be0ce4"}, + {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:317db01a2cb02552fd67e2b1cca77a4b528a2a277176c5e0bf2cecbb639d3f54"}, + {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8ee3838dcb656602c3b51e16aed9bfb0822f8d8d6d1c5966d32ec8c104be8e20"}, + {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:425920379052ff1fe465268f3361d35804a241bbdd5a1b592c8cb60df4c52325"}, + {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:69bb2400abef928e365ea7d4d9925169ada78ed2295546780002d4b65de3df88"}, + {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:81661f82d302484e3119e7c80c519c02fa9bcc2a6b339baf67d67bc89c580f04"}, + {file = "coverage-7.15.4-cp310-cp310-win32.whl", hash = "sha256:cb476b2e828ecb71cb6b6a928d23fd20a7ddb501188022dae1c37499149cc338"}, + {file = "coverage-7.15.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fc2130bf37df31852a8384f12601563a45a0024bccc6624f38355cba7a8d360"}, + {file = "coverage-7.15.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bbac5abad70df71019988f83f26ac7092ff2642975def4429e98dc7585ef3490"}, + {file = "coverage-7.15.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:357a173465c7ce028d07a95cc2b63b5bf59f50ecdd5ad75c5cbb78ada984048e"}, + {file = "coverage-7.15.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:21b803935e2efc3acebe9697197a294fccf5dc4e5382bd6369542ff7a7d2a1d7"}, + {file = "coverage-7.15.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7a2b580774a4786c1053157c0165e04476e03ff293993d7c148eee784a94bae6"}, + {file = "coverage-7.15.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9464451c4efffe8d47ace5a540b10b0dc10e879066290f8600872b7f54a419d"}, + {file = "coverage-7.15.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de602f34123c2f4af1c1869c6dbbbd60da6d5983bf01937367295d135cccbfce"}, + {file = "coverage-7.15.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6879ded16a27f3eeca19b900c147e81616e7054db451471a611b2755ee5249f7"}, + {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:986be58c3ab54aae8d3496a6225eea74f760fdbe739b38bd442c7e8d133aa53b"}, + {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c6103639613fe6c1e989082948419bc77a2d26b6c825c99d7fad25f7d3d87afc"}, + {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d3af93dddb5659276c63bc16ac6466ac2033a70ca816097bbc06345b8ccdf571"}, + {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:b10075e5421d04265766a6d1dac809bbeb8a946fbb23c8f82c227409b2190719"}, + {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a67a9f78b2942d87ba8ce3059c642164d2aedd65337377fb52fe9803656bc5c7"}, + {file = "coverage-7.15.4-cp311-cp311-win32.whl", hash = "sha256:69484d1aca26e322e1c3ce03f09341e84524ababad2d7202161738d83cc9f82e"}, + {file = "coverage-7.15.4-cp311-cp311-win_amd64.whl", hash = "sha256:63fd6fcd1dd6e158f7eb78606e72933b3f6d01e7b747f99c6c12d764307a0fdc"}, + {file = "coverage-7.15.4-cp311-cp311-win_arm64.whl", hash = "sha256:ea82116c9893fa89e929b7f197ee5a1950a76e91cc5c85ba503fc02379d04890"}, + {file = "coverage-7.15.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d4fedd1f7f428f9fe83b1ead5e7cc87a43427be31aadafbac3ac0636dc7abb22"}, + {file = "coverage-7.15.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:37e2f0cdf58e2e1fed4e4d5a8f8786ae2f7eb80b478016876667dc4a01d60a97"}, + {file = "coverage-7.15.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fb55d0e70bb15f2e81477613627286581414693d74ac7963c93a790dd453ca9d"}, + {file = "coverage-7.15.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:899b9da30f3c6c336566e3707495bb23e8302d39d862f01fa78c48b99b9437e2"}, + {file = "coverage-7.15.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d15715e8c46552827e5e4f30a35575a2dbcad14454cf3284c54483946bd16931"}, + {file = "coverage-7.15.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:002a438859f7b430bc99afeaf01a6d187dad1d0dc907b64cdeffc632a5db8fd8"}, + {file = "coverage-7.15.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e4193a04b518f7968f3099755f5509ee7cccc6dc2b92a6b14841934d22e222c9"}, + {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e98dcc55d572b38e69d117da7e8e8efb8500f1f5eaf81ecd460a63220790b839"}, + {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:af6c538498ce66c10d3fd541c2a8d5b03da5850355add34e6cba564210cb9e72"}, + {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1d10025d96ea89fc2f73714dbc4cbd433fe012c1ac9e23f895d7728b238b6e52"}, + {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d802e1947603162ded419bff83ac7489820355d2b856dfb09206574e3a37ac0c"}, + {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2de40895718f91951b86712b4c5b694acaf9a0a49be13874896f599a1eed3f4"}, + {file = "coverage-7.15.4-cp312-cp312-win32.whl", hash = "sha256:5c3431b2161279b7db5c2a1aa58ae02e5cb8c3c42d93a5094be3f5537bd5b11b"}, + {file = "coverage-7.15.4-cp312-cp312-win_amd64.whl", hash = "sha256:6befeab5fb2b51c958ca4ac6c5d141a1e8240f4f76e46350f1911963deda49cd"}, + {file = "coverage-7.15.4-cp312-cp312-win_arm64.whl", hash = "sha256:67bc345491ab55b837277d76f5775d057e8c7f1ac44d890d8c2c82adde258c6f"}, + {file = "coverage-7.15.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c705b28feb2775dc82a25f1d473a370bc37ff93f5177f4e29ce2425f560f6921"}, + {file = "coverage-7.15.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3ff205ab5e3ecc670f6a4dd19d9cbf12ede53dd41cfc1e15716ec961ea6d314e"}, + {file = "coverage-7.15.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5172326e861a38b48b48befca15e0f477a26b283337a33a739c8fed229934e36"}, + {file = "coverage-7.15.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:12b59c90084e3234fb11184886bf4a40f4f16a8c8f867be2e087b81f8e8868d4"}, + {file = "coverage-7.15.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349062d66f00b40fa2c1c222438bad25fabf755631b5d82937fe985c8008615c"}, + {file = "coverage-7.15.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4256ced708e598e05209bc1a8ab4074e04a51dba4c62fb45926a229af675ace7"}, + {file = "coverage-7.15.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d80f974b20782d9612c8b4c9beeca867074c7cf4079d1419843fa25a26428b25"}, + {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2e179f19bfe1d31f8eeeaa12990194d761c4f62f0759661000bca6cd8729f40b"}, + {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8bc16bb47b7679670eceff71d78bfb7d6e5b143f6c2cd117487ec7c75e0d4b78"}, + {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1cd685005cd2c4200adfc14cf39a603b9320efab3f18a8f7f156d20c9cc3345f"}, + {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:337399ad2c93b3acd2a937627dae8b3e86b66707cd3d3e856347999aadf1ef8d"}, + {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:96e257121228ec5cd2bb919276e94ac11074471bc37d68dbae0e8308cce15fff"}, + {file = "coverage-7.15.4-cp313-cp313-win32.whl", hash = "sha256:c65a9e0dfc6143491879da4e13b5e30f8be192055de508d737fb14601edbd22c"}, + {file = "coverage-7.15.4-cp313-cp313-win_amd64.whl", hash = "sha256:2ff8f5e9b8f7a94f0c11c45631eee103dbcb7d63274edd12c56efe1be690b3b4"}, + {file = "coverage-7.15.4-cp313-cp313-win_arm64.whl", hash = "sha256:6e0a8a5083b096487d6cfced94cdd514d8f5db6f113610fb36c0620edb1028cf"}, + {file = "coverage-7.15.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:770e9325ab5ea6d56f77e59b29ecfe0ac20b57a82a601876f90494a4dda0386f"}, + {file = "coverage-7.15.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d12b33a3a50a1676b7784dc8d00a0c6d66a9f2add4b85a041c19b6a7e53ef23c"}, + {file = "coverage-7.15.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5669c8378ebde86f5def7a25d29586631b58acc27ffde04399f678f3dfc6e082"}, + {file = "coverage-7.15.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ff97a14362eef486483ed44042ca2027ea257df6ff768e62358ee0c9776925ac"}, + {file = "coverage-7.15.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a325e815318638aed1655d9c06e6d7c2d3d46c09231ce988070428a8762d734"}, + {file = "coverage-7.15.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:474223409d88eb20d2d6a0d37ea60e8647a65a90cc008dc1f0410af5f64f1e0d"}, + {file = "coverage-7.15.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7f2f62ae3cd189dd2e13aece758c57b3eecbd27be070dbd4cbd10936049e5dbf"}, + {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:39ece820e29e0a2ba34b3ecb3be83c27e997eed8926f2ba6fe7ce7a0bda5843b"}, + {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f21b56dcace11dfe013014201f577dcd592b2a9b72182d930361b47cf6f73f25"}, + {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:93a3a0b662abcc10c73a47cbc72cd60f63618d6989fb2d1286e50eacd974f303"}, + {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:141fae2cabf5569b782c10afc4c850ce10f618c13f8db54765cba99cc839da1f"}, + {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:81294c7e6ab30c5f74c0353b11b2fd6320e72d9bee6ac73b357caa8b916323a5"}, + {file = "coverage-7.15.4-cp314-cp314-win32.whl", hash = "sha256:7bbd7d6418e0dab31a206af5203bd43ae36edb8e7fba1940b055d3e9249290d7"}, + {file = "coverage-7.15.4-cp314-cp314-win_amd64.whl", hash = "sha256:f0204ed122758782970526057093f448051a39db9d810d4e344bb87a3546f425"}, + {file = "coverage-7.15.4-cp314-cp314-win_arm64.whl", hash = "sha256:9e71e7bc71c686a123347ae47a0de33a175e797a85bb57b791492adf4eec8ed8"}, + {file = "coverage-7.15.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7c922735321eef3f87c280a3d39afff6b646723a2880b862cda4ac7a093b8aa8"}, + {file = "coverage-7.15.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f41c17c4668a655ce96d090d8d5ffdc24ef64b5a02f9753884d08483e8a4a41a"}, + {file = "coverage-7.15.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:46822e9b6ff1c6a72b518c162c44a8f45a61a1d609c51084bf5b16c023c5037b"}, + {file = "coverage-7.15.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d6f4955b73b5445271379a59e3792b0d978f42d4a01e0cf7a67d9c33a3bb0a5"}, + {file = "coverage-7.15.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3fc9e047706fb4a9abb54f719d3aa643e80e5bb3818182c40aee01ac0f0247ba"}, + {file = "coverage-7.15.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05e491d4f3165d62d4f5c8fd48dfeabf2ae8f42cbbd484319af33ea851b78982"}, + {file = "coverage-7.15.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:226c66e80ec0598d3b9b4874123df167ccca342aca8714f77cac6829688ee09c"}, + {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac41cc14bebda0dbfb0628036b7f75706935c95bcc07fefe9a0f93614aa60a57"}, + {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8af623e5cd92080acddd02b38f2f406a2c3a0893c38950b211890361448fbf26"}, + {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07545711d4f0f32852a18f18ad11f76f0109909d09e78b9008b4cfc67e829429"}, + {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a0865421cfdc53654b342d515e5a233187590882d20b95752150e53f65460017"}, + {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:460115e32ee40566476db5048f9bec1e842c127ad8e6f8be745aad3ac9cbc839"}, + {file = "coverage-7.15.4-cp314-cp314t-win32.whl", hash = "sha256:cbde877ef9dd7baf272b9bfef2b8a25edd45d9170fc326951dd20eb480335e85"}, + {file = "coverage-7.15.4-cp314-cp314t-win_amd64.whl", hash = "sha256:3da9e92d1c551fd7563833e9ade686efb0c4b7363ab7681a94283958c950bf5e"}, + {file = "coverage-7.15.4-cp314-cp314t-win_arm64.whl", hash = "sha256:3a54f5a0d85050c73a38f6793090ee83974531e67fe5e57a1da9bee11398aa5e"}, + {file = "coverage-7.15.4-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:2c9872e4d9dc5d3cf616bf4b382f5a00359305a5be666a3dd0b5cdb4e49597f9"}, + {file = "coverage-7.15.4-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:e101dbb4b9b72f0cddd8cdc8c9c5b47f456766f5e0ac82dbfb75e5c55409b78a"}, + {file = "coverage-7.15.4-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7d1abebdb047729e852b9c77a00497dfbeb11eb3a117e037d7dbc3ac8e5f5c54"}, + {file = "coverage-7.15.4-cp315-cp315-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d28a4a899354d0ea6214cc59b4fa19eefbce1b9ff1688ab579acf49e894bd3fb"}, + {file = "coverage-7.15.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffb3c2aacea411cc7e1d27712490c11108e2de1d39019ae32915493a59a8b9ed"}, + {file = "coverage-7.15.4-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9447978a92f405d301123cfd39ff49895490efb769a758fe2734c7f631bf8ce"}, + {file = "coverage-7.15.4-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:050467a7983b8e2fe7dd41a78bb30c3e7f8c0b8cafda14b1c46f8b5e3cf2dd3c"}, + {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:d003b7a5708ddad5c206c79607a6b92abb6fc13c57d99d8a4468cc03a2941ced"}, + {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c38efe30fd74e5c19e9433f11fb1f5dc9c6522770971b7c6145bbaa413dc8800"}, + {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:1f4f826d70f772ab8b0c052329580d7fe8b8abd191e4ce0c8f81aec6614665d3"}, + {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:4a4bf917c9953f57c957be31c1cd504e3bd2f34d4a352b9d391a3025336f6768"}, + {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:1c9bf40ebef178a45192c75c4964760bb261b0e6ad725da5fc4c93f674f19753"}, + {file = "coverage-7.15.4-cp315-cp315-win32.whl", hash = "sha256:43619d04c3671792d2c4706ae8bf45e265dc87bbd4078189ef8b847ea1e74be2"}, + {file = "coverage-7.15.4-cp315-cp315-win_amd64.whl", hash = "sha256:be619439dbcd31a2eab10b32de9fff62c26ed4bab69dc32b8363fdaaa0882809"}, + {file = "coverage-7.15.4-cp315-cp315-win_arm64.whl", hash = "sha256:def597967dafc2e8d97c9097ea453c464e0bb8ed38f193a43070f10dc623bb6d"}, + {file = "coverage-7.15.4-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c7dbc748ac8a1e3e59a2b28bea47675e6e778081dbbf081bde0d75def2fcbe1d"}, + {file = "coverage-7.15.4-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:2413074a5ecbb61a01a7888fc72db0ca324d13588c5b38bc0dd8564cdcdfea26"}, + {file = "coverage-7.15.4-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4e6f6f632b7b2f714bf7a1346e8f97b650ee71f3c298aaad42a2ab60f0f07645"}, + {file = "coverage-7.15.4-cp315-cp315t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8df457da2249d3c75ca2e5e835d59c725abfe92d27fdff6cd99eed85b51d5e9a"}, + {file = "coverage-7.15.4-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:050f66a08805acb5b8a23c6d4a517b1ecf82c08e81ed0e4bd727df065e5c6624"}, + {file = "coverage-7.15.4-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1587fb771d1ccceef708fdde1e5af8c7ed24b486b61d13a321acb7d8145390aa"}, + {file = "coverage-7.15.4-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b4f1c3a69ca580f3fbd6b2046915f536d7f586874f25c1bb23add2a3c88d50f"}, + {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:ffb58d7eff5b7f6ecc6fa21d6288ab7f968a212cb67d682c269c09b9eba3b66f"}, + {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:d9df165544774574ee004b953023d1bebada1894a80b1052a43d798b0f676e67"}, + {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:f9de0a24a4079b53e523b5c5e2c5945ec251ab486652659955187cf255a259bc"}, + {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:150089274bdc9f940628552cb92844e0223c987f1902ab8efe9f45a2ec758d88"}, + {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:a58a94fed5da6997d258e8f7668c1e195fbd04a691d781b7558f1e468f9e68bc"}, + {file = "coverage-7.15.4-cp315-cp315t-win32.whl", hash = "sha256:ebd5a6d8466ff30836572f3ba2cae8a5e8f85029b1c6d5e2ed338dc472a5166a"}, + {file = "coverage-7.15.4-cp315-cp315t-win_amd64.whl", hash = "sha256:288bde2a2d7ab6b6c2d7252fcde8b524387f2d970bdba9658fc6f8bbcaef0f9b"}, + {file = "coverage-7.15.4-cp315-cp315t-win_arm64.whl", hash = "sha256:68be5e1de60ff13c9095bbec0e5a7fa45b33b101752215b91345ea1f61c4a278"}, + {file = "coverage-7.15.4-py3-none-any.whl", hash = "sha256:964730a1e9de9c0cf11be6a1a3c79ce419c34882842abd256086ba4698705e84"}, + {file = "coverage-7.15.4.tar.gz", hash = "sha256:0548198fff07ccf4faf469520bce1c2eceb1ce3e62891921138dec10907f9d00"}, ] [package.dependencies] @@ -2343,103 +2397,150 @@ referencing = ">=0.31.0" [[package]] name = "librt" -version = "0.11.0" +version = "0.15.0" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"}, - {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"}, - {file = "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"}, - {file = "librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"}, - {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"}, - {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"}, - {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"}, - {file = "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"}, - {file = "librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"}, - {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"}, - {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"}, - {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"}, - {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"}, - {file = "librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"}, - {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"}, - {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"}, - {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"}, - {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"}, - {file = "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"}, - {file = "librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"}, - {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"}, - {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"}, - {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"}, - {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"}, - {file = "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"}, - {file = "librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"}, - {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"}, - {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"}, - {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"}, - {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"}, - {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"}, - {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"}, - {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"}, - {file = "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"}, - {file = "librt-0.11.0-cp39-cp39-win32.whl", hash = "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"}, - {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"}, - {file = "librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"}, + {file = "librt-0.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e1a49adf16a7c9d9646816c2946135527197b6fcf4347c7b8b761cf1bfbf4489"}, + {file = "librt-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81a398f45b45a59200e13cd5ad1ae1d3f44334de98b148331afe2cdfee701c52"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4eafbaff06b9563f8b1c850621ce51605de05208e09d4d71ce490bc972b7b9e8"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:b0411b4066db926b80258c60dcb0e6db4c9cee312eab45b7e8866b17ddf9ada1"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:febb1ce6cac545a54e6b769982824e955a700fdd9fbf3a08a3d82c990968b57d"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b230acc1c3bfe2d6f2627ba2b95dc92e58aa494600e9722d0e6ccbc931e59702"}, + {file = "librt-0.15.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6da110e5f314c19ab8478464d02ae18808ae73d522c15260fa4918acdcd64da9"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:eab9208b00ca55bf75983ec99f7bf13acc746a36102e98953addaad7f7ea1e1b"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6c013cd3a1721e69e14380ada97eaa4b7b0cdf1c6b96fa765d4ea47c875088db"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:567b1c430f8bd560e689421468278ac5941bab4a05303b5d95b6ae10db03f451"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:29c4cab9df457b19672c39be7f384ebb2bc925c4e2684b8780c222b43eb36389"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bccbd8e5b0bffb7106cf18eb1baa3d7194b1cebb3b4b1cdbd4bdb19382a6ee6c"}, + {file = "librt-0.15.0-cp310-cp310-win32.whl", hash = "sha256:8ae493ed5f659a7761c43d42f183db514536073ded9bcf671d2d1df47e29a07e"}, + {file = "librt-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:bc25fb356d0c7810bb49ff3df908ad1fda6995d660ab099ded69244ed7ab6053"}, + {file = "librt-0.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:823b92cf3c18ecd08afc70c42473888b41b6e8ef5046f3b82c05c154a2fa3d22"}, + {file = "librt-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70bc1b602cf59917e8f0c7a2cbc8bcc6fbc14d5486136b00707a79619121d63"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:814ff83a25b5fce8b9c80c4dd803153fb5c5599fc74db9e022466938368957ef"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:57f5eeb6ad4c180de583b1038e61fe5fbd9796bb69a8a1c1a0c7ddbec4c8c60f"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82909c8f7eb9952656b65d3147afde4cf8e6d5a991eebc86418b5e65843b0ab8"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f779070399f991400fc451719e0ea388eb7de313388bada2c127a35de05f798a"}, + {file = "librt-0.15.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bac89069bc496ebdf4f79ebb57bbd10d0b214c8454225deb672d91002bd17e18"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e0d00c708fb2f5822b152429b1ac80a58dbbbc3f6c232c4d13a3f7fcf2ea5b4c"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6c6624fe268625869485553dd7cc1daf30d22558215bb2a4ff16f67a9801a31a"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f56b397858a23dacf35ede366ed2212fdc03a6a57a1ad36468ad6e9dc5fac091"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4388184646efe2054911c5b00a1077d6d1ee86a95b7e8ba96dc7850a809f3f40"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97335f59082f9fe2ce6c2a9cc6433a0114bbb6cd4d5c09dd76c95c68b9f9a8b0"}, + {file = "librt-0.15.0-cp311-cp311-win32.whl", hash = "sha256:83380ffde38062a2e9bb55d83e74474f6614665528b98a6928720fc006dfffbb"}, + {file = "librt-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:f75720477ee05d509a310e856cacc8d909adc182f7b91193c207bcc26d7ee6db"}, + {file = "librt-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:256237037a3ab001ae8d9803b2d43562a4c3aa38739843694349e4d5ebb0fd56"}, + {file = "librt-0.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e87bc679f86a99aa3b26e3c78eeb821a247c9a28eae48eaafcc32c3bf4c3bb9e"}, + {file = "librt-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71599e011ac880e8e45d46047d714871894c7d4ab6f25626f8d4f89da21f368d"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c802434092b769b1d613ed2e13fac15fbfce1934a74bd10283b03c0fae231cd1"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5500eeae393a184d14e1f35645962c27129d20c81afa4069e6ef826ebc2b3aaa"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6ecfc32dfb46fb7b565bcd6abf9412acf978775a998273d22888a6d7953730dd"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cc46cfd15022e35084355478c9ac809d90b1152222706ac9a7655ec21df6fa"}, + {file = "librt-0.15.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d5f51401d102c885b9ca509e62c79b1dbff286e1b9b047fde6f763780789356d"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cc30523e3f1a23fb7511cc659834a0d01a1042bb9de359bc1c131cc4ec6c9656"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:59fe030d8ae4a57e3fb7756bf35a858de74e04066fc8555c53d0af979132af81"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a6526a2a956bbb1e4ae3568c82e650fc99119c66bb011ea60715744955a2b4d"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:85ea21ec6730194d67156b0e0b5430ccb1d61f8b8b907e39b37f9812b74a13f0"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1e47b8ba865d7ede071a91a7163073bbaeb72541f1ef8a07d512c45c7b5007f2"}, + {file = "librt-0.15.0-cp312-cp312-win32.whl", hash = "sha256:a5207ec414d1c4a2a7231b2086970dc036f94293cdf338190984958a013a42f1"}, + {file = "librt-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:73b30cfa976659b3917c8f6153bdb0591c6a9ec6583599fd24a689b690622022"}, + {file = "librt-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:a54cf9e0ef47b96af580849db5471142200568ce1e02cbf416addab551369570"}, + {file = "librt-0.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:db13ca398005abcbe538deda87b686d9bd08b7001cf40c4c06b444960ae10a26"}, + {file = "librt-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa1f1995789dca3698bc550aaceb09a51bd5df0a057ff84ff15296cd1975b801"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55456ea87d8df21808446d03817be2f65e20391c1c615d9187440dff28cd08dc"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5a86a5a08c2235316bdb359d5dbb6ce0abfca7fac06363103e2c5af571d92f95"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e56b6a368529bed262da40ce13f8fef590db0479819cca84f16a1f01ac356d0b"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:234d8d394721fa0d786af15ebf1f3fb7f3ed82fd1cd0cde45c2f247b5d4281d2"}, + {file = "librt-0.15.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d8363d7accb0286ac3a0e633f396e93800dafb8150494505daf9515bbda591f3"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0f0ee3644d951f31055ad07d77d92520e84505dd7a432cc4cd501dd70ee06785"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cfd1a81a648806e6a7717be4cc4d1bb392fa229752bf8444ba365e381e984d6"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a6cd22c9da0d866558e46a041f1cc0c2bbb26b61b137b2347fa834c332e1d101"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:6d5225ef8801e4ea5e482fa9b5dfb891dd9ef6f6d870f1f25d449ca2c70ac218"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d28a05796b99f749bf8794f17ba9ba1612d0076b802e9cfc62c554634e9ce3b"}, + {file = "librt-0.15.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:2067ff438048cead9d223ca5675bae2a25e520a7c3e6c1498bf9c6892d22caab"}, + {file = "librt-0.15.0-cp313-cp313-win32.whl", hash = "sha256:1cd3b721f24c206398b9e26da3c3a9c011e6e89d06f318ba8ebefc30f1003890"}, + {file = "librt-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:f395a4a9a03ac062dbe9a9f82e0c720502e590a38feee6a757bc82e9c63afbd8"}, + {file = "librt-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:0a15cb554761247d84a3ec0cbdf4078d70725384f0e4662c0fa3b26266eb60ad"}, + {file = "librt-0.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f5de7feedc56337a088eb15cd9fafa9938367362221d8cc62c642b7f94821993"}, + {file = "librt-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c0eb900c0e91f4aebe680845242e614f1864edfd44106380d0752ac29522bf8"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e8c9a650a188e38bac005048cbe6342e81407782944d01934540ab75e417df21"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:92bfed8deec93df30286b9fe9e3b1dd17329cc076a192b4ee5ec223841d54953"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec4b19788f835711a2072f9dbe6b03b3bf32ed1f0fb30cf399bdd59d9f0c33fa"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4c7bacb70930f3d0a56f4ecf1be474a1f0d941b01dd73b756f3c256d42cb879"}, + {file = "librt-0.15.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3e79f05e4a08b4d880342673312bbc895b56df7765605796f15902eb5367d3ae"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a417149c0cba4d50b61e992e5a15e69eaf96746609b461cc4ed168aeef6b79dd"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:da7a94d6a3411f579d72aa3e3bc5fbca7ed4549f3dbd7e5de3aa567333374285"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:856f743ae607f2c1380eccb566c0038a9fb3eabf0fc2be2704d76d9f73557239"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:779a6e7c894737e5983e7790a9c78c4000c30e23c9aada08081bdbea53b0fa60"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:96bb17dbe8bab3c0954fbebfc69ed395599de75b6bbc35e3270a878e15d4dd65"}, + {file = "librt-0.15.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:7220697efaa6e5348fc3d18ee7f8563d4bfecd9872b37ffb915bfc1d08840622"}, + {file = "librt-0.15.0-cp314-cp314-win32.whl", hash = "sha256:f54598964d357b1c5ab77cf5d92f21e598fe0e23cdbe9618480807f81b4eba15"}, + {file = "librt-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ff5893a2c23d886aa9ce786de5ac6ddc74aeeaf90743682b74d920e117d2e28"}, + {file = "librt-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:3722a099730704c9a3d70c879fc0f51daec25fe5f1555672d97bc595abeafb95"}, + {file = "librt-0.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:38c0c7d4b6fc06c3324b3f9162c8391bfc4fd9dde53afe1033ce7edb48d5a714"}, + {file = "librt-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8b2fdd7ead3c995c37940a790690660d0ca006c302db26cc51933f6766866fc3"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fde98cf1fc4bac144ce23c2c4c017b924ba714509ea9334977b0b27050c837d"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:e3b461183c5fa7681b48560f91515f53a953122fb30c71e07abc67d7ddf58c38"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4bbcc257e3babea20a91715c361b24554ec4e8f51aa578568afc230799fe1a19"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b845b8d48088fad0cadc84be4b8fda63203be7e9237b71015b3925443c1f35ab"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b30e600e8f337b9bd7f39b86d9fdfedc73cc46e3d0f745931a23a234220bb7e2"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:64b0c8c35aa4c4ed79896359f3e0b285cbe4e610042106500da4811c322cc108"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0da0d94cb802f32a0524653e7201f2cef72d5f700a5407678f5290483d4fcd08"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4a6369168d371207339b1e50d4532b06a7121586141f82599505a3f315751d47"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c434e072557ade9cbc642d052c89d031efe47d5c9614523619d0d74a02378e81"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7eec6a42018bc1d45763b1c162d3d2bf7c3b9a1b0ed30d3e91dcba390efefcc"}, + {file = "librt-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:6912fa5e635d74529ac7cdb1bdf6ca3af4453da8d1edbe0110ee1cb4ad407ebf"}, + {file = "librt-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8e11699ed745931c395acd3621b07062e0f840efa6935aad87a64ed0995f0915"}, + {file = "librt-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5d2a91724463bfed4f573cd7a9fdc856d2e230d0c0e5a61416a93481dccd8605"}, + {file = "librt-0.15.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:8443e38dcfcfdbcf5add5118c623efd788d65ac2e25756d6251a54a06a4d0aca"}, + {file = "librt-0.15.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:6d15a29033c57490cfe2069097c6fc4049e4e65ffbb749be7dc453b7c4c68965"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2c05c729b589e734c09578bf5964be48a911765484840d017bbc84f49d4c4ad"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:fa60887537e1d0cd2d9982269d33a709bf54b195cd2b9364fc0a758022af5bd9"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d8bc24219b24c0af375718942ab75e3544b2763085f40f965be4326734ae8328"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86a21a7bd3fe3a419512ef424cc1c020f6771d0b29cfddff36d1635a855e63f0"}, + {file = "librt-0.15.0-cp315-cp315-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dbab647e88d90b3167b91efe7091e248653688ed4337e4f90907a722c7361bb9"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:d8edcf6f550e918dca779c069b9e156385c60b406f99fc7641f32c52f7193659"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:8b62076030baa2d8b1501a46bf0e19c27a489aa90671c55665bff7887f7660b0"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:d00d20d1818e82a07a0ee0aa89a98b17ed7916b92441090b683719cb20a59b6d"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:4e6ee93fc3cf848dcbf0cce2eca73d8e7dcd0cc2b6df3a529d57750b30a4c55c"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:32896a0af72508ea979e0acb4e4c04cbeeae04938167950d535c83c45597167d"}, + {file = "librt-0.15.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:ec3ba415afaf951f6951b1dd16d3c8e4f540065fc382d7e70b823a79567ca374"}, + {file = "librt-0.15.0-cp315-cp315-win32.whl", hash = "sha256:d2813ba2503764f0450680c533d13df7cff9b49df1411062eded5f67db4195b9"}, + {file = "librt-0.15.0-cp315-cp315-win_amd64.whl", hash = "sha256:b87d67e33afaf265262f2a66db578284b88ee2e6fcd224579cb5c15518677ad8"}, + {file = "librt-0.15.0-cp315-cp315-win_arm64.whl", hash = "sha256:713bd7df21170b982e729e46870f31d6b437bd1a9b4648cffb529bd3c2ec5c4b"}, + {file = "librt-0.15.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:3de789c82752730f94782a5ee518baf9c05edf85733aeaf73bb6e518755cdf54"}, + {file = "librt-0.15.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:e0b5deec9a8664eb722c797241970fd4aa1894d25fda36a1ddac0f7407606bd6"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5563302a8359bc2295bb7084d1a8ed1519df96afb30eb2aa4e0bff7b54228988"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:22d6263b9d39d7bbb286fa791945646e3218f1be2d693e36fb630f1d0e59cd13"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39ffd14646190c454f0d86e0d256b33f00a87a26ab410e619773b841d0e41416"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47318cd3a61401452de11282242937e3e057c4fd3dbaf601e269d0928a06c0a"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a56a1d4f859a82ca5b99fc4b82c9b027b15e3c455c5cd99e7d0719f27bb20b6c"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:077471b3182db4e17c36ae91555f36a4d2c00080b267f749bcad34a478a9a302"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:411ca4d1b905b860ceba7570dd6717a71dedaddcc4b0f77ece710aa41ee11f8d"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:1256589e0b0adb31751d685a68bce29d73407ddf4ef05d4188f49d5dcf9566d9"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:f42b74a53e5f26a0ba0007411a7455b66c67ce4022a39cc1f56fc4efd65bcbab"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:291bf73caf78b9e88d6fae9bfd693207ff7d832e2fdbe2cf8e746bc13f5f892b"}, + {file = "librt-0.15.0-cp315-cp315t-win32.whl", hash = "sha256:c16d15ee371643ab48dc8248a3e680ebbeca573a13af2c3dd0c985b142d77162"}, + {file = "librt-0.15.0-cp315-cp315t-win_amd64.whl", hash = "sha256:dbd605739f228912dc49027cb764456b9757750bdc2b6b7773164db7096c6fd1"}, + {file = "librt-0.15.0-cp315-cp315t-win_arm64.whl", hash = "sha256:84d244b00604d17df3fc7736c327892d6bba66181254aa4087be807b6c342bdc"}, + {file = "librt-0.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0e2d0c0acf5b0ada7d045912b7cf787c21315c95b38b1fa939ef72d45d366b3d"}, + {file = "librt-0.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9ca190fe9edc0eb08eec558a509a16d28d91c35667b8f043cba40ed5e77a959"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80811e1c42386ea95c6fb30571d3250ad43d7863f883f787f70517f441150e59"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:88c2a17815c266e6d8180204ff62cb739ab869ada4a746d4c505331526ac58f1"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a5fa8f1f916988d0bf1afea005bda37f56ac41a18016e813ccf0097a8d460ca4"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:355e3a4c725225a14262004fc1872a552b9d3634b4f791a0dfc80804aafbfd55"}, + {file = "librt-0.15.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc1ed11c4ad0b91af24def2050f2840ea4567828e3dd058fbe608d982f6e5465"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1f4ef2e71db33df4309167ed7f1520c4fae5e611226e159fa9cf33f93e6ddb3d"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1a1a8cd430c7dd0c083f455cb1b328d7fc682b05c31b940906f7845bdff80881"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:04d5387b908676c0b8d5d2f5fb58373b4ea382d81f7a6f0fab8ea2a462bb4738"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:1172c6ad2a88b646e7fe3b480e3fac4ab4418b3443fd8a4061fdd531e0622fc7"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:52e8db01f603f5da0ca30987479acff98769382efc8e142fa3962395dcf3ffdb"}, + {file = "librt-0.15.0-cp39-cp39-win32.whl", hash = "sha256:e4c911f15a1652ca94ae9f1abd92e74cbb1b3597d2d92fdd556202f94e8cd455"}, + {file = "librt-0.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:68242379c9b65a582b6e97318a1e9fbd6d445e58954f2d437991c4804ab11578"}, + {file = "librt-0.15.0.tar.gz", hash = "sha256:4e66cbe84437497d951b799d3e1551291b6fb3d643820a7014b3655d57a59162"}, ] [[package]] @@ -2887,61 +2988,69 @@ dill = ">=0.4.1" [[package]] name = "mypy" -version = "2.1.0" +version = "2.3.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mypy-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:11a6beb180257a805961aea9ec591bbd0bd17f1e18d35b8456d57aee5bedfedc"}, - {file = "mypy-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ef78c1d306bbf9a8a12f526c44902c9c28dffd6c52c52bf6a72641ce18d3849"}, - {file = "mypy-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c209a90853081ff01d01ee895cafe10f7db1474e0d95beaeef0f6c1db9119bbd"}, - {file = "mypy-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47cebf61abde7c088a4e27718a8b13a81655686b2e9c251f5c0915a802248166"}, - {file = "mypy-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d57a90ae5e872138a425ec328edbc9b235d1934c4377881a33ec05b341acc9a8"}, - {file = "mypy-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:aea7f7a8a55b459c34275fc468ada6ca7c173a5e43a68f5dbe588a563d8a06b8"}, - {file = "mypy-2.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c989640253f0d76843e9c6c1bbf4bd48c5e85ada61bde4beb37cb3eca035685e"}, - {file = "mypy-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a683016b16fe2f572dc04c72be7ee0504ac1605a265d0200f5cea695fb788f41"}, - {file = "mypy-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a293c534adb55271fef24a26da04b855540a8c13cc07bc5917b9fd2c394f2ca"}, - {file = "mypy-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7406f4d048e71e576f5356d317e5b0a9e666dfd966bd99f9d14ca06e1a341538"}, - {file = "mypy-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0210d626fc8b31ccc90233754c7bc90e1f43205e85d96387f7db1285b55c398"}, - {file = "mypy-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3712c20deed54e814eaaa825603bada8ea1c390670a397c95b98405347acc563"}, - {file = "mypy-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fcaa0e479066e31f7cceb6a3bea39cb22b2ff51a6b2f24f193d19179ba17c389"}, - {file = "mypy-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:0b1a5260c95aa443083f9ed3592662941951bca3d4ca224a5dc517c38b7cf666"}, - {file = "mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af"}, - {file = "mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6"}, - {file = "mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211"}, - {file = "mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b"}, - {file = "mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22"}, - {file = "mypy-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b"}, - {file = "mypy-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8"}, - {file = "mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5"}, - {file = "mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e"}, - {file = "mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e"}, - {file = "mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285"}, - {file = "mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5"}, - {file = "mypy-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65"}, - {file = "mypy-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d"}, - {file = "mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2"}, - {file = "mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f"}, - {file = "mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4"}, - {file = "mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef"}, - {file = "mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135"}, - {file = "mypy-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21"}, - {file = "mypy-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57"}, - {file = "mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e"}, - {file = "mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780"}, - {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd"}, - {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08"}, - {file = "mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081"}, - {file = "mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7"}, - {file = "mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6"}, - {file = "mypy-2.1.0-py3-none-any.whl", hash = "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289"}, - {file = "mypy-2.1.0.tar.gz", hash = "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633"}, + {file = "mypy-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:57a936373fc690c43a8cd7e7e12a35148e4ec5aa7698ad7fc0a9f918bdc5be41"}, + {file = "mypy-2.3.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d00d769056bde2f4e69c175071eba45cfb44fa1ed92bdfbfe64a93e0543b0cf0"}, + {file = "mypy-2.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2166b29228835e1f88ff411e96639e6ca3c7fdde84b62ec211f70f86b4051167"}, + {file = "mypy-2.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:83d36c2924df7426333abe7faf4724a7e1aab0d9fd41625e81b4683034b80c13"}, + {file = "mypy-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:f12fdb70459d0060dea40b29e52163a961b156106d68d57882a6a9f648983a53"}, + {file = "mypy-2.3.1-cp310-cp310-win_arm64.whl", hash = "sha256:e099200a1b1b1223a4951f0a90cbff1b8c91b250ba599dab1f7217a628144d90"}, + {file = "mypy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94f04929f1c44c35fb0061e912087edaf504acede963a4a7d00680bd089d8531"}, + {file = "mypy-2.3.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f5d716048611e85ca9eefb2e1baa5d73ede389b5820ded260ea27c757d667af8"}, + {file = "mypy-2.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b091a455111214cb5c9d54a57b9618e9a49f9fe2a42e4e1ac86e9d104ed96ce8"}, + {file = "mypy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:df12e20c9efd614738c71b390007ecd0181125afc4ccafca04d78a1d2eed2c01"}, + {file = "mypy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:52eaf3a155f35cf80b40220288c861eb45f14a2340c1f6cbfbdb0feff32879d1"}, + {file = "mypy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:9b4eacbee8a69836c06eff6d0dd4e134a07c2b047755b30c08625fe214f322c6"}, + {file = "mypy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a32bbbb940af990d3be0b8af321c7b6815bb1b3b48142fe7459b9cc5f58959ff"}, + {file = "mypy-2.3.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff715e45b2231a8e85de1d163d1b42791e4d7aab8f5145f85fee1b710b735aff"}, + {file = "mypy-2.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:858fc57d3d91fa728e33e7ad71def60fc6272694607b306cd3292db53ae39080"}, + {file = "mypy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:851833db876e7b650f93719c74b7879a08e338979c96054fdfc3bfd90a486355"}, + {file = "mypy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:4c5095a327483591c94e0c8d3ef9e50d4ab1369b541eae007c1f23bc2a41f6bb"}, + {file = "mypy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:bbfe022634a2a195406bd469e888d2eaf193b02ba7e607391cd7640374aaae3b"}, + {file = "mypy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:114dff494000f18bd10d5d95d84b8567b26da60279ecbe838131841df20e635d"}, + {file = "mypy-2.3.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8637731bb5eee3671eb2c3200827aa3564ed8a9309ecee4d1afe77e6d031bdb"}, + {file = "mypy-2.3.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c80fbc405ed8020f5ff3802dc18cf060197bcdd3fbdd6a26ef2fd34dfdd5226"}, + {file = "mypy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:84081f538ce27375045c02e3d7f81bd11d853400621ae245d87ce7b6c420ec74"}, + {file = "mypy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:e9144ac16fde007096f9563eb2041b4433c2d705c4218edeb79e7e9d01035ee6"}, + {file = "mypy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:77ad9529e67dca28e511f5cd5671436584ce91f6d3bac159a353158187b986ac"}, + {file = "mypy-2.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:192abaedf75da1bc0b1cef104927e70ec49c1ef0031cc4825c7ee10a438ed24d"}, + {file = "mypy-2.3.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf678dffd16efcda2c15cbd30e9ecc0081388e29ea23687a88e686ed92638dc3"}, + {file = "mypy-2.3.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e036f06b41630f4c8a1d48f9ac6aa26acc65f8be089973f5519da643318f03f"}, + {file = "mypy-2.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71af9c8a894e862b58e92abb08e53b05a384a1e5e5d6dc7cda59126211a53d82"}, + {file = "mypy-2.3.1-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:3c80cd23d85368bdd9f37d5231dfd97d35bcbf5bf41af96ef3a9b078ad1957f9"}, + {file = "mypy-2.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:4956f34d145e145562a0a0bf367f642bbc85c04ec2baf47ae015947c3169a85d"}, + {file = "mypy-2.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:cfb12e360242d23d91f5e978d94f58ea66acf5804c4fb6f2f794a20d4cb1b595"}, + {file = "mypy-2.3.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5f1c50bb05b64e2026b52867e8d21106f01313c744a2c4ecc34c90d12e8d6e2"}, + {file = "mypy-2.3.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:667196b352f4cf304ded4c10f90cfc179263a1acfb3cdcfa984bdfd340d498bc"}, + {file = "mypy-2.3.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b9c53e395c12cad2c6d4b67d5da7c6057638a132d85c08b73646b18f802a0045"}, + {file = "mypy-2.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:18162b128c3f9c703cd35f5537446900b0d21a2549aa7a95d21380d2ef643fb0"}, + {file = "mypy-2.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:30c0477d4aab7b7f39c8397dc877f2c96b9fe5588ec379f372c56eb63d599f63"}, + {file = "mypy-2.3.1-cp314-cp314t-win_arm64.whl", hash = "sha256:6941ab3619377bc3f32ca02876b07d27f216f5201604b664d3937ea0fdd23bb4"}, + {file = "mypy-2.3.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:6f041a6de52c9217ca125e78ba0a335cb7fd98a1c0580978e49ab2b126f70b57"}, + {file = "mypy-2.3.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5159ae60f5dbc3a498af5ba8365505808ac8031bc63f9e00304ad545d40bdd9b"}, + {file = "mypy-2.3.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47a8a7a0a7f6f6e63995c0ac36fa0c07b127413fdc81f0439b7f3dccafd33561"}, + {file = "mypy-2.3.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:2329c0501293d4e1f33bc15d04d6304d65a1cdda967ee93a05c1e681a3923133"}, + {file = "mypy-2.3.1-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:bb26deed807bdb0457cf3e3f1cd7c4a1cf9d66864eaf1b4a61e06805d4c6b1f9"}, + {file = "mypy-2.3.1-cp315-cp315-win_amd64.whl", hash = "sha256:375d7013876a8233b2d05be185bfa09f689696cd999ce8b1cfe6acac5c80e8a3"}, + {file = "mypy-2.3.1-cp315-cp315-win_arm64.whl", hash = "sha256:586b3612214cceabb3c0f588c97e7d1e535393f06a60e912e994f6b3ace97523"}, + {file = "mypy-2.3.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:ef0c6335cda9d807f8193d8ff6204a72bc909fa9882aacbca14f43cdb7188306"}, + {file = "mypy-2.3.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e598c8c66401d26b150872154a286e6d484cf2789c3bb28a7556806298423021"}, + {file = "mypy-2.3.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eda22fd4efa9dcd39331d1dede9b5b8b8a7fd69af07592e778433da98610d29e"}, + {file = "mypy-2.3.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:2a0ba2e57847849fb0d1fcdabb32786d223095ed8bc121dfe322bcdb3d9c46bc"}, + {file = "mypy-2.3.1-cp315-cp315t-win_amd64.whl", hash = "sha256:3f7e865dd51f235f60a2dbcd8728a1c095f5ca28f095d48a725b84cd935735c4"}, + {file = "mypy-2.3.1-cp315-cp315t-win_arm64.whl", hash = "sha256:8ad80807dc3ab8ea978b1b2b6e4a657194ace1d4ef03e0e731aff1abd517da29"}, + {file = "mypy-2.3.1-py3-none-any.whl", hash = "sha256:6ed5c7e3419083268e5c9258bd1c1ef91af44a9e89374dbcaf37b775716e72eb"}, + {file = "mypy-2.3.1.tar.gz", hash = "sha256:47c1b1207258513a9d93495f69c8be9de73916186f0e52703e8c461b7a623419"}, ] [package.dependencies] -ast-serialize = ">=0.3.0,<1.0.0" -librt = {version = ">=0.11.0", markers = "platform_python_implementation != \"PyPy\""} +ast-serialize = ">=0.6.0,<1.0.0" +librt = {version = ">=0.13.0", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" pathspec = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} @@ -3369,15 +3478,15 @@ files = [ ] [[package]] -name = "py-cpuinfo" -version = "9.0.0" +name = "py-cpuinfo2" +version = "10.1.1" description = "Get CPU info with pure Python" optional = false -python-versions = "*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690"}, - {file = "py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5"}, + {file = "py_cpuinfo2-10.1.1-py3-none-any.whl", hash = "sha256:adc53396bfb206e6498d078ec2ab407f85799ecd819584ac36a8f80a2d4d762d"}, + {file = "py_cpuinfo2-10.1.1.tar.gz", hash = "sha256:7861133863663f16e06eca63b12904ef100b5760415e92372dac0162799a4771"}, ] [[package]] @@ -3656,18 +3765,18 @@ testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-benchmark" -version = "5.2.3" +version = "5.3.0" description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pytest_benchmark-5.2.3-py3-none-any.whl", hash = "sha256:bc839726ad20e99aaa0d11a127445457b4219bdb9e80a1afc4b51da7f96b0803"}, - {file = "pytest_benchmark-5.2.3.tar.gz", hash = "sha256:deb7317998a23c650fd4ff76e1230066a76cb45dcece0aca5607143c619e7779"}, + {file = "pytest_benchmark-5.3.0-py3-none-any.whl", hash = "sha256:920ab1dfcffa718d49aa15ba144c7e357bda59216a0dc308016cc1c7236f719d"}, + {file = "pytest_benchmark-5.3.0.tar.gz", hash = "sha256:358444d4e89be901ee2b6404fb043ac3d7684002ad7f3563cc153fca6339c965"}, ] [package.dependencies] -py-cpuinfo = "*" +py-cpuinfo2 = ">=10.1" pytest = ">=8.1" [package.extras] @@ -3715,14 +3824,14 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "pytest-socket" -version = "0.8.0" +version = "0.8.1" description = "Pytest Plugin to disable socket calls during tests" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pytest_socket-0.8.0-py3-none-any.whl", hash = "sha256:81821ba59f07d7600fe2b551d8714f40b068bd46e8b6704c48664e9d60cdacb8"}, - {file = "pytest_socket-0.8.0.tar.gz", hash = "sha256:af9bb5f487da72be63573a6194cfac033b6c7a1c1561e150521105970f9e99f2"}, + {file = "pytest_socket-0.8.1-py3-none-any.whl", hash = "sha256:f9846bed1dcd96eed459e5e14795bbaf96715cf4e827891fe70773817ecb8ed4"}, + {file = "pytest_socket-0.8.1.tar.gz", hash = "sha256:2f57787914ad2e1308d09ce141b95c3e55741fbb4fb7b7556593a6b063e0c9c7"}, ] [package.dependencies] @@ -4297,30 +4406,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.19" +version = "0.16.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ruff-0.15.19-py3-none-linux_armv6l.whl", hash = "sha256:922d1eb283161564759bd49f507e91dc6112c15da8bd5b84ed714e086243cf86"}, - {file = "ruff-0.15.19-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4d190d8f62a0b94aba8f721116538a9ee29b1e74d26650846ba9b99f0ae21c40"}, - {file = "ruff-0.15.19-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5a2c86ba6870dd415a9d9eb8be94d7924ebec6a26ffc7958ec7ca29d4bff967d"}, - {file = "ruff-0.15.19-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b432bc087264aea70fd25ac198918b70bd9e2aa0db4297b0bb91bbfbbc63ce"}, - {file = "ruff-0.15.19-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8530a09d03b3a8c994f8b559a7dcdabc690bcd3f78ef276c38c83166798ebf56"}, - {file = "ruff-0.15.19-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87bf21fb3875fe69f0eacc825411657e2e85589cce633c35c0adf1113649c62b"}, - {file = "ruff-0.15.19-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9b229cb3ef56ecc2c1c8ebeca64b7a7740ccaef40a9eb097e78dde5a8560b83"}, - {file = "ruff-0.15.19-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c754515be7b76afe6e7e62df7776709571bcfc1631183828afcf3bafa869e3"}, - {file = "ruff-0.15.19-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a498f82e0f4d8904c4e0aea5139cdfac1f39d19a3c51d491292f63a36e83b2e"}, - {file = "ruff-0.15.19-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d48caa34488fb521fd0ef4aea2b0e8fe758298df044138f0d67b687a6a0d07ed"}, - {file = "ruff-0.15.19-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4171b6613effa9363cd46dd4f75bd1827b6d1b946b5e278ed0c600d305379445"}, - {file = "ruff-0.15.19-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:27c15b2a241dd4d995557949a094fe78b8ad99122a38ccae1595849bcc947b3f"}, - {file = "ruff-0.15.19-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ed03b7862d68f0a8771d50ee129980cbf1b113f96e250b73954bc292f689e0bb"}, - {file = "ruff-0.15.19-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:08143f0685ae278b30727ea72e90c61e5bd9c31b91aac4f5bb989538f73d24b8"}, - {file = "ruff-0.15.19-py3-none-win32.whl", hash = "sha256:8f47f0f92952af2557212bb10cf3e695cd4cf28b2c6e42cdb18ec6c9ebfa19da"}, - {file = "ruff-0.15.19-py3-none-win_amd64.whl", hash = "sha256:efeca47ee3f9d4a7162655a3b8e6ee4a878646044233978d4d2c1ff8cdd914f0"}, - {file = "ruff-0.15.19-py3-none-win_arm64.whl", hash = "sha256:6c6b607466e47349332eb1d9be52fb1467423fc07c217341af41cd0f3f0573be"}, - {file = "ruff-0.15.19.tar.gz", hash = "sha256:edc27f7172a93b32b102687009d6a588508815072141543ae603a8b9b0823063"}, + {file = "ruff-0.16.4-py3-none-linux_armv6l.whl", hash = "sha256:df4075f71ddac40b9934af60c3ec8a53047dd5a5fdc43224e6e4e8e9a27cb6f7"}, + {file = "ruff-0.16.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0c95538517af68004306b0fb3214ff2f2af67a65092aee77cd9eb86db6656604"}, + {file = "ruff-0.16.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:963f83df8e69e575b64d67dd447ebbc917db41a14bf38d4593a4183e7aaa8255"}, + {file = "ruff-0.16.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32a5057c7ff3f6e6480a48fccfb3a412a690f48a3d03ac5cf08177d6c2da3ade"}, + {file = "ruff-0.16.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b3dce8d9b0c57c265b91885a66a567d8ea1372e8eb4e250fa8e5e3f579e99cff"}, + {file = "ruff-0.16.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7dc651db49283c69f8e72c834eec4fe5573e4c646856aebece0ce385dceb2a80"}, + {file = "ruff-0.16.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3817b87dbcabc92f13b05019257c5b89b5b4d51b5fb20f56fb5235ceb723cd07"}, + {file = "ruff-0.16.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9fce1499134b2c8c68e5166f95705a5812062bb93aacc5f9873bb1a27084bc7"}, + {file = "ruff-0.16.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2d812e482f5a7e02eee26cd73d2a37ebbdf47d795ea63ba1b89110ae93e9fb3"}, + {file = "ruff-0.16.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:6baaf984aa7976edf93d3b627fe2d1d22ee94bbca05fa6f90fc76d73924e3454"}, + {file = "ruff-0.16.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:bdfcf0b28662eb890372d50f92c283bb94e67e7635ed93c7fd533970acff7b2b"}, + {file = "ruff-0.16.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b66b02cb9b04f537643cadf5768e5f98dc461890d530cb67113d71c8c76e605d"}, + {file = "ruff-0.16.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8528bf9a4b291a60bf02ea453511e8ce6215bd2b982ee80405b66b008b6c30a0"}, + {file = "ruff-0.16.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fbd85d2875fdd67e833213a651f613bbf25303abf6aa822a5121f4531195678d"}, + {file = "ruff-0.16.4-py3-none-win32.whl", hash = "sha256:312769988007aaeb8e189b443ccdd03c0e6374489e053467be6d96518ebff76e"}, + {file = "ruff-0.16.4-py3-none-win_amd64.whl", hash = "sha256:05d9d27a18c4bcbefada602480ec9e01e0bc949d432e0ced5df77edac195919c"}, + {file = "ruff-0.16.4-py3-none-win_arm64.whl", hash = "sha256:a3a61621c9b6f6a89573e938a080e648f1695baa3f58570a3a707bc51ff65a21"}, + {file = "ruff-0.16.4.tar.gz", hash = "sha256:13171aa9d9af2240ee3504e639de73122c67e74036de5ba2e1d01422cd17e3dc"}, ] [[package]] @@ -5224,4 +5333,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "08e37143f0927393aa997ebc6fe2a3324415f29d9086f6ba4f8d3a0815db7e42" +content-hash = "368940a68ae8b3bbb72ab67bbb91e4da4170e07a7faf28011343cfcb809ce84a" diff --git a/pyproject.toml b/pyproject.toml index 31ca7daccbe..0510319e5f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -116,7 +116,7 @@ types-python-dateutil = "^2.8.19.6" aws-cdk-aws-appsync-alpha = "^2.59.0a0" httpx = ">=0.23.3,<0.29.0" sentry-sdk = ">=1.22.2,<3.0.0" -ruff = ">=0.5.1,<0.15.20" +ruff = ">=0.5.1,<0.16.5" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.9" types-redis = "^4.6.0.7" diff --git a/ruff.toml b/ruff.toml index 6761e206cdc..304f77c680d 100644 --- a/ruff.toml +++ b/ruff.toml @@ -33,6 +33,7 @@ lint.select = [ lint.ignore = [ "W291", # https://beta.ruff.rs/docs/rules/trailing-whitespace/ "PLR0913", # https://beta.ruff.rs/docs/rules/too-many-arguments/ + "PLR0917", # https://docs.astral.sh/ruff/rules/too-many-positional-arguments/ "PLR2004", #https://beta.ruff.rs/docs/rules/magic-value-comparison/ "PLW0603", #https://beta.ruff.rs/docs/rules/global-statement/ "B904", # raise-without-from-inside-except - disabled temporarily From a8df37d3e08c2668c104ebd5bdda2c11336adddb Mon Sep 17 00:00:00 2001 From: Aditya Jain <93090622+Adityaj0@users.noreply.github.com> Date: Fri, 28 Aug 2026 09:58:23 -0700 Subject: [PATCH 74/76] fix(idempotency): is_missing_idempotency_key iterates dict keys instead of values (#8391) * fix(idempotency): is_missing_idempotency_key iterates dict keys instead of values is_missing_idempotency_key iterated `data` directly for dict input, which walks its keys, not its values. For a dict whose values are all None but whose keys are ordinary non-None strings -- exactly what a JMESPath multi-select expression like '{user: headers.user_id, order: body.order_id}' produces when the referenced event fields are absent -- this returns False ("not missing") when it should return True. With raise_on_no_idempotency_key=True, the safety check that's supposed to raise IdempotencyKeyError in this situation silently doesn't fire. With the default False, no warning is emitted and the persistence layer hashes the all-None dict into a real idempotency key, so unrelated invocations that both fail to populate those fields collapse onto the same idempotency key and get incorrectly deduplicated against each other. The existing test only covered a dict of {None: None} (None as the key), which happens to still pass under the old key-iterating behavior and so never caught this. Iterate data.values() for dict input instead, and add a test covering the realistic non-None-keys/all-None-values case. * test(idempotency): cover missing dictionary keys --------- Co-authored-by: Leandro --- .../utilities/idempotency/persistence/base.py | 5 ++++- .../idempotency/_boto3/test_idempotency.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/base.py b/aws_lambda_powertools/utilities/idempotency/persistence/base.py index 3d54a01f018..2271520139d 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/base.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/base.py @@ -131,7 +131,10 @@ def _get_hashed_idempotency_key(self, data: dict[str, Any]) -> str | None: @staticmethod def is_missing_idempotency_key(data) -> bool: - if isinstance(data, (tuple, list, dict)): + if isinstance(data, dict): + # JMESPath multi-select dicts retain their keys when all selected values are missing. + return all(x is None for x in data.values()) + elif isinstance(data, (tuple, list)): return all(x is None for x in data) elif isinstance(data, (int, float, bool)): return False diff --git a/tests/functional/idempotency/_boto3/test_idempotency.py b/tests/functional/idempotency/_boto3/test_idempotency.py index e5916dba0fa..a4a55dd947a 100644 --- a/tests/functional/idempotency/_boto3/test_idempotency.py +++ b/tests/functional/idempotency/_boto3/test_idempotency.py @@ -1046,6 +1046,10 @@ def test_is_missing_idempotency_key(): assert BasePersistenceLayer.is_missing_idempotency_key((None, None)) # GIVEN a dict of Nones THEN is_missing_idempotency_key is True assert BasePersistenceLayer.is_missing_idempotency_key({None: None}) + # GIVEN a dict with all-None values THEN is_missing_idempotency_key is True + assert BasePersistenceLayer.is_missing_idempotency_key({"user": None, "order": None}) + # GIVEN a dict with a non-None value THEN is_missing_idempotency_key is False + assert BasePersistenceLayer.is_missing_idempotency_key({"user": "abc"}) is False # GIVEN True THEN is_missing_idempotency_key is False assert BasePersistenceLayer.is_missing_idempotency_key(True) is False @@ -1114,6 +1118,19 @@ def test_raise_on_no_idempotency_key( assert "No data found to create a hashed idempotency_key" in str(excinfo.value) +def test_raise_on_no_idempotency_key_for_dict_jmespath(persistence_store: DynamoDBPersistenceLayer): + # GIVEN a dict multi-select expression whose values are missing + idempotency_config = IdempotencyConfig( + event_key_jmespath="{user: headers.user_id, order: body.order_id}", + raise_on_no_idempotency_key=True, + ) + persistence_store.configure(idempotency_config) + + # WHEN extracting the idempotency key THEN raise IdempotencyKeyError + with pytest.raises(IdempotencyKeyError, match="No data found to create a hashed idempotency_key"): + persistence_store._get_hashed_idempotency_key({"headers": {}, "body": {}}) + + @pytest.mark.parametrize( "idempotency_config", [ From 78fdd32b5a0f5c5b7576998aa38a850a65a54f6f Mon Sep 17 00:00:00 2001 From: OctaviO Date: Sat, 29 Aug 2026 00:08:29 +0500 Subject: [PATCH 75/76] refactor(typing): use PEP 604 syntax for Optional annotations (UP045) (#8399) * refactor(typing): use PEP 604 syntax for Optional annotations (UP045) Convert Optional[X] to X | None across the codebase and remove the temporary UP045 ignore from ruff.toml, so the fix and the removal of the ignore land together. 283 of the 285 violations were handled by the ruff autofix. The two remaining cases in utilities/batch/types.py are runtime assignments rather than annotations, so they were converted by hand and verified to compare equal to their previous definitions. Union is left in place, since it belongs to UP007. * fix(typing): use Any instead of the builtin any in e2e data fetcher annotations Optional[any] was tolerated because typing never validated its argument, so the lowercase any went unnoticed. Once converted to any | None the expression is evaluated at import time, and neither module has the future annotations import, so importing them raised TypeError. Also updates the matching docstring line in logs.py. These modules are never imported by the test suite, since make test runs with --ignore tests/e2e, which is why this was not caught locally. --------- Co-authored-by: Leandro Damascena --- .../utilities/batch/exceptions.py | 4 +- .../utilities/batch/types.py | 9 +- .../utilities/parser/models/apigw.py | 72 ++++++++-------- .../parser/models/apigw_websocket.py | 6 +- .../utilities/parser/models/apigwv2.py | 40 ++++----- .../utilities/parser/models/appsync.py | 20 ++--- .../utilities/parser/models/appsync_events.py | 12 +-- .../utilities/parser/models/bedrock_agent.py | 8 +- .../utilities/parser/models/cloudwatch.py | 4 +- .../utilities/parser/models/cognito.py | 84 +++++++++---------- .../utilities/parser/models/dynamodb.py | 12 +-- .../utilities/parser/models/event_bridge.py | 4 +- .../parser/models/iot_registry_events.py | 12 +-- .../utilities/parser/models/kafka.py | 8 +- .../parser/models/kinesis_firehose.py | 6 +- .../parser/models/kinesis_firehose_sqs.py | 6 +- .../utilities/parser/models/s3.py | 38 ++++----- .../parser/models/s3_batch_operation.py | 10 +-- .../parser/models/s3_object_event.py | 8 +- .../utilities/parser/models/ses.py | 10 +-- .../utilities/parser/models/sns.py | 12 +-- .../utilities/parser/models/sqs.py | 18 ++-- .../parser/models/transfer_family.py | 4 +- .../utilities/parser/models/vpc_latticev2.py | 28 +++---- .../src/advanced_accessing_lambda_context.py | 4 +- ...vanced_accessing_lambda_context_manager.py | 4 +- .../batch_processing/src/pydantic_dynamodb.py | 6 +- examples/build_recipes/poetry/app_poetry.py | 4 +- .../sam/no-layers/src/app_sam_no_layer.py | 4 +- .../sam/with-layers/src/app/app_sam_layer.py | 4 +- .../src/enable_exceptions_batch_resolver.py | 4 +- .../src/accessing_request_details.py | 6 +- .../src/customizing_response_validation.py | 3 +- ...stomizing_response_validation_exception.py | 3 +- .../event_handler_rest/src/data_validation.py | 4 +- .../data_validation_fine_grained_response.py | 3 +- .../src/data_validation_sanitized_error.py | 4 +- .../src/skip_validating_query_strings.py | 6 +- .../src/validating_headers.py | 4 +- .../src/validating_headers_with_pydantic.py | 4 +- .../event_handler_rest/src/validating_path.py | 4 +- .../src/validating_payload_subset.py | 4 +- .../src/validating_payloads.py | 4 +- .../validating_query_string_with_pydantic.py | 4 +- .../src/validating_query_strings.py | 6 +- .../src/bring_your_own_persistent_store.py | 6 +- .../bring_your_own_formatter_from_scratch.py | 4 +- .../src/assert_transformation_module.py | 4 +- examples/streaming/src/s3_json_transform.py | 6 +- ruff.toml | 1 - tests/e2e/utils/data_fetcher/common.py | 14 ++-- tests/e2e/utils/data_fetcher/logs.py | 34 ++++---- tests/e2e/utils/data_fetcher/traces.py | 56 ++++++------- .../batch/_pydantic/sample_models.py | 6 +- .../test_utilities_batch_pydantic.py | 10 +-- .../_pydantic/test_bedrock_agent.py | 6 +- .../_pydantic/test_openapi_params.py | 10 +-- .../_pydantic/test_openapi_responses.py | 4 +- .../test_openapi_schema_pydantic_v2.py | 4 +- .../_pydantic/test_openapi_serialization.py | 4 +- .../test_openapi_validation_middleware.py | 34 ++++---- .../idempotency/_boto3/test_idempotency.py | 4 +- .../test_idempotency_with_pydantic.py | 4 +- tests/functional/idempotency/utils.py | 4 +- tests/unit/parser/_pydantic/schemas.py | 6 +- 65 files changed, 361 insertions(+), 384 deletions(-) diff --git a/aws_lambda_powertools/utilities/batch/exceptions.py b/aws_lambda_powertools/utilities/batch/exceptions.py index 87a2df22d6d..247388a9886 100644 --- a/aws_lambda_powertools/utilities/batch/exceptions.py +++ b/aws_lambda_powertools/utilities/batch/exceptions.py @@ -6,9 +6,9 @@ import traceback from types import TracebackType -from typing import Optional, Tuple, Type +from typing import Tuple, Type -ExceptionInfo = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +ExceptionInfo = Tuple[Type[BaseException] | None, BaseException | None, TracebackType | None] class BaseBatchProcessingError(Exception): diff --git a/aws_lambda_powertools/utilities/batch/types.py b/aws_lambda_powertools/utilities/batch/types.py index ec543bf51ea..32e11b5ae07 100644 --- a/aws_lambda_powertools/utilities/batch/types.py +++ b/aws_lambda_powertools/utilities/batch/types.py @@ -1,7 +1,7 @@ from __future__ import annotations import sys -from typing import Optional, Type, TypedDict, Union +from typing import Type, TypedDict, Union has_pydantic = "pydantic" in sys.modules @@ -14,15 +14,16 @@ ) from aws_lambda_powertools.utilities.parser.models.kafka import KafkaRecordModel - BatchTypeModels = Optional[ + BatchTypeModels = ( Union[ Type[SqsRecordModel], Type[DynamoDBStreamRecordModel], Type[KinesisDataStreamRecordModel], Type[KafkaRecordModel], ] - ] - BatchSqsTypeModel = Optional[Type[SqsRecordModel]] + | None + ) + BatchSqsTypeModel = Type[SqsRecordModel] | None else: # pragma: no cover BatchTypeModels = "BatchTypeModels" # type: ignore BatchSqsTypeModel = "BatchSqsTypeModel" # type: ignore diff --git a/aws_lambda_powertools/utilities/parser/models/apigw.py b/aws_lambda_powertools/utilities/parser/models/apigw.py index ea01a5e8a6b..349ebbb512b 100644 --- a/aws_lambda_powertools/utilities/parser/models/apigw.py +++ b/aws_lambda_powertools/utilities/parser/models/apigw.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, List, Literal, Optional, Type, Union +from typing import Any, Dict, List, Literal, Type, Union from pydantic import BaseModel, field_validator, model_validator from pydantic.networks import IPvAnyNetwork @@ -21,23 +21,23 @@ class ApiGatewayUserCert(BaseModel): class APIGatewayEventIdentity(BaseModel): - accessKey: Optional[str] = None - accountId: Optional[str] = None - apiKey: Optional[str] = None - apiKeyId: Optional[str] = None - caller: Optional[str] = None - cognitoAuthenticationProvider: Optional[str] = None - cognitoAuthenticationType: Optional[str] = None - cognitoIdentityId: Optional[str] = None - cognitoIdentityPoolId: Optional[str] = None - principalOrgId: Optional[str] = None + accessKey: str | None = None + accountId: str | None = None + apiKey: str | None = None + apiKeyId: str | None = None + caller: str | None = None + cognitoAuthenticationProvider: str | None = None + cognitoAuthenticationType: str | None = None + cognitoIdentityId: str | None = None + cognitoIdentityPoolId: str | None = None + principalOrgId: str | None = None # see #1562, temp workaround until API Gateway fixes it the Test button payload # removing it will not be considered a regression in the future sourceIp: Union[IPvAnyNetwork, str] - user: Optional[str] = None - userAgent: Optional[str] = None - userArn: Optional[str] = None - clientCert: Optional[ApiGatewayUserCert] = None + user: str | None = None + userAgent: str | None = None + userArn: str | None = None + clientCert: ApiGatewayUserCert | None = None @field_validator("sourceIp", mode="before") @classmethod @@ -46,34 +46,34 @@ def _validate_source_ip(cls, value): class APIGatewayEventAuthorizer(BaseModel): - claims: Optional[Dict[str, Any]] = None - scopes: Optional[List[str]] = None + claims: Dict[str, Any] | None = None + scopes: List[str] | None = None class APIGatewayEventRequestContext(BaseModel): accountId: str apiId: str - authorizer: Optional[APIGatewayEventAuthorizer] = None + authorizer: APIGatewayEventAuthorizer | None = None stage: str protocol: str identity: APIGatewayEventIdentity requestId: str requestTime: str requestTimeEpoch: datetime - resourceId: Optional[str] = None + resourceId: str | None = None resourcePath: str - domainName: Optional[str] = None - domainPrefix: Optional[str] = None - extendedRequestId: Optional[str] = None + domainName: str | None = None + domainPrefix: str | None = None + extendedRequestId: str | None = None httpMethod: Literal["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] path: str - connectedAt: Optional[datetime] = None - connectionId: Optional[str] = None - eventType: Optional[Literal["CONNECT", "MESSAGE", "DISCONNECT"]] = None - messageDirection: Optional[str] = None - messageId: Optional[str] = None - routeKey: Optional[str] = None - operationName: Optional[str] = None + connectedAt: datetime | None = None + connectionId: str | None = None + eventType: Literal["CONNECT", "MESSAGE", "DISCONNECT"] | None = None + messageDirection: str | None = None + messageId: str | None = None + routeKey: str | None = None + operationName: str | None = None @model_validator(mode="before") def check_message_id(cls, values): @@ -84,19 +84,19 @@ def check_message_id(cls, values): class APIGatewayProxyEventModel(BaseModel): - version: Optional[str] = None + version: str | None = None resource: str path: str httpMethod: Literal["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] headers: Dict[str, str] multiValueHeaders: Dict[str, List[str]] - queryStringParameters: Optional[Dict[str, str]] = None - multiValueQueryStringParameters: Optional[Dict[str, List[str]]] = None + queryStringParameters: Dict[str, str] | None = None + multiValueQueryStringParameters: Dict[str, List[str]] | None = None requestContext: APIGatewayEventRequestContext - pathParameters: Optional[Dict[str, str]] = None - stageVariables: Optional[Dict[str, str]] = None - isBase64Encoded: Optional[bool] = None - body: Optional[Union[str, Type[BaseModel]]] = None + pathParameters: Dict[str, str] | None = None + stageVariables: Dict[str, str] | None = None + isBase64Encoded: bool | None = None + body: Union[str, Type[BaseModel]] | None = None class ApiGatewayAuthorizerToken(BaseModel): diff --git a/aws_lambda_powertools/utilities/parser/models/apigw_websocket.py b/aws_lambda_powertools/utilities/parser/models/apigw_websocket.py index b9e7ecd68c7..3454d7d30a0 100644 --- a/aws_lambda_powertools/utilities/parser/models/apigw_websocket.py +++ b/aws_lambda_powertools/utilities/parser/models/apigw_websocket.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Dict, List, Literal, Optional, Type, Union +from typing import Dict, List, Literal, Type, Union from pydantic import BaseModel, Field from pydantic.networks import IPvAnyNetwork @@ -7,7 +7,7 @@ class APIGatewayWebSocketEventIdentity(BaseModel): source_ip: IPvAnyNetwork = Field(alias="sourceIp") - user_agent: Optional[str] = Field(None, alias="userAgent") + user_agent: str | None = Field(None, alias="userAgent") class APIGatewayWebSocketEventRequestContextBase(BaseModel): @@ -61,4 +61,4 @@ class APIGatewayWebSocketDisconnectEventModel(BaseModel): class APIGatewayWebSocketMessageEventModel(BaseModel): request_context: APIGatewayWebSocketMessageEventRequestContext = Field(alias="requestContext") is_base64_encoded: bool = Field(alias="isBase64Encoded") - body: Optional[Union[str, Type[BaseModel]]] = Field(None, alias="body") + body: Union[str, Type[BaseModel]] | None = Field(None, alias="body") diff --git a/aws_lambda_powertools/utilities/parser/models/apigwv2.py b/aws_lambda_powertools/utilities/parser/models/apigwv2.py index 9bd66b7a585..b01cb1beb03 100644 --- a/aws_lambda_powertools/utilities/parser/models/apigwv2.py +++ b/aws_lambda_powertools/utilities/parser/models/apigwv2.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, List, Literal, Optional, Type, Union +from typing import Any, Dict, List, Literal, Type, Union from pydantic import BaseModel, Field, field_validator from pydantic.networks import IPvAnyNetwork @@ -14,24 +14,24 @@ class RequestContextV2AuthorizerIamCognito(BaseModel): class RequestContextV2AuthorizerIam(BaseModel): - accessKey: Optional[str] = None - accountId: Optional[str] = None - callerId: Optional[str] = None - principalOrgId: Optional[str] = None - userArn: Optional[str] = None - userId: Optional[str] = None - cognitoIdentity: Optional[RequestContextV2AuthorizerIamCognito] = None + accessKey: str | None = None + accountId: str | None = None + callerId: str | None = None + principalOrgId: str | None = None + userArn: str | None = None + userId: str | None = None + cognitoIdentity: RequestContextV2AuthorizerIamCognito | None = None class RequestContextV2AuthorizerJwt(BaseModel): claims: Dict[str, Any] - scopes: Optional[List[str]] = None + scopes: List[str] | None = None class RequestContextV2Authorizer(BaseModel): - jwt: Optional[RequestContextV2AuthorizerJwt] = None - iam: Optional[RequestContextV2AuthorizerIam] = None - lambda_value: Optional[Dict[str, Any]] = Field(None, alias="lambda") + jwt: RequestContextV2AuthorizerJwt | None = None + iam: RequestContextV2AuthorizerIam | None = None + lambda_value: Dict[str, Any] | None = Field(None, alias="lambda") class RequestContextV2Http(BaseModel): @@ -50,7 +50,7 @@ def _validate_source_ip(cls, value): class RequestContextV2(BaseModel): accountId: str apiId: str - authorizer: Optional[RequestContextV2Authorizer] = None + authorizer: RequestContextV2Authorizer | None = None domainName: str domainPrefix: str requestId: str @@ -66,17 +66,17 @@ class APIGatewayProxyEventV2Model(BaseModel): routeKey: str rawPath: str rawQueryString: str - cookies: Optional[List[str]] = None + cookies: List[str] | None = None headers: Dict[str, str] - queryStringParameters: Optional[Dict[str, str]] = None - pathParameters: Optional[Dict[str, str]] = None - stageVariables: Optional[Dict[str, str]] = None + queryStringParameters: Dict[str, str] | None = None + pathParameters: Dict[str, str] | None = None + stageVariables: Dict[str, str] | None = None requestContext: RequestContextV2 - body: Optional[Union[str, Type[BaseModel]]] = None - isBase64Encoded: Optional[bool] = None + body: Union[str, Type[BaseModel]] | None = None + isBase64Encoded: bool | None = None class ApiGatewayAuthorizerRequestV2(APIGatewayProxyEventV2Model): type: Literal["REQUEST"] routeArn: str - identitySource: Optional[List[str]] = None + identitySource: List[str] | None = None diff --git a/aws_lambda_powertools/utilities/parser/models/appsync.py b/aws_lambda_powertools/utilities/parser/models/appsync.py index 6d6deedcdcc..e9fe251d38f 100644 --- a/aws_lambda_powertools/utilities/parser/models/appsync.py +++ b/aws_lambda_powertools/utilities/parser/models/appsync.py @@ -1,16 +1,16 @@ -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Union from pydantic import BaseModel, Field class AppSyncIamIdentity(BaseModel): accountId: str = Field(description="The AWS account ID of the caller.", examples=["123456789012"]) - cognitoIdentityPoolId: Optional[str] = Field( + cognitoIdentityPoolId: str | None = Field( default=None, description="The Amazon Cognito identity pool ID associated with the caller.", examples=["us-east-1:12345678-1234-1234-1234-123456789012"], ) - cognitoIdentityId: Optional[str] = Field( + cognitoIdentityId: str | None = Field( default=None, description="The Amazon Cognito identity ID of the caller.", examples=["us-east-1:12345678-1234-1234-1234-123456789012"], @@ -29,12 +29,12 @@ class AppSyncIamIdentity(BaseModel): description="The Amazon Resource Name (ARN) of the IAM user.", examples=["arn:aws:iam::123456789012:user/appsync", "arn:aws:iam::123456789012:user/service-user"], ) - cognitoIdentityAuthType: Optional[str] = Field( + cognitoIdentityAuthType: str | None = Field( default=None, description="Either authenticated or unauthenticated based on the identity type.", examples=["authenticated", "unauthenticated"], ) - cognitoIdentityAuthProvider: Optional[str] = Field( + cognitoIdentityAuthProvider: str | None = Field( default=None, description=( "A comma-separated list of external identity provider information " @@ -74,7 +74,7 @@ class AppSyncCognitoIdentity(BaseModel): description="The default authorization strategy for this caller (ALLOW or DENY).", examples=["ALLOW", "DENY"], ) - groups: Optional[List[str]] = Field( + groups: List[str] | None = Field( default=None, description="The Cognito User Pool groups that the user belongs to.", examples=[["admin", "users"], ["developers"]], @@ -115,7 +115,7 @@ class AppSyncLambdaIdentity(BaseModel): class AppSyncRequestModel(BaseModel): - domainName: Optional[str] = Field( + domainName: str | None = Field( default=None, description=( "The custom domain name used to access the GraphQL endpoint. " @@ -190,11 +190,11 @@ class AppSyncResolverEventModel(BaseModel): {"page": 2, "size": 1, "name": "value"}, ], ) - identity: Optional[AppSyncIdentity] = Field( + identity: AppSyncIdentity | None = Field( default=None, description="Information about the caller identity (authenticated user or API key).", ) - source: Optional[Dict[str, Any]] = Field( + source: Dict[str, Any] | None = Field( default=None, description="The parent object for the field. For top-level fields, this will be null.", examples=[ @@ -208,7 +208,7 @@ class AppSyncResolverEventModel(BaseModel): info: AppSyncInfoModel = Field( description="Information about the GraphQL request including selection set and field details.", ) - prev: Optional[AppSyncPrevModel] = Field( + prev: AppSyncPrevModel | None = Field( default=None, description="Results from the previous resolver in a pipeline resolver.", ) diff --git a/aws_lambda_powertools/utilities/parser/models/appsync_events.py b/aws_lambda_powertools/utilities/parser/models/appsync_events.py index ceeb3ae621a..a1168d5dd3f 100644 --- a/aws_lambda_powertools/utilities/parser/models/appsync_events.py +++ b/aws_lambda_powertools/utilities/parser/models/appsync_events.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Dict, List, Literal from pydantic import BaseModel, Field @@ -51,7 +51,7 @@ class AppSyncEventsEventModel(BaseModel): class AppSyncEventsModel(BaseModel): - identity: Optional[AppSyncIdentity] = Field( + identity: AppSyncIdentity | None = Field( default=None, description="Information about the caller identity (authenticated user or API key).", ) @@ -59,17 +59,17 @@ class AppSyncEventsModel(BaseModel): info: AppSyncEventsInfoModel = Field( description="Information about the AppSync Events operation including channel details.", ) - prev: Optional[str] = Field( + prev: str | None = Field( default=None, description="Results from the previous operation in a pipeline resolver.", examples=["previous-result-data"], ) - outErrors: Optional[List[str]] = Field( + outErrors: List[str] | None = Field( default=None, description="List of output errors that occurred during event processing.", examples=[["Error message 1", "Error message 2"]], ) - stash: Optional[Dict[str, Any]] = Field( + stash: Dict[str, Any] | None = Field( default=None, description=( "The stash is a map that is made available inside each resolver and function mapping template. " @@ -77,7 +77,7 @@ class AppSyncEventsModel(BaseModel): ), examples=[{"customData": "value", "userId": "123"}], ) - events: Optional[List[AppSyncEventsEventModel]] = Field( + events: List[AppSyncEventsEventModel] | None = Field( default=None, description="List of events being published or subscribed to in the AppSync Events operation.", examples=[ diff --git a/aws_lambda_powertools/utilities/parser/models/bedrock_agent.py b/aws_lambda_powertools/utilities/parser/models/bedrock_agent.py index 1aa5ae07a34..c06cfd457b6 100644 --- a/aws_lambda_powertools/utilities/parser/models/bedrock_agent.py +++ b/aws_lambda_powertools/utilities/parser/models/bedrock_agent.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Optional +from typing import Dict, List from pydantic import BaseModel, Field @@ -34,8 +34,8 @@ class BedrockAgentEventModel(BaseModel): session_attributes: Dict[str, str] = Field({}, alias="sessionAttributes") prompt_session_attributes: Dict[str, str] = Field({}, alias="promptSessionAttributes") agent: BedrockAgentModel - parameters: Optional[List[BedrockAgentPropertyModel]] = None - request_body: Optional[BedrockAgentRequestBodyModel] = Field(None, alias="requestBody") + parameters: List[BedrockAgentPropertyModel] | None = None + request_body: BedrockAgentRequestBodyModel | None = Field(None, alias="requestBody") class BedrockAgentFunctionEventModel(BaseModel): @@ -51,6 +51,6 @@ class BedrockAgentFunctionEventModel(BaseModel): session_id: str = Field(..., alias="sessionId") action_group: str = Field(..., alias="actionGroup") function: str - parameters: Optional[List[BedrockAgentPropertyModel]] = None + parameters: List[BedrockAgentPropertyModel] | None = None session_attributes: Dict[str, str] = Field({}, alias="sessionAttributes") prompt_session_attributes: Dict[str, str] = Field({}, alias="promptSessionAttributes") diff --git a/aws_lambda_powertools/utilities/parser/models/cloudwatch.py b/aws_lambda_powertools/utilities/parser/models/cloudwatch.py index 6c3d25e1727..0fdc7562962 100644 --- a/aws_lambda_powertools/utilities/parser/models/cloudwatch.py +++ b/aws_lambda_powertools/utilities/parser/models/cloudwatch.py @@ -3,7 +3,7 @@ import logging import zlib from datetime import datetime -from typing import List, Optional, Type, Union +from typing import List, Type, Union from pydantic import BaseModel, Field, field_validator @@ -47,7 +47,7 @@ class CloudWatchLogsDecode(BaseModel): description="Array of log events included in the message.", examples=[[{"id": "eventId1", "timestamp": 1673779200000, "message": "Sample log line"}]], ) - policyLevel: Optional[str] = Field( + policyLevel: str | None = Field( default=None, description="Optional field specifying the policy level applied to the subscription filter, if present.", examples=["ACCOUNT", "LOG_GROUP"], diff --git a/aws_lambda_powertools/utilities/parser/models/cognito.py b/aws_lambda_powertools/utilities/parser/models/cognito.py index 05726e37db4..75a21254324 100644 --- a/aws_lambda_powertools/utilities/parser/models/cognito.py +++ b/aws_lambda_powertools/utilities/parser/models/cognito.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Dict, List, Literal from pydantic import BaseModel @@ -14,22 +14,22 @@ class CognitoTriggerBaseSchema(BaseModel): version: str region: str userPoolId: str - userName: Optional[str] = None + userName: str | None = None callerContext: CognitoCallerContextModel # Models for Pre-Signup flow class CognitoPreSignupRequestModel(BaseModel): userAttributes: Dict[str, Any] - validationData: Optional[Dict[str, Any]] = None - clientMetadata: Optional[Dict[str, Any]] = None - userNotFound: Optional[bool] = None + validationData: Dict[str, Any] | None = None + clientMetadata: Dict[str, Any] | None = None + userNotFound: bool | None = None class CognitoPreSignupResponseModel(BaseModel): - autoConfirmUser: Optional[bool] = False - autoVerifyPhone: Optional[bool] = False - autoVerifyEmail: Optional[bool] = False + autoConfirmUser: bool | None = False + autoVerifyPhone: bool | None = False + autoVerifyEmail: bool | None = False class CognitoPreSignupTriggerModel(CognitoTriggerBaseSchema): @@ -41,7 +41,7 @@ class CognitoPreSignupTriggerModel(CognitoTriggerBaseSchema): # Models for Post-Confirmation flow class CognitoPostConfirmationRequestModel(BaseModel): userAttributes: Dict[str, Any] - clientMetadata: Optional[Dict[str, Any]] = None + clientMetadata: Dict[str, Any] | None = None class CognitoPostConfirmationTriggerModel(CognitoTriggerBaseSchema): @@ -53,8 +53,8 @@ class CognitoPostConfirmationTriggerModel(CognitoTriggerBaseSchema): # Models for Pre-Authentication flow class CognitoPreAuthenticationRequestModel(BaseModel): userAttributes: Dict[str, Any] - validationData: Optional[Dict[str, Any]] = None - userNotFound: Optional[bool] = None + validationData: Dict[str, Any] | None = None + userNotFound: bool | None = None class CognitoPreAuthenticationTriggerModel(CognitoTriggerBaseSchema): @@ -66,8 +66,8 @@ class CognitoPreAuthenticationTriggerModel(CognitoTriggerBaseSchema): # Models for Post-Authentication flow class CognitoPostAuthenticationRequestModel(BaseModel): userAttributes: Dict[str, Any] - newDeviceUsed: Optional[bool] = None - clientMetadata: Optional[Dict[str, Any]] = None + newDeviceUsed: bool | None = None + clientMetadata: Dict[str, Any] | None = None class CognitoPostAuthenticationTriggerModel(CognitoTriggerBaseSchema): @@ -80,13 +80,13 @@ class CognitoPostAuthenticationTriggerModel(CognitoTriggerBaseSchema): class CognitoGroupConfigurationModel(BaseModel): groupsToOverride: List[str] iamRolesToOverride: List[str] - preferredRole: Optional[str] = None + preferredRole: str | None = None class CognitoPreTokenGenerationRequestModel(BaseModel): userAttributes: Dict[str, Any] groupConfiguration: CognitoGroupConfigurationModel - clientMetadata: Optional[Dict[str, Any]] = None + clientMetadata: Dict[str, Any] | None = None class CognitoPreTokenGenerationTriggerModelV1(CognitoTriggerBaseSchema): @@ -96,7 +96,7 @@ class CognitoPreTokenGenerationTriggerModelV1(CognitoTriggerBaseSchema): class CognitoPreTokenGenerationRequestModelV2AndV3(CognitoPreTokenGenerationRequestModel): - scopes: Optional[Dict[str, Any]] = None + scopes: Dict[str, Any] | None = None class CognitoPreTokenGenerationTriggerModelV2AndV3(CognitoTriggerBaseSchema): @@ -107,17 +107,17 @@ class CognitoPreTokenGenerationTriggerModelV2AndV3(CognitoTriggerBaseSchema): # Models for User Migration flow class CognitoMigrateUserRequestModel(BaseModel): password: str - validationData: Optional[Dict[str, Any]] = None - clientMetadata: Optional[Dict[str, Any]] = None + validationData: Dict[str, Any] | None = None + clientMetadata: Dict[str, Any] | None = None class CognitoMigrateUserResponseModel(BaseModel): - userAttributes: Optional[Dict[str, Any]] = None - finalUserStatus: Optional[str] = None - messageAction: Optional[str] = None - desiredDeliveryMediums: Optional[List[str]] = None - forceAliasCreation: Optional[bool] = None - enableSMSMFA: Optional[bool] = None + userAttributes: Dict[str, Any] | None = None + finalUserStatus: str | None = None + messageAction: str | None = None + desiredDeliveryMediums: List[str] | None = None + forceAliasCreation: bool | None = None + enableSMSMFA: bool | None = None class CognitoMigrateUserTriggerModel(CognitoTriggerBaseSchema): @@ -131,15 +131,15 @@ class CognitoMigrateUserTriggerModel(CognitoTriggerBaseSchema): class CognitoCustomMessageRequestModel(BaseModel): userAttributes: Dict[str, Any] codeParameter: str - linkParameter: Optional[str] = None - usernameParameter: Optional[str] = None - clientMetadata: Optional[Dict[str, Any]] = None + linkParameter: str | None = None + usernameParameter: str | None = None + clientMetadata: Dict[str, Any] | None = None class CognitoCustomMessageResponseModel(BaseModel): - smsMessage: Optional[str] = None - emailMessage: Optional[str] = None - emailSubject: Optional[str] = None + smsMessage: str | None = None + emailMessage: str | None = None + emailSubject: str | None = None class CognitoCustomMessageTriggerModel(CognitoTriggerBaseSchema): @@ -152,7 +152,7 @@ class CognitoCustomMessageTriggerModel(CognitoTriggerBaseSchema): class CognitoCustomEmailSMSSenderRequestModel(BaseModel): type: str code: str - clientMetadata: Optional[Dict[str, Any]] = None + clientMetadata: Dict[str, Any] | None = None userAttributes: Dict[str, Any] @@ -179,20 +179,20 @@ class CognitoChallengeResultModel(BaseModel): "ADMIN_NO_SRP_AUTH", ] challengeResult: bool - challengeMetadata: Optional[str] = None + challengeMetadata: str | None = None class CognitoAuthChallengeRequestModel(BaseModel): userAttributes: Dict[str, Any] session: List[CognitoChallengeResultModel] - clientMetadata: Optional[Dict[str, Any]] = None - userNotFound: Optional[bool] = None + clientMetadata: Dict[str, Any] | None = None + userNotFound: bool | None = None class CognitoDefineAuthChallengeResponseModel(BaseModel): - challengeName: Optional[str] = None - issueTokens: Optional[bool] = None - failAuthentication: Optional[bool] = None + challengeName: str | None = None + issueTokens: bool | None = None + failAuthentication: bool | None = None class CognitoDefineAuthChallengeTriggerModel(CognitoTriggerBaseSchema): @@ -202,9 +202,9 @@ class CognitoDefineAuthChallengeTriggerModel(CognitoTriggerBaseSchema): class CognitoCreateAuthChallengeResponseModel(BaseModel): - publicChallengeParameters: Optional[Dict[str, Any]] = None - privateChallengeParameters: Optional[Dict[str, Any]] = None - challengeMetadata: Optional[str] = None + publicChallengeParameters: Dict[str, Any] | None = None + privateChallengeParameters: Dict[str, Any] | None = None + challengeMetadata: str | None = None class CognitoCreateAuthChallengeTriggerModel(CognitoTriggerBaseSchema): @@ -217,8 +217,8 @@ class CognitoVerifyAuthChallengeRequestModel(BaseModel): userAttributes: Dict[str, Any] privateChallengeParameters: Dict[str, Any] challengeAnswer: str - clientMetadata: Optional[Dict[str, Any]] = None - userNotFound: Optional[bool] = None + clientMetadata: Dict[str, Any] | None = None + userNotFound: bool | None = None class CognitoVerifyAuthChallengeResponseModel(BaseModel): diff --git a/aws_lambda_powertools/utilities/parser/models/dynamodb.py b/aws_lambda_powertools/utilities/parser/models/dynamodb.py index 595e19068e3..714cb06e90a 100644 --- a/aws_lambda_powertools/utilities/parser/models/dynamodb.py +++ b/aws_lambda_powertools/utilities/parser/models/dynamodb.py @@ -1,6 +1,6 @@ # ruff: noqa: FA100 from datetime import datetime -from typing import Any, Dict, List, Literal, Optional, Type, Union +from typing import Any, Dict, List, Literal, Type, Union from pydantic import BaseModel, ConfigDict, Field, field_validator from pydantic.alias_generators import to_camel @@ -11,18 +11,18 @@ class DynamoDBStreamChangedRecordModel(BaseModel): - ApproximateCreationDateTime: Optional[datetime] = Field( # AWS sends this as Unix epoch float + ApproximateCreationDateTime: datetime | None = Field( # AWS sends this as Unix epoch float default=None, description="The approximate date and time when the stream record was created (Unix epoch time).", examples=[1693997155.0], ) Keys: Dict[str, Any] = Field(description="Primary key attributes for the item.", examples=[{"Id": {"N": "101"}}]) - NewImage: Optional[Union[Dict[str, Any], Type[BaseModel], BaseModel]] = Field( + NewImage: Union[Dict[str, Any], Type[BaseModel], BaseModel] | None = Field( default=None, description="The item after modifications, in DynamoDB attribute-value format.", examples=[{"Message": {"S": "New item!"}, "Id": {"N": "101"}}], ) - OldImage: Optional[Union[Dict[str, Any], Type[BaseModel], BaseModel]] = Field( + OldImage: Union[Dict[str, Any], Type[BaseModel], BaseModel] | None = Field( default=None, description="The item before modifications, in DynamoDB attribute-value format.", examples=[{"Message": {"S": "Old item!"}, "Id": {"N": "100"}}], @@ -80,7 +80,7 @@ class DynamoDBStreamRecordModel(BaseModel): }, ], ) - userIdentity: Optional[UserIdentity] = Field( + userIdentity: UserIdentity | None = Field( default=None, description="Information about the identity that made the request.", examples=[{"type": "Service", "principalId": "dynamodb.amazonaws.com"}], @@ -175,7 +175,7 @@ class ResponseContext(BaseModel): description="The version of the Lambda executed", examples=["$LATEST"], ) - function_error: Optional[str] = Field( + function_error: str | None = Field( default=None, description="", examples=["Unhandled"], diff --git a/aws_lambda_powertools/utilities/parser/models/event_bridge.py b/aws_lambda_powertools/utilities/parser/models/event_bridge.py index 67eef21dbf2..11c2e28bc41 100644 --- a/aws_lambda_powertools/utilities/parser/models/event_bridge.py +++ b/aws_lambda_powertools/utilities/parser/models/event_bridge.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List, Optional +from typing import List from pydantic import BaseModel, ConfigDict, Field, field_validator @@ -50,7 +50,7 @@ class EventBridgeModel(BaseModel): detail: RawDictOrModel = Field( description="A JSON object, whose content is at the discretion of the service originating the event.", ) - replay_name: Optional[str] = Field( + replay_name: str | None = Field( None, alias="replay-name", description="Identifies whether the event is being replayed and what is the name of the replay.", diff --git a/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py b/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py index 7af5992a20d..950aa01fe53 100644 --- a/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py +++ b/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Dict, List, Literal from pydantic import BaseModel, Field @@ -25,7 +25,7 @@ class IoTCoreThingEvent(IoTCoreRegistryEventsBase): account_id: str = Field(..., alias="accountId") thing_name: str = Field(..., alias="thingName") version_number: int = Field(..., alias="versionNumber") - thing_type_name: Optional[str] = Field(None, alias="thingTypeName") + thing_type_name: str | None = Field(None, alias="thingTypeName") attributes: Dict[str, Any] @@ -46,7 +46,7 @@ class IoTCoreThingTypeEvent(IoTCoreRegistryEventsBase): thing_type_id: str = Field(..., alias="thingTypeId") thing_type_name: str = Field(..., alias="thingTypeName") is_deprecated: bool = Field(..., alias="isDeprecated") - deprecation_date: Optional[datetime] = Field(None, alias="deprecationDate") + deprecation_date: datetime | None = Field(None, alias="deprecationDate") searchable_attributes: List[str] = Field(..., alias="searchableAttributes") propagating_attributes: List[Dict[str, str]] = Field(..., alias="propagatingAttributes") description: str @@ -84,12 +84,12 @@ class IoTCoreThingGroupEvent(IoTCoreRegistryEventsBase): thing_group_id: str = Field(..., alias="thingGroupId") thing_group_name: str = Field(..., alias="thingGroupName") version_number: int = Field(..., alias="versionNumber") - parent_group_name: Optional[str] = Field(None, alias="parentGroupName") - parent_group_id: Optional[str] = Field(None, alias="parentGroupId") + parent_group_name: str | None = Field(None, alias="parentGroupName") + parent_group_id: str | None = Field(None, alias="parentGroupId") description: str root_to_parent_thing_groups: List[Dict[str, str]] = Field(..., alias="rootToParentThingGroups") attributes: Dict[str, Any] - dynamic_group_mapping_id: Optional[str] = Field(None, alias="dynamicGroupMappingId") + dynamic_group_mapping_id: str | None = Field(None, alias="dynamicGroupMappingId") class IoTCoreAddOrRemoveFromThingGroupEvent(IoTCoreRegistryEventsBase): diff --git a/aws_lambda_powertools/utilities/parser/models/kafka.py b/aws_lambda_powertools/utilities/parser/models/kafka.py index df232469b95..9ce0063d09b 100644 --- a/aws_lambda_powertools/utilities/parser/models/kafka.py +++ b/aws_lambda_powertools/utilities/parser/models/kafka.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Dict, List, Literal, Optional, Type, Union +from typing import Dict, List, Literal, Type, Union from pydantic import BaseModel, Field, field_validator @@ -40,7 +40,7 @@ class KafkaRecordModel(BaseModel): description="The type of timestamp (CREATE_TIME or LOG_APPEND_TIME).", examples=["CREATE_TIME", "LOG_APPEND_TIME"], ) - key: Optional[bytes] = Field( + key: bytes | None = Field( default=None, description="The message key, base64-encoded. Can be null for messages without keys.", examples=["cmVjb3JkS2V5", "dXNlci0xMjM=", "b3JkZXItNDU2", None], @@ -61,12 +61,12 @@ class KafkaRecordModel(BaseModel): [], ], ) - keySchemaMetadata: Optional[KafkaRecordSchemaMetadata] = Field( + keySchemaMetadata: KafkaRecordSchemaMetadata | None = Field( default=None, description="Schema metadata for the message key when using schema registry.", examples=[{"dataFormat": "AVRO", "schemaId": "1234"}, None], ) - valueSchemaMetadata: Optional[KafkaRecordSchemaMetadata] = Field( + valueSchemaMetadata: KafkaRecordSchemaMetadata | None = Field( default=None, description="Schema metadata for the message value when using schema registry.", examples=[{"dataFormat": "AVRO", "schemaId": "1234"}, None], diff --git a/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py b/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py index 697a3fbdd89..77e7b47baa6 100644 --- a/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py +++ b/aws_lambda_powertools/utilities/parser/models/kinesis_firehose.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Type, Union +from typing import List, Type, Union from pydantic import BaseModel, Field, PositiveInt, field_validator @@ -45,7 +45,7 @@ class KinesisFirehoseRecord(BaseModel): (Unix timestamp in milliseconds).", examples=[1428537600000, 1609459200500], ) - kinesisRecordMetadata: Optional[KinesisFirehoseRecordMetadata] = Field( + kinesisRecordMetadata: KinesisFirehoseRecordMetadata | None = Field( None, description="Metadata about the original Kinesis stream record \ (only present when the delivery stream source is a Kinesis stream).", @@ -69,7 +69,7 @@ class KinesisFirehoseModel(BaseModel): description="The AWS region where the delivery stream is located.", examples=["us-east-1", "us-west-2", "eu-west-1"], ) - sourceKinesisStreamArn: Optional[str] = Field( + sourceKinesisStreamArn: str | None = Field( None, description="The ARN of the source Kinesis stream \ (only present when the delivery stream source is a Kinesis stream).", diff --git a/aws_lambda_powertools/utilities/parser/models/kinesis_firehose_sqs.py b/aws_lambda_powertools/utilities/parser/models/kinesis_firehose_sqs.py index b9032a4c934..ecad8b26fc7 100644 --- a/aws_lambda_powertools/utilities/parser/models/kinesis_firehose_sqs.py +++ b/aws_lambda_powertools/utilities/parser/models/kinesis_firehose_sqs.py @@ -1,5 +1,5 @@ import json -from typing import List, Optional +from typing import List from pydantic import BaseModel, Field, PositiveInt, field_validator @@ -20,7 +20,7 @@ class KinesisFirehoseSqsRecord(BaseModel): (Unix timestamp in milliseconds).", examples=[1428537600000, 1609459200500], ) - kinesisRecordMetadata: Optional[KinesisFirehoseRecordMetadata] = Field( + kinesisRecordMetadata: KinesisFirehoseRecordMetadata | None = Field( None, description="Metadata about the original Kinesis stream record \ (only present when the delivery stream source is a Kinesis stream).", @@ -45,7 +45,7 @@ class KinesisFirehoseSqsModel(BaseModel): description="The AWS region where the delivery stream is located.", examples=["us-east-1", "us-west-2", "eu-west-1"], ) - sourceKinesisStreamArn: Optional[str] = Field( + sourceKinesisStreamArn: str | None = Field( None, description="The ARN of the source Kinesis stream \ (only present when the delivery stream source is a Kinesis stream).", diff --git a/aws_lambda_powertools/utilities/parser/models/s3.py b/aws_lambda_powertools/utilities/parser/models/s3.py index d53a0fe5655..a2aeb945e9e 100644 --- a/aws_lambda_powertools/utilities/parser/models/s3.py +++ b/aws_lambda_powertools/utilities/parser/models/s3.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List, Literal, Optional, Union +from typing import List, Literal, Union from pydantic import BaseModel, model_validator from pydantic.fields import Field @@ -130,12 +130,12 @@ class S3Object(BaseModel): "logs/2023/01/15/app.log", ], ) - size: Optional[NonNegativeFloat] = Field( + size: NonNegativeFloat | None = Field( default=None, description="The size of the object in bytes.", examples=[1024, 2048576, 0], ) - eTag: Optional[str] = Field( + eTag: str | None = Field( default=None, description="The entity tag (ETag) of the object.", examples=[ @@ -143,7 +143,7 @@ class S3Object(BaseModel): "098f6bcd4621d373cade4e832627b4f6", ], ) - sequencer: Optional[str] = Field( + sequencer: str | None = Field( default=None, description="A string representation of a hexadecimal value used to determine event sequence.", examples=[ @@ -151,7 +151,7 @@ class S3Object(BaseModel): "005B21C13A6F24045E", ], ) - versionId: Optional[str] = Field( + versionId: str | None = Field( default=None, description="The version ID of the object (if versioning is enabled).", examples=[ @@ -188,7 +188,7 @@ class S3Message(BaseModel): }, ], ) - object: Optional[S3Object] = Field( + object: S3Object | None = Field( default=None, description="The S3 object object. Used by most S3 event types.", examples=[ @@ -200,7 +200,7 @@ class S3Message(BaseModel): }, ], ) # noqa: A003 - get_object: Optional[S3Object] = Field( + get_object: S3Object | None = Field( default=None, alias="get_object", description="The S3 object object. Used by IntelligentTiering events instead of 'object'.", @@ -225,7 +225,7 @@ class S3EventNotificationObjectModel(BaseModel): "logs/2023/01/15/app.log", ], ) - size: Optional[NonNegativeFloat] = Field( + size: NonNegativeFloat | None = Field( default=None, description="The size of the object in bytes.", examples=[1024, 2048576, 0], @@ -238,7 +238,7 @@ class S3EventNotificationObjectModel(BaseModel): "098f6bcd4621d373cade4e832627b4f6", ], ) - version_id: Optional[str] = Field( + version_id: str | None = Field( default=None, alias="version-id", description="The version ID of the object (if versioning is enabled).", @@ -247,7 +247,7 @@ class S3EventNotificationObjectModel(BaseModel): "null", ], ) - sequencer: Optional[str] = Field( + sequencer: str | None = Field( default=None, description="A string representation of a hexadecimal value used to determine event sequence.", examples=[ @@ -307,7 +307,7 @@ class S3EventNotificationEventBridgeDetailModel(BaseModel): "123456789012", ], ) - source_ip_address: Optional[str] = Field( + source_ip_address: str | None = Field( None, alias="source-ip-address", description="Source IP address of S3 request. Only present for events triggered by an S3 request.", @@ -315,7 +315,7 @@ class S3EventNotificationEventBridgeDetailModel(BaseModel): "255.255.255.255", ], ) - reason: Optional[str] = Field( + reason: str | None = Field( default=None, description="For 'Object Created' events, the S3 API used to create the object: PutObject, POST Object, " "CopyObject, or CompleteMultipartUpload. For 'Object Deleted' events, this is set to 'DeleteObject' " @@ -327,7 +327,7 @@ class S3EventNotificationEventBridgeDetailModel(BaseModel): "DeleteObject", ], ) - deletion_type: Optional[str] = Field( + deletion_type: str | None = Field( default=None, alias="deletion-type", description="For 'Object Deleted' events, when an unversioned object is deleted, or a versioned object is " @@ -336,28 +336,28 @@ class S3EventNotificationEventBridgeDetailModel(BaseModel): "see https://docs.aws.amazon.com/AmazonS3/latest/userguide/DeletingObjectVersions.html", examples=["Delete Marker Created", "Permanently Deleted"], ) - restore_expiry_time: Optional[str] = Field( + restore_expiry_time: str | None = Field( default=None, alias="restore-expiry-time", description="For 'Object Restore Completed' events, the time when the temporary copy of the object will be " "deleted from S3. For more information, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/archived-objects.html.", examples=["2021-11-13T00:00:00Z"], ) - source_storage_class: Optional[str] = Field( + source_storage_class: str | None = Field( default=None, alias="source-storage-class", description="For 'Object Restore Initiated' and 'Object Restore Completed' events, the storage class of the " "object being restored. For more information, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/archived-objects.html.", examples=["GLACIER", "STANDARD", "STANDARD_IA"], ) - destination_storage_class: Optional[str] = Field( + destination_storage_class: str | None = Field( default=None, alias="destination-storage-class", description="For 'Object Storage Class Changed' events, the new storage class of the object. For more " "information, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-transition-general-considerations.html.", examples=["INTELLIGENT_TIERING", "STANDARD", "STANDARD_IA"], ) - destination_access_tier: Optional[str] = Field( + destination_access_tier: str | None = Field( default=None, alias="destination-access-tier", description="For 'Object Access Tier Changed' events, the new access tier of the object. For more information, " @@ -462,7 +462,7 @@ class S3RecordModel(BaseModel): }, ], ) - glacierEventData: Optional[S3EventRecordGlacierEventData] = Field( + glacierEventData: S3EventRecordGlacierEventData | None = Field( default=None, description="The Glacier event data object.", examples=[ @@ -474,7 +474,7 @@ class S3RecordModel(BaseModel): }, ], ) - intelligentTieringEventData: Optional[S3EventRecordIntelligentTieringEventData] = Field( + intelligentTieringEventData: S3EventRecordIntelligentTieringEventData | None = Field( default=None, description="The Intelligent-Tiering event data object.", examples=[ diff --git a/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py b/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py index 934ace9ac07..b9581243f51 100644 --- a/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py +++ b/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Dict, List, Literal from pydantic import BaseModel, model_validator @@ -6,9 +6,9 @@ class S3BatchOperationTaskModel(BaseModel): taskId: str s3Key: str - s3VersionId: Optional[str] = None - s3BucketArn: Optional[str] = None - s3Bucket: Optional[str] = None + s3VersionId: str | None = None + s3BucketArn: str | None = None + s3Bucket: str | None = None @model_validator(mode="before") def validate_s3bucket(cls, values: Dict[str, Any]) -> Dict[str, Any]: @@ -20,7 +20,7 @@ def validate_s3bucket(cls, values: Dict[str, Any]) -> Dict[str, Any]: class S3BatchOperationJobModel(BaseModel): id: str - userArguments: Optional[Dict[str, Any]] = None + userArguments: Dict[str, Any] | None = None class S3BatchOperationModel(BaseModel): diff --git a/aws_lambda_powertools/utilities/parser/models/s3_object_event.py b/aws_lambda_powertools/utilities/parser/models/s3_object_event.py index 867cd996fa0..1bd2c2628af 100644 --- a/aws_lambda_powertools/utilities/parser/models/s3_object_event.py +++ b/aws_lambda_powertools/utilities/parser/models/s3_object_event.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional, Type, Union +from typing import Dict, Type, Union from pydantic import BaseModel, HttpUrl @@ -22,7 +22,7 @@ class S3ObjectUserRequest(BaseModel): class S3ObjectSessionIssuer(BaseModel): type: str # noqa: A003, VNE003 - userName: Optional[str] = None + userName: str | None = None principalId: str arn: str accountId: str @@ -42,10 +42,10 @@ class S3ObjectUserIdentity(BaseModel): type: str # noqa: A003 accountId: str accessKeyId: str - userName: Optional[str] = None + userName: str | None = None principalId: str arn: str - sessionContext: Optional[S3ObjectSessionContext] = None + sessionContext: S3ObjectSessionContext | None = None class S3ObjectLambdaEvent(BaseModel): diff --git a/aws_lambda_powertools/utilities/parser/models/ses.py b/aws_lambda_powertools/utilities/parser/models/ses.py index 9a7a9914e6e..833cc557df0 100644 --- a/aws_lambda_powertools/utilities/parser/models/ses.py +++ b/aws_lambda_powertools/utilities/parser/models/ses.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List, Literal, Optional +from typing import List, Literal from pydantic import BaseModel, Field from pydantic.types import PositiveInt @@ -34,10 +34,10 @@ class SesMailHeaders(BaseModel): class SesMailCommonHeaders(BaseModel): header_from: List[str] = Field(..., alias="from") to: List[str] - cc: Optional[List[str]] = None - bcc: Optional[List[str]] = None - sender: Optional[List[str]] = None - reply_to: Optional[List[str]] = Field(None, alias="reply-to") + cc: List[str] | None = None + bcc: List[str] | None = None + sender: List[str] | None = None + reply_to: List[str] | None = Field(None, alias="reply-to") returnPath: str messageId: str date: str diff --git a/aws_lambda_powertools/utilities/parser/models/sns.py b/aws_lambda_powertools/utilities/parser/models/sns.py index 62b8efc2e17..c2a740dbcbd 100644 --- a/aws_lambda_powertools/utilities/parser/models/sns.py +++ b/aws_lambda_powertools/utilities/parser/models/sns.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Dict, List, Literal, Optional, Union +from typing import Dict, List, Literal, Union from typing import Type as TypingType from pydantic import BaseModel, Field, model_validator @@ -18,7 +18,7 @@ class SnsMsgAttributeModel(BaseModel): class SnsNotificationModel(BaseModel): - Subject: Optional[str] = Field( + Subject: str | None = Field( default=None, description="The subject parameter provided when the notification was published to the topic.", examples=["TestInvoke", "Alert: System maintenance", "Order Confirmation", None], @@ -48,7 +48,7 @@ class SnsNotificationModel(BaseModel): description="The type of message. For Lambda triggers, this is always 'Notification'.", examples=["Notification"], ) - MessageAttributes: Optional[Dict[str, SnsMsgAttributeModel]] = Field( + MessageAttributes: Dict[str, SnsMsgAttributeModel] | None = Field( default=None, description="User-defined message attributes as key-value pairs with type information.", examples=[ @@ -73,7 +73,7 @@ class SnsNotificationModel(BaseModel): "f3c8d4e2-1a2b-4c5d-9e8f-7g6h5i4j3k2l", ], ) - SigningCertUrl: Optional[HttpUrl] = Field( + SigningCertUrl: HttpUrl | None = Field( default=None, description=( "The URL to the certificate that was used to sign the message. " @@ -85,7 +85,7 @@ class SnsNotificationModel(BaseModel): None, ], ) # NOTE: FIFO opt-in removes attribute - Signature: Optional[str] = Field( + Signature: str | None = Field( default=None, description=( "Base64-encoded SHA1withRSA signature of the message. " @@ -105,7 +105,7 @@ class SnsNotificationModel(BaseModel): "2023-12-25T18:45:30.123Z", ], ) - SignatureVersion: Optional[str] = Field( + SignatureVersion: str | None = Field( default=None, description=( "Version of the Amazon SNS signature used. Not present for FIFO topics with content-based deduplication." diff --git a/aws_lambda_powertools/utilities/parser/models/sqs.py b/aws_lambda_powertools/utilities/parser/models/sqs.py index 06452cd2a8f..020fe2288dc 100644 --- a/aws_lambda_powertools/utilities/parser/models/sqs.py +++ b/aws_lambda_powertools/utilities/parser/models/sqs.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Dict, List, Literal, Optional, Sequence, Type, Union +from typing import Dict, List, Literal, Sequence, Type, Union from pydantic import BaseModel, Field @@ -13,12 +13,12 @@ class SqsAttributesModel(BaseModel): description="The time the message was first received from the queue (epoch time in milliseconds).", examples=["1545082649185", "1545082650649", "1713185156612"], ) - MessageDeduplicationId: Optional[str] = Field( + MessageDeduplicationId: str | None = Field( default=None, description="Returns the value provided by the producer that calls the SendMessage action.", examples=["msg-dedup-12345", "unique-msg-abc123", None], ) - MessageGroupId: Optional[str] = Field( + MessageGroupId: str | None = Field( default=None, description="Returns the value provided by the producer that calls the SendMessage action.", examples=["order-processing", "user-123-updates", None], @@ -31,17 +31,17 @@ class SqsAttributesModel(BaseModel): description="The time the message was sent to the queue (epoch time in milliseconds).", examples=["1545082649183", "1545082650636", "1713185156609"], ) - SequenceNumber: Optional[str] = Field( + SequenceNumber: str | None = Field( default=None, description="Returns the value provided by Amazon SQS.", examples=["18849496460467696128", "18849496460467696129", None], ) - AWSTraceHeader: Optional[str] = Field( + AWSTraceHeader: str | None = Field( default=None, description="The AWS X-Ray trace header for request tracing.", examples=["Root=1-5e1b4151-5ac6c58239c1e5b4", None], ) - DeadLetterQueueSourceArn: Optional[str] = Field( + DeadLetterQueueSourceArn: str | None = Field( default=None, description="The ARN of the dead-letter queue from which the message was moved.", examples=["arn:aws:sqs:eu-central-1:123456789012:sqs-redrive-SampleQueue-RNvLCpwGmLi7", None], @@ -49,12 +49,12 @@ class SqsAttributesModel(BaseModel): class SqsMsgAttributeModel(BaseModel): - stringValue: Optional[str] = Field( + stringValue: str | None = Field( default=None, description="The string value of the message attribute.", examples=["100", "active", "user-12345", None], ) - binaryValue: Optional[str] = Field( + binaryValue: str | None = Field( default=None, description="The binary value of the message attribute, base64-encoded.", examples=["base64Str", "SGVsbG8gV29ybGQ=", None], @@ -140,7 +140,7 @@ class SqsRecordModel(BaseModel): "6a204bd89f3c8348afd5c77c717a097a", ], ) - md5OfMessageAttributes: Optional[str] = Field( + md5OfMessageAttributes: str | None = Field( default=None, description="An MD5 digest of the non-URL-encoded message attribute string.", examples=[ diff --git a/aws_lambda_powertools/utilities/parser/models/transfer_family.py b/aws_lambda_powertools/utilities/parser/models/transfer_family.py index be23c29449f..8219cef179b 100644 --- a/aws_lambda_powertools/utilities/parser/models/transfer_family.py +++ b/aws_lambda_powertools/utilities/parser/models/transfer_family.py @@ -1,4 +1,4 @@ -from typing import Literal, Optional +from typing import Literal from pydantic import BaseModel, Field from pydantic.networks import IPvAnyAddress @@ -9,7 +9,7 @@ class TransferFamilyAuthorizer(BaseModel): description="The username of the user attempting to authenticate.", examples=["bobusa", "john.doe", "sftp-user-123", "data-transfer-user"], ) - password: Optional[str] = Field( + password: str | None = Field( default=None, description="The password for authentication.", examples=["", "", None], diff --git a/aws_lambda_powertools/utilities/parser/models/vpc_latticev2.py b/aws_lambda_powertools/utilities/parser/models/vpc_latticev2.py index cdb75642bd5..9ce8b79dd85 100644 --- a/aws_lambda_powertools/utilities/parser/models/vpc_latticev2.py +++ b/aws_lambda_powertools/utilities/parser/models/vpc_latticev2.py @@ -1,65 +1,65 @@ from datetime import datetime -from typing import Dict, Optional, Type, Union +from typing import Dict, Type, Union from pydantic import BaseModel, Field, field_validator class VpcLatticeV2RequestContextIdentity(BaseModel): - source_vpc_arn: Optional[str] = Field( + source_vpc_arn: str | None = Field( None, alias="sourceVpcArn", description="The ARN of the VPC from which the request originated.", examples=["arn:aws:ec2:us-east-2:123456789012:vpc/vpc-0b8276c84697e7339"], ) - get_type: Optional[str] = Field( + get_type: str | None = Field( None, alias="type", description="The type of identity making the request.", examples=["AWS_IAM", "NONE"], ) - principal: Optional[str] = Field( + principal: str | None = Field( None, alias="principal", description="The principal ARN of the identity making the request.", examples=["arn:aws:sts::123456789012:assumed-role/example-role/057d00f8b51257ba3c853a0f248943cf"], ) - principal_org_id: Optional[str] = Field( + principal_org_id: str | None = Field( None, alias="principalOrgID", description="The AWS organization ID of the principal.", examples=["o-1234567890"], ) - session_name: Optional[str] = Field( + session_name: str | None = Field( None, alias="sessionName", description="The session name for assumed role sessions.", examples=["057d00f8b51257ba3c853a0f248943cf"], ) - x509_subject_cn: Optional[str] = Field( + x509_subject_cn: str | None = Field( None, alias="X509SubjectCn", description="The X.509 certificate subject common name.", examples=["example.com"], ) - x509_issuer_ou: Optional[str] = Field( + x509_issuer_ou: str | None = Field( None, alias="X509IssuerOu", description="The X.509 certificate issuer organizational unit.", examples=["IT Department"], ) - x509_san_dns: Optional[str] = Field( + x509_san_dns: str | None = Field( None, alias="x509SanDns", description="The X.509 certificate Subject Alternative Name DNS entry.", examples=["example.com"], ) - x509_san_uri: Optional[str] = Field( + x509_san_uri: str | None = Field( None, alias="X509SanUri", description="The X.509 certificate Subject Alternative Name URI entry.", examples=["https://example.com"], ) - x509_san_name_cn: Optional[str] = Field( + x509_san_name_cn: str | None = Field( None, alias="X509SanNameCn", description="The X.509 certificate Subject Alternative Name common name.", @@ -120,17 +120,17 @@ class VpcLatticeV2Model(BaseModel): {"content-type": "application/json"}, ], ) - query_string_parameters: Optional[Dict[str, str]] = Field( + query_string_parameters: Dict[str, str] | None = Field( None, alias="queryStringParameters", description="The query string parameters as key-value pairs.", examples=[{"order-id": "1"}, {"page": "2", "limit": "10"}], ) - body: Optional[Union[str, Type[BaseModel]]] = Field( + body: Union[str, Type[BaseModel]] | None = Field( None, description="The request body. Can be a string or a parsed model if content-type allows parsing.", ) - is_base64_encoded: Optional[bool] = Field( + is_base64_encoded: bool | None = Field( None, alias="isBase64Encoded", description="Indicates whether the body is base64-encoded.", diff --git a/examples/batch_processing/src/advanced_accessing_lambda_context.py b/examples/batch_processing/src/advanced_accessing_lambda_context.py index b0e7eeb98af..d8820138fa1 100644 --- a/examples/batch_processing/src/advanced_accessing_lambda_context.py +++ b/examples/batch_processing/src/advanced_accessing_lambda_context.py @@ -1,5 +1,3 @@ -from typing import Optional - from aws_lambda_powertools import Logger, Tracer from aws_lambda_powertools.utilities.batch import ( BatchProcessor, @@ -15,7 +13,7 @@ @tracer.capture_method -def record_handler(record: SQSRecord, lambda_context: Optional[LambdaContext] = None): +def record_handler(record: SQSRecord, lambda_context: LambdaContext | None = None): if lambda_context is not None: remaining_time = lambda_context.get_remaining_time_in_millis() logger.info(remaining_time) diff --git a/examples/batch_processing/src/advanced_accessing_lambda_context_manager.py b/examples/batch_processing/src/advanced_accessing_lambda_context_manager.py index 17b719a84d4..11e92a13f93 100644 --- a/examples/batch_processing/src/advanced_accessing_lambda_context_manager.py +++ b/examples/batch_processing/src/advanced_accessing_lambda_context_manager.py @@ -1,5 +1,3 @@ -from typing import Optional - from aws_lambda_powertools import Logger, Tracer from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord @@ -11,7 +9,7 @@ @tracer.capture_method -def record_handler(record: SQSRecord, lambda_context: Optional[LambdaContext] = None): +def record_handler(record: SQSRecord, lambda_context: LambdaContext | None = None): if lambda_context is not None: remaining_time = lambda_context.get_remaining_time_in_millis() logger.info(remaining_time) diff --git a/examples/batch_processing/src/pydantic_dynamodb.py b/examples/batch_processing/src/pydantic_dynamodb.py index b46f5c78201..7e411a39caa 100644 --- a/examples/batch_processing/src/pydantic_dynamodb.py +++ b/examples/batch_processing/src/pydantic_dynamodb.py @@ -1,5 +1,5 @@ import json -from typing import Dict, Optional +from typing import Dict from typing_extensions import Literal @@ -32,8 +32,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): # type: ignore[override] - NewImage: Optional[OrderDynamoDB] - OldImage: Optional[OrderDynamoDB] + NewImage: OrderDynamoDB | None + OldImage: OrderDynamoDB | None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): # type: ignore[override] diff --git a/examples/build_recipes/poetry/app_poetry.py b/examples/build_recipes/poetry/app_poetry.py index d570cca39cf..47927eb25b9 100644 --- a/examples/build_recipes/poetry/app_poetry.py +++ b/examples/build_recipes/poetry/app_poetry.py @@ -1,5 +1,3 @@ -from typing import Optional - from pydantic import BaseModel from aws_lambda_powertools import Logger, Metrics, Tracer @@ -16,7 +14,7 @@ class UserModel(BaseModel): name: str email: str - age: Optional[int] = None + age: int | None = None @app.post("/users") diff --git a/examples/build_recipes/sam/no-layers/src/app_sam_no_layer.py b/examples/build_recipes/sam/no-layers/src/app_sam_no_layer.py index dcda4cede13..04c2d227c73 100644 --- a/examples/build_recipes/sam/no-layers/src/app_sam_no_layer.py +++ b/examples/build_recipes/sam/no-layers/src/app_sam_no_layer.py @@ -1,5 +1,3 @@ -from typing import Optional - from pydantic import BaseModel from aws_lambda_powertools import Logger, Metrics, Tracer @@ -16,7 +14,7 @@ class UserModel(BaseModel): name: str email: str - age: Optional[int] = None + age: int | None = None @app.get("/health") diff --git a/examples/build_recipes/sam/with-layers/src/app/app_sam_layer.py b/examples/build_recipes/sam/with-layers/src/app/app_sam_layer.py index 9d4b39e63a1..56425bce2aa 100644 --- a/examples/build_recipes/sam/with-layers/src/app/app_sam_layer.py +++ b/examples/build_recipes/sam/with-layers/src/app/app_sam_layer.py @@ -1,5 +1,3 @@ -from typing import Optional - import requests from pydantic import BaseModel @@ -17,7 +15,7 @@ class UserModel(BaseModel): name: str email: str - age: Optional[int] = None + age: int | None = None @app.get("/health") diff --git a/examples/event_handler_graphql/src/enable_exceptions_batch_resolver.py b/examples/event_handler_graphql/src/enable_exceptions_batch_resolver.py index 1d94e4693c8..b32399167fa 100644 --- a/examples/event_handler_graphql/src/enable_exceptions_batch_resolver.py +++ b/examples/event_handler_graphql/src/enable_exceptions_batch_resolver.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional +from typing import Dict from aws_lambda_powertools.event_handler import AppSyncResolver from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent @@ -18,7 +18,7 @@ class PostRelatedNotFound(Exception): ... @app.batch_resolver(type_name="Query", field_name="relatedPosts", raise_on_error=True) # (1)! -def related_posts(event: AppSyncResolverEvent, post_id: str) -> Optional[Dict]: +def related_posts(event: AppSyncResolverEvent, post_id: str) -> Dict | None: post_found = posts_related.get(post_id, None) if not post_found: diff --git a/examples/event_handler_rest/src/accessing_request_details.py b/examples/event_handler_rest/src/accessing_request_details.py index e9a5d924017..cd6e8b6a56e 100644 --- a/examples/event_handler_rest/src/accessing_request_details.py +++ b/examples/event_handler_rest/src/accessing_request_details.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List import requests from requests import Response @@ -18,13 +18,13 @@ def get_todos(): todo_id: str = app.current_event.query_string_parameters["id"] # alternatively - _: Optional[str] = app.current_event.query_string_parameters.get("id") + _: str | None = app.current_event.query_string_parameters.get("id") # or multi-value query string parameters; ?category="red"&?category="blue" _: List[str] = app.current_event.multi_value_query_string_parameters["category"] # Payload - _: Optional[str] = app.current_event.body # raw str | None + _: str | None = app.current_event.body # raw str | None endpoint = "https://jsonplaceholder.typicode.com/todos" if todo_id: diff --git a/examples/event_handler_rest/src/customizing_response_validation.py b/examples/event_handler_rest/src/customizing_response_validation.py index 25aa07bf52a..2043c0c9c57 100644 --- a/examples/event_handler_rest/src/customizing_response_validation.py +++ b/examples/event_handler_rest/src/customizing_response_validation.py @@ -1,5 +1,4 @@ from http import HTTPStatus -from typing import Optional import requests from pydantic import BaseModel, Field @@ -19,7 +18,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/customizing_response_validation_exception.py b/examples/event_handler_rest/src/customizing_response_validation_exception.py index c94ace290d2..871c222151c 100644 --- a/examples/event_handler_rest/src/customizing_response_validation_exception.py +++ b/examples/event_handler_rest/src/customizing_response_validation_exception.py @@ -1,5 +1,4 @@ from http import HTTPStatus -from typing import Optional import requests from pydantic import BaseModel, Field @@ -21,7 +20,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/data_validation.py b/examples/event_handler_rest/src/data_validation.py index 1daa9fb2174..bbb43df74ea 100644 --- a/examples/event_handler_rest/src/data_validation.py +++ b/examples/event_handler_rest/src/data_validation.py @@ -1,5 +1,3 @@ -from typing import Optional - import requests from pydantic import BaseModel, Field @@ -15,7 +13,7 @@ class Todo(BaseModel): # (2)! userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/data_validation_fine_grained_response.py b/examples/event_handler_rest/src/data_validation_fine_grained_response.py index 1209c6a1af1..36ee0a41299 100644 --- a/examples/event_handler_rest/src/data_validation_fine_grained_response.py +++ b/examples/event_handler_rest/src/data_validation_fine_grained_response.py @@ -1,5 +1,4 @@ from http import HTTPStatus -from typing import Optional import requests from pydantic import BaseModel, Field @@ -16,7 +15,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/data_validation_sanitized_error.py b/examples/event_handler_rest/src/data_validation_sanitized_error.py index 71849938f48..72d8c82b737 100644 --- a/examples/event_handler_rest/src/data_validation_sanitized_error.py +++ b/examples/event_handler_rest/src/data_validation_sanitized_error.py @@ -1,5 +1,3 @@ -from typing import Optional - import requests from pydantic import BaseModel, Field @@ -16,7 +14,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/skip_validating_query_strings.py b/examples/event_handler_rest/src/skip_validating_query_strings.py index 882769239a1..0cf6628035e 100644 --- a/examples/event_handler_rest/src/skip_validating_query_strings.py +++ b/examples/event_handler_rest/src/skip_validating_query_strings.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List import requests from pydantic import BaseModel, Field @@ -15,14 +15,14 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool @app.get("/todos") @tracer.capture_method -def get_todos(completed: Optional[str] = None) -> List[Todo]: # (1)! +def get_todos(completed: str | None = None) -> List[Todo]: # (1)! url = "https://jsonplaceholder.typicode.com/todos" if completed is not None: diff --git a/examples/event_handler_rest/src/validating_headers.py b/examples/event_handler_rest/src/validating_headers.py index f92f0ead463..9c649c11bac 100644 --- a/examples/event_handler_rest/src/validating_headers.py +++ b/examples/event_handler_rest/src/validating_headers.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List import requests from pydantic import BaseModel, Field @@ -17,7 +17,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/validating_headers_with_pydantic.py b/examples/event_handler_rest/src/validating_headers_with_pydantic.py index 03f6c56e9fd..821ad566185 100644 --- a/examples/event_handler_rest/src/validating_headers_with_pydantic.py +++ b/examples/event_handler_rest/src/validating_headers_with_pydantic.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Dict from pydantic import BaseModel, Field from typing_extensions import Annotated @@ -16,7 +16,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/validating_path.py b/examples/event_handler_rest/src/validating_path.py index c5ddbba4f37..f1001a6e18f 100644 --- a/examples/event_handler_rest/src/validating_path.py +++ b/examples/event_handler_rest/src/validating_path.py @@ -1,5 +1,3 @@ -from typing import Optional - import requests from pydantic import BaseModel, Field from typing_extensions import Annotated @@ -17,7 +15,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/validating_payload_subset.py b/examples/event_handler_rest/src/validating_payload_subset.py index ebd0cf0c20f..051505369f9 100644 --- a/examples/event_handler_rest/src/validating_payload_subset.py +++ b/examples/event_handler_rest/src/validating_payload_subset.py @@ -1,5 +1,3 @@ -from typing import Optional - import requests from pydantic import BaseModel, Field from typing_extensions import Annotated @@ -13,7 +11,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/validating_payloads.py b/examples/event_handler_rest/src/validating_payloads.py index 945cefd8089..a7ed6c88749 100644 --- a/examples/event_handler_rest/src/validating_payloads.py +++ b/examples/event_handler_rest/src/validating_payloads.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List import requests from pydantic import BaseModel, Field @@ -15,7 +15,7 @@ class Todo(BaseModel): # (2)! userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/validating_query_string_with_pydantic.py b/examples/event_handler_rest/src/validating_query_string_with_pydantic.py index 75f6212e1a6..2ea42995c37 100644 --- a/examples/event_handler_rest/src/validating_query_string_with_pydantic.py +++ b/examples/event_handler_rest/src/validating_query_string_with_pydantic.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Dict from pydantic import BaseModel, Field from typing_extensions import Annotated @@ -16,7 +16,7 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/examples/event_handler_rest/src/validating_query_strings.py b/examples/event_handler_rest/src/validating_query_strings.py index 047e9973b63..75ff7450a1c 100644 --- a/examples/event_handler_rest/src/validating_query_strings.py +++ b/examples/event_handler_rest/src/validating_query_strings.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List import requests from pydantic import BaseModel, Field @@ -17,14 +17,14 @@ class Todo(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool @app.get("/todos") @tracer.capture_method -def get_todos(completed: Annotated[Optional[str], Query(min_length=4)] = None) -> List[Todo]: # (3)! +def get_todos(completed: Annotated[str | None, Query(min_length=4)] = None) -> List[Todo]: # (3)! url = "https://jsonplaceholder.typicode.com/todos" if completed is not None: diff --git a/examples/idempotency/src/bring_your_own_persistent_store.py b/examples/idempotency/src/bring_your_own_persistent_store.py index 83ab27b8c4e..50e3595e94f 100644 --- a/examples/idempotency/src/bring_your_own_persistent_store.py +++ b/examples/idempotency/src/bring_your_own_persistent_store.py @@ -1,6 +1,6 @@ import datetime import logging -from typing import Any, Dict, Optional +from typing import Any, Dict import boto3 from botocore.config import Config @@ -24,8 +24,8 @@ def __init__( status_attr: str = "status", data_attr: str = "data", validation_key_attr: str = "validation", - boto_config: Optional[Config] = None, - boto3_session: Optional[boto3.session.Session] = None, + boto_config: Config | None = None, + boto3_session: boto3.session.Session | None = None, ): boto3_session = boto3_session or boto3.session.Session() self._ddb_resource = boto3_session.resource("dynamodb", config=boto_config) diff --git a/examples/logger/src/bring_your_own_formatter_from_scratch.py b/examples/logger/src/bring_your_own_formatter_from_scratch.py index 425f00b0d28..7bcffa1d0af 100644 --- a/examples/logger/src/bring_your_own_formatter_from_scratch.py +++ b/examples/logger/src/bring_your_own_formatter_from_scratch.py @@ -1,13 +1,13 @@ import json import logging -from typing import Any, Dict, Iterable, List, Optional +from typing import Any, Dict, Iterable, List from aws_lambda_powertools import Logger from aws_lambda_powertools.logging.formatter import BasePowertoolsFormatter class CustomFormatter(BasePowertoolsFormatter): - def __init__(self, log_record_order: Optional[List[str]] = None, *args, **kwargs): + def __init__(self, log_record_order: List[str] | None = None, *args, **kwargs): self.log_record_order = log_record_order or ["level", "location", "message", "timestamp"] self.log_format = dict.fromkeys(self.log_record_order) super().__init__(*args, **kwargs) diff --git a/examples/streaming/src/assert_transformation_module.py b/examples/streaming/src/assert_transformation_module.py index eac11abd4af..cc9b1dc4984 100644 --- a/examples/streaming/src/assert_transformation_module.py +++ b/examples/streaming/src/assert_transformation_module.py @@ -1,5 +1,5 @@ import io -from typing import IO, Optional +from typing import IO from aws_lambda_powertools.utilities.streaming.transformations import BaseTransform @@ -9,7 +9,7 @@ def __init__(self, input_stream: IO[bytes], encoding: str): self.encoding = encoding self.input_stream = io.TextIOWrapper(input_stream, encoding=encoding) - def read(self, size: int = -1) -> Optional[bytes]: + def read(self, size: int = -1) -> bytes | None: data = self.input_stream.read(size) return data.upper().encode(self.encoding) diff --git a/examples/streaming/src/s3_json_transform.py b/examples/streaming/src/s3_json_transform.py index 30c31b0f32c..8588498e38b 100644 --- a/examples/streaming/src/s3_json_transform.py +++ b/examples/streaming/src/s3_json_transform.py @@ -1,5 +1,5 @@ import io -from typing import IO, Optional +from typing import IO import ijson @@ -11,10 +11,10 @@ class JsonDeserializer(io.RawIOBase): def __init__(self, input_stream: IO[bytes]): self.input = ijson.items(input_stream, "", multiple_values=True) - def read(self, size: int = -1) -> Optional[bytes]: + def read(self, size: int = -1) -> bytes | None: raise NotImplementedError(f"{__name__} does not implement read") - def readline(self, size: Optional[int] = None) -> bytes: + def readline(self, size: int | None = None) -> bytes: raise NotImplementedError(f"{__name__} does not implement readline") def read_object(self) -> dict: diff --git a/ruff.toml b/ruff.toml index 304f77c680d..1bdb7ffa4ae 100644 --- a/ruff.toml +++ b/ruff.toml @@ -45,7 +45,6 @@ lint.ignore = [ "UP006", "UP007", "UP035", - "UP045", ] # Exclude files and directories diff --git a/tests/e2e/utils/data_fetcher/common.py b/tests/e2e/utils/data_fetcher/common.py index 1300daa55aa..61a56386251 100644 --- a/tests/e2e/utils/data_fetcher/common.py +++ b/tests/e2e/utils/data_fetcher/common.py @@ -2,7 +2,7 @@ import time from concurrent.futures import Future, ThreadPoolExecutor from datetime import datetime -from typing import List, Optional, Tuple +from typing import List, Tuple import boto3 import requests @@ -18,8 +18,8 @@ class GetLambdaResponseOptions(BaseModel): lambda_arn: str - payload: Optional[str] = None - client: Optional[LambdaClient] = None + payload: str | None = None + client: LambdaClient | None = None raise_on_error: bool = True model_config = ConfigDict( @@ -29,8 +29,8 @@ class GetLambdaResponseOptions(BaseModel): def get_lambda_response( lambda_arn: str, - payload: Optional[str] = None, - client: Optional[LambdaClient] = None, + payload: str | None = None, + client: LambdaClient | None = None, raise_on_error: bool = True, ) -> GetLambdaResponse: """Invoke function synchronously @@ -39,9 +39,9 @@ def get_lambda_response( ---------- lambda_arn : str Lambda function ARN to invoke - payload : Optional[str], optional + payload : str | None, optional JSON payload for Lambda invocation, by default None - client : Optional[LambdaClient], optional + client : LambdaClient | None, optional Boto3 Lambda SDK client, by default None raise_on_error : bool, optional Whether to raise exception upon invocation error, by default True diff --git a/tests/e2e/utils/data_fetcher/logs.py b/tests/e2e/utils/data_fetcher/logs.py index dc036cba36e..eaa783fbba5 100644 --- a/tests/e2e/utils/data_fetcher/logs.py +++ b/tests/e2e/utils/data_fetcher/logs.py @@ -1,6 +1,6 @@ import json from datetime import datetime -from typing import List, Optional, Union +from typing import Any, List, Union import boto3 from mypy_boto3_logs.client import CloudWatchLogsClient @@ -14,12 +14,12 @@ class Log(BaseModel, extra="allow"): message: Union[dict, str] timestamp: str service: str - cold_start: Optional[bool] = None - function_name: Optional[str] = None - function_memory_size: Optional[str] = None - function_arn: Optional[str] = None - function_request_id: Optional[str] = None - xray_trace_id: Optional[str] = None + cold_start: bool | None = None + function_name: str | None = None + function_memory_size: str | None = None + function_arn: str | None = None + function_request_id: str | None = None + xray_trace_id: str | None = None class LogFetcher: @@ -27,8 +27,8 @@ def __init__( self, function_name: str, start_time: datetime, - log_client: Optional[CloudWatchLogsClient] = None, - filter_expression: Optional[str] = None, + log_client: CloudWatchLogsClient | None = None, + filter_expression: str | None = None, minimum_log_entries: int = 1, ): """Fetch and expose Powertools for AWS Lambda (Python) Logger logs from CloudWatch Logs @@ -39,9 +39,9 @@ def __init__( Name of Lambda function to fetch logs for start_time : datetime Start date range to filter traces - log_client : Optional[CloudWatchLogsClient], optional + log_client : CloudWatchLogsClient | None, optional Amazon CloudWatch Logs Client, by default boto3.client('logs) - filter_expression : Optional[str], optional + filter_expression : str | None, optional CloudWatch Logs Filter Pattern expression, by default "message" minimum_log_entries: int Minimum number of log entries to be retrieved before exhausting retry attempts @@ -54,14 +54,14 @@ def __init__( self.minimum_log_entries = minimum_log_entries self.logs: List[Log] = self._get_logs() - def get_log(self, key: str, value: Optional[any] = None) -> List[Log]: + def get_log(self, key: str, value: Any | None = None) -> List[Log]: """Get logs based on key or key and value Parameters ---------- key : str Log key name - value : Optional[any], optional + value : Any | None, optional Log value, by default None Returns @@ -132,8 +132,8 @@ def get_logs( function_name: str, start_time: datetime, minimum_log_entries: int = 1, - filter_expression: Optional[str] = None, - log_client: Optional[CloudWatchLogsClient] = None, + filter_expression: str | None = None, + log_client: CloudWatchLogsClient | None = None, ) -> LogFetcher: """_summary_ @@ -145,9 +145,9 @@ def get_logs( Start date range to filter traces minimum_log_entries : int Minimum number of log entries to be retrieved before exhausting retry attempts - log_client : Optional[CloudWatchLogsClient], optional + log_client : CloudWatchLogsClient | None, optional Amazon CloudWatch Logs Client, by default boto3.client('logs) - filter_expression : Optional[str], optional + filter_expression : str | None, optional CloudWatch Logs Filter Pattern expression, by default "message" Returns diff --git a/tests/e2e/utils/data_fetcher/traces.py b/tests/e2e/utils/data_fetcher/traces.py index f8b364fc97c..4309fa0d520 100644 --- a/tests/e2e/utils/data_fetcher/traces.py +++ b/tests/e2e/utils/data_fetcher/traces.py @@ -1,6 +1,6 @@ import json from datetime import datetime, timedelta -from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional +from typing import TYPE_CHECKING, Any, Dict, Generator, List import boto3 from botocore.paginate import PageIterator @@ -17,10 +17,10 @@ class TraceSubsegment(BaseModel): name: str start_time: float end_time: float - aws: Optional[dict] = None - subsegments: Optional[List["TraceSubsegment"]] = None - annotations: Optional[Dict[str, Any]] = None - metadata: Optional[Dict[str, Dict[str, Any]]] = None + aws: dict | None = None + subsegments: List["TraceSubsegment"] | None = None + annotations: Dict[str, Any] | None = None + metadata: Dict[str, Dict[str, Any]] | None = None class TraceDocument(BaseModel): @@ -29,10 +29,10 @@ class TraceDocument(BaseModel): start_time: float end_time: float trace_id: str - parent_id: Optional[str] = None + parent_id: str | None = None aws: Dict origin: str - subsegments: Optional[List[TraceSubsegment]] = None + subsegments: List[TraceSubsegment] | None = None class TraceFetcher: @@ -42,11 +42,11 @@ def __init__( self, filter_expression: str, start_date: datetime, - end_date: Optional[datetime] = None, - xray_client: Optional[XRayClient] = None, - exclude_segment_name: Optional[List[str]] = None, - resource_name: Optional[List[str]] = None, - origin: Optional[List[str]] = None, + end_date: datetime | None = None, + xray_client: XRayClient | None = None, + exclude_segment_name: List[str] | None = None, + resource_name: List[str] | None = None, + origin: List[str] | None = None, minimum_traces: int = 1, ): """Fetch and expose traces from X-Ray based on parameters @@ -67,15 +67,15 @@ def __init__( see: https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html start_date : datetime Start date range to filter traces - end_date : Optional[datetime], optional + end_date : datetime | None, optional End date range to filter traces, by default 5 minutes past start_date - xray_client : Optional[XRayClient], optional + xray_client : XRayClient | None, optional AWS X-Ray SDK Client, by default boto3.client('xray') - exclude_segment_name : Optional[List[str]], optional + exclude_segment_name : List[str] | None, optional Name of segments to exclude, by default ["Initialization", "Invocation", "Overhead"] - resource_name : Optional[List[str]], optional + resource_name : List[str] | None, optional Name of resource to filter traces (e.g., function name), by default None - origin : Optional[List[str]], optional + origin : List[str] | None, optional Trace origin name to filter traces, by default ["AWS::Lambda::Function"] minimum_traces : int Minimum number of traces to be retrieved before exhausting retry attempts @@ -106,7 +106,7 @@ def __init__( self.trace_documents = self._get_trace_documents(trace_ids) self.subsegments = self._get_subsegments() - def get_annotation(self, key: str, value: Optional[any] = None) -> List: + def get_annotation(self, key: str, value: Any | None = None) -> List: return [ annotation for annotation in self.annotations @@ -223,11 +223,11 @@ def _get_trace_documents(self, trace_ids: List[str]) -> Dict[str, TraceDocument] def get_traces( filter_expression: str, start_date: datetime, - end_date: Optional[datetime] = None, - xray_client: Optional[XRayClient] = None, - exclude_segment_name: Optional[List[str]] = None, - resource_name: Optional[List[str]] = None, - origin: Optional[List[str]] = None, + end_date: datetime | None = None, + xray_client: XRayClient | None = None, + exclude_segment_name: List[str] | None = None, + resource_name: List[str] | None = None, + origin: List[str] | None = None, minimum_traces: int = 1, ) -> TraceFetcher: """Fetch traces from AWS X-Ray @@ -239,15 +239,15 @@ def get_traces( see: https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html start_date : datetime Start date range to filter traces - end_date : Optional[datetime], optional + end_date : datetime | None, optional End date range to filter traces, by default 5 minutes past start_date - xray_client : Optional[XRayClient], optional + xray_client : XRayClient | None, optional AWS X-Ray SDK Client, by default boto3.client('xray') - exclude_segment_name : Optional[List[str]], optional + exclude_segment_name : List[str] | None, optional Name of segments to exclude, by default ["Initialization", "Invocation", "Overhead"] - resource_name : Optional[List[str]], optional + resource_name : List[str] | None, optional Name of resource to filter traces (e.g., function name), by default None - origin : Optional[List[str]], optional + origin : List[str] | None, optional Trace origin name to filter traces, by default ["AWS::Lambda::Function"] minimum_traces : int Minimum number of traces to be retrieved before exhausting retry attempts diff --git a/tests/functional/batch/_pydantic/sample_models.py b/tests/functional/batch/_pydantic/sample_models.py index c2912b3f8a3..d3974ccce82 100644 --- a/tests/functional/batch/_pydantic/sample_models.py +++ b/tests/functional/batch/_pydantic/sample_models.py @@ -1,5 +1,5 @@ import json -from typing import Dict, Optional +from typing import Dict from pydantic import field_validator @@ -44,8 +44,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: Optional[OrderDynamoDB] = None - OldImage: Optional[OrderDynamoDB] = None + NewImage: OrderDynamoDB | None = None + OldImage: OrderDynamoDB | None = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): diff --git a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py index 382cbdb0335..1e6a0452d2a 100644 --- a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py +++ b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py @@ -1,7 +1,7 @@ import json import uuid from random import randint -from typing import Any, Awaitable, Callable, Dict, Optional +from typing import Any, Awaitable, Callable, Dict import pytest from pydantic import BaseModel, field_validator @@ -311,8 +311,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): return json.loads(value) class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: Optional[OrderDynamoDB] = None - OldImage: Optional[OrderDynamoDB] = None + NewImage: OrderDynamoDB | None = None + OldImage: OrderDynamoDB | None = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): dynamodb: OrderDynamoDBChangeRecord @@ -355,8 +355,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): return json.loads(value) class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: Optional[OrderDynamoDB] = None - OldImage: Optional[OrderDynamoDB] = None + NewImage: OrderDynamoDB | None = None + OldImage: OrderDynamoDB | None = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): dynamodb: OrderDynamoDBChangeRecord diff --git a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py index 4367a94f49d..90e9e69790b 100644 --- a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py +++ b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py @@ -1,6 +1,6 @@ import json from functools import partial -from typing import Any, Dict, Optional +from typing import Any, Dict import pytest from typing_extensions import Annotated @@ -192,7 +192,7 @@ def test_openapi_schema_for_pydanticv2(openapi30_schema): # WHEN we have a simple handler @app.get("/", description="Testing") - def handler() -> Optional[Dict]: + def handler() -> Dict | None: pass # WHEN we get the schema @@ -336,7 +336,7 @@ def test_bedrock_resolver_with_openapi_extensions(): # WHEN we have a simple handler with openapi extension @app.get("/", description="Testing", openapi_extensions={"x-requireConfirmation": "ENABLED"}) - def handler() -> Optional[Dict]: + def handler() -> Dict | None: pass # WHEN we get the schema diff --git a/tests/functional/event_handler/_pydantic/test_openapi_params.py b/tests/functional/event_handler/_pydantic/test_openapi_params.py index 40722bb838b..b9426bf4da7 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_params.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_params.py @@ -1,7 +1,7 @@ import json from dataclasses import dataclass from datetime import datetime -from typing import List, Literal, Optional, Tuple +from typing import List, Literal, Tuple import pytest from pydantic import BaseModel, Field @@ -34,7 +34,7 @@ def test_openapi_pydantic_query_params(): class QueryParams(BaseModel): limit: int = Field(default=10, ge=1, le=100, description="Number of items to return") offset: int = Field(default=0, ge=0, description="Number of items to skip") - search: Optional[str] = Field(default=None, description="Search term") + search: str | None = Field(default=None, description="Search term") @app.get("/search") def search_handler(params: Annotated[QueryParams, Query()]): @@ -82,7 +82,7 @@ def test_openapi_pydantic_header_params(): class HeaderParams(BaseModel): authorization: str = Field(description="Authorization token") user_agent: str = Field(default="PowerTools/1.0", description="User agent") - language: Optional[str] = Field(default=None, alias="accept-language", description="Language preference") + language: str | None = Field(default=None, alias="accept-language", description="Language preference") @app.get("/protected") def protected_handler(headers: Annotated[HeaderParams, Header()]): @@ -941,7 +941,7 @@ def test_openapi_form_parameter_edge_cases(): @app.post("/form-edge-cases") def form_edge_cases( required_field: Annotated[str, Form(description="Required field")], - optional_field: Annotated[Optional[str], Form(description="Optional field")] = None, + optional_field: Annotated[str | None, Form(description="Optional field")] = None, field_with_default: Annotated[str, Form(description="Field with default")] = "default_value", ): return {"required": required_field, "optional": optional_field, "default": field_with_default} @@ -1034,7 +1034,7 @@ def test_openapi_pydantic_required_vs_optional(): class QueryParams(BaseModel): required_field: str = Field(description="Required field") optional_with_default: str = Field(default="default", description="Optional with default") - optional_nullable: Optional[str] = Field(default=None, description="Optional nullable") + optional_nullable: str | None = Field(default=None, description="Optional nullable") @app.get("/test") def test_handler(params: Annotated[QueryParams, Query()]): diff --git a/tests/functional/event_handler/_pydantic/test_openapi_responses.py b/tests/functional/event_handler/_pydantic/test_openapi_responses.py index dccfae3e28d..c00b4e00462 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_responses.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_responses.py @@ -1,5 +1,5 @@ from secrets import randbelow -from typing import Optional, Union +from typing import Union from pydantic import BaseModel @@ -325,7 +325,7 @@ def test_openapi_response_examples_preserved_with_model(): class UserResponse(BaseModel): id: int name: str - email: Optional[str] = None + email: str | None = None @app.get( "/", diff --git a/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py b/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py index d25811d24ae..6f4b89e47cc 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py @@ -1,6 +1,6 @@ import json import warnings -from typing import Literal, Optional +from typing import Literal import pytest from pydantic import BaseModel, Field, computed_field @@ -52,7 +52,7 @@ def test_openapi_3_1_complex_handler(openapi31_schema): # GIVEN a complex pydantic model class TodoAttributes(BaseModel): userId: int - id_: Optional[int] = Field(alias="id", default=None) + id_: int | None = Field(alias="id", default=None) title: str completed: bool diff --git a/tests/functional/event_handler/_pydantic/test_openapi_serialization.py b/tests/functional/event_handler/_pydantic/test_openapi_serialization.py index ef5c8ddd938..9bad2c61422 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_serialization.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_serialization.py @@ -1,6 +1,6 @@ import json from dataclasses import dataclass -from typing import Dict, Optional, Set +from typing import Dict, Set import pytest from pydantic import BaseModel @@ -81,7 +81,7 @@ class Model(BaseModel): age: int @app.get("/valid_optional") - def handler_valid_optional() -> Optional[Model]: + def handler_valid_optional() -> Model | None: return Model(name="John", age=30) # WHEN returning a valid model for an Optional type diff --git a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py index aee94e80b14..ec14c14fa08 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from enum import Enum from pathlib import PurePath -from typing import Any, Dict, List, Literal, Optional, Tuple, Union +from typing import Any, Dict, List, Literal, Tuple, Union import pytest from pydantic import ( @@ -88,7 +88,7 @@ def test_validate_pydantic_query_params(gw_event): class QueryParams(BaseModel): limit: int = Field(default=10, ge=1, le=100, description="Number of items") - search: Optional[str] = Field(default=None, description="Search term") + search: str | None = Field(default=None, description="Search term") @app.get("/search") def search_handler(params: Annotated[QueryParams, Query()]): @@ -1777,7 +1777,7 @@ class Model(BaseModel): age: int @app.get("/none_allowed") - def handler_none_allowed() -> Optional[Model]: + def handler_none_allowed() -> Model | None: return None # WHEN returning None for an Optional type @@ -3123,15 +3123,15 @@ def _post_json(app, path, payload): return result["statusCode"], json.loads(result["body"]) -# ---------- Optional[List[Model]] ---------- +# ---------- List[Model] | None ---------- def test_optional_list_body_with_list(): - """Optional[List[Model]] must preserve the full list.""" + """List[Model] | None must preserve the full list.""" app = APIGatewayRestResolver(enable_validation=True) @app.post("/items") - def handler(items: Annotated[Optional[List[_Item]], Body()]) -> Dict[str, Any]: + def handler(items: Annotated[List[_Item] | None, Body()]) -> Dict[str, Any]: assert isinstance(items, list) return {"count": len(items)} @@ -3141,11 +3141,11 @@ def handler(items: Annotated[Optional[List[_Item]], Body()]) -> Dict[str, Any]: def test_optional_list_body_with_none(): - """Optional[List[Model]] must accept a null body gracefully.""" + """List[Model] | None must accept a null body gracefully.""" app = APIGatewayRestResolver(enable_validation=True) @app.post("/items") - def handler(items: Annotated[Optional[List[_Item]], Body()] = None) -> Dict[str, Any]: + def handler(items: Annotated[List[_Item] | None, Body()] = None) -> Dict[str, Any]: return {"received_none": items is None} status, body = _post_json(app, "/items", None) @@ -3153,15 +3153,15 @@ def handler(items: Annotated[Optional[List[_Item]], Body()] = None) -> Dict[str, assert body["received_none"] is True -# ---------- Optional[Union[Model, List[Model]]] ---------- +# ---------- Union[Model, List[Model]] | None ---------- def test_optional_union_model_or_list_with_list(): - """Optional[Union[Model, List[Model]]] — send list, get full list.""" + """Union[Model, List[Model]] | None — send list, get full list.""" app = APIGatewayRestResolver(enable_validation=True) @app.post("/items") - def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Dict[str, Any]: + def handler(items: Annotated[Union[_Item, List[_Item]] | None, Body()]) -> Dict[str, Any]: assert isinstance(items, list) return {"count": len(items)} @@ -3171,11 +3171,11 @@ def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Di def test_optional_union_model_or_list_with_single(): - """Optional[Union[Model, List[Model]]] — send single obj, get single obj.""" + """Union[Model, List[Model]] | None — send single obj, get single obj.""" app = APIGatewayRestResolver(enable_validation=True) @app.post("/items") - def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Dict[str, Any]: + def handler(items: Annotated[Union[_Item, List[_Item]] | None, Body()]) -> Dict[str, Any]: assert not isinstance(items, list) return {"name": items.name} @@ -3185,11 +3185,11 @@ def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Di def test_optional_union_model_or_list_with_none(): - """Optional[Union[Model, List[Model]]] — send null, get None.""" + """Union[Model, List[Model]] | None — send null, get None.""" app = APIGatewayRestResolver(enable_validation=True) @app.post("/items") - def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()] = None) -> Dict[str, Any]: + def handler(items: Annotated[Union[_Item, List[_Item]] | None, Body()] = None) -> Dict[str, Any]: return {"is_none": items is None} status, body = _post_json(app, "/items", None) @@ -3288,11 +3288,11 @@ def handler(data: Annotated[Union[str, List[Dict[str, Any]]], Body()]) -> Dict[s def test_optional_rootmodel_list_body(): - """Optional[RootModel[List[Model]]] — list must not be truncated.""" + """RootModel[List[Model]] | None — list must not be truncated.""" app = APIGatewayRestResolver(enable_validation=True) @app.post("/items") - def handler(items: Annotated[Optional[_ItemCollection], Body()]) -> Dict[str, Any]: + def handler(items: Annotated[_ItemCollection | None, Body()]) -> Dict[str, Any]: return {"count": len(items.root)} status, body = _post_json(app, "/items", _THREE_ITEMS) diff --git a/tests/functional/idempotency/_boto3/test_idempotency.py b/tests/functional/idempotency/_boto3/test_idempotency.py index a4a55dd947a..56b317a9b5a 100644 --- a/tests/functional/idempotency/_boto3/test_idempotency.py +++ b/tests/functional/idempotency/_boto3/test_idempotency.py @@ -2,7 +2,7 @@ import dataclasses import datetime import warnings -from typing import Any, Optional +from typing import Any from unittest.mock import MagicMock, Mock import jmespath @@ -2103,7 +2103,7 @@ class PaymentOutput: config=config, output_serializer=output_serializer, ) - def collect_payment(payment: PaymentInput) -> Optional[PaymentOutput]: + def collect_payment(payment: PaymentInput) -> PaymentOutput | None: return PaymentOutput(**dataclasses.asdict(payment)) # WHEN diff --git a/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py b/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py index f8e3debbc30..b5decebafbe 100644 --- a/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py +++ b/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from pydantic import BaseModel @@ -252,7 +250,7 @@ class PaymentOutput(BaseModel): config=config, output_serializer=output_serializer, ) - def collect_payment(payment: PaymentInput) -> Optional[PaymentOutput]: + def collect_payment(payment: PaymentInput) -> PaymentOutput | None: return PaymentOutput(**payment.dict()) # WHEN diff --git a/tests/functional/idempotency/utils.py b/tests/functional/idempotency/utils.py index 2e1ee4ab821..c6b3ee9b1a0 100644 --- a/tests/functional/idempotency/utils.py +++ b/tests/functional/idempotency/utils.py @@ -1,6 +1,6 @@ import hashlib import json -from typing import Any, Dict, Optional +from typing import Any, Dict from botocore import stub from pytest import FixtureRequest @@ -88,7 +88,7 @@ def build_idempotency_put_item_response_stub( expiration: int, status: str, request: FixtureRequest, - validation_data: Optional[Any], + validation_data: Any | None, ): response = { "Item": { diff --git a/tests/unit/parser/_pydantic/schemas.py b/tests/unit/parser/_pydantic/schemas.py index 0713924c486..2565d649ee9 100644 --- a/tests/unit/parser/_pydantic/schemas.py +++ b/tests/unit/parser/_pydantic/schemas.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List from pydantic import BaseModel @@ -21,8 +21,8 @@ class MyDynamoBusiness(BaseModel): class MyDynamoScheme(DynamoDBStreamChangedRecordModel): - NewImage: Optional[MyDynamoBusiness] = None - OldImage: Optional[MyDynamoBusiness] = None + NewImage: MyDynamoBusiness | None = None + OldImage: MyDynamoBusiness | None = None class MyDynamoDBStreamRecordModel(DynamoDBStreamRecordModel): From a39e1018e36b7965b08313288bea3b7420df5220 Mon Sep 17 00:00:00 2001 From: Aditya Jain <93090622+Adityaj0@users.noreply.github.com> Date: Fri, 28 Aug 2026 12:21:39 -0700 Subject: [PATCH 76/76] fix(idempotency): Redis persistence layer reclaims live in-progress records as orphans, allowing concurrent double-execution (#8387) * fix(idempotency): Redis persistence layer reclaims live in-progress records as orphans, allowing concurrent double-execution RedisCachePersistenceLayer._put_in_progress_record() only guarded against a competing invocation when the existing record's in_progress_expiry_timestamp was set AND still in the future. When that field is None -- which is the normal case for idempotent_function, since it never calls config.register_lambda_context(), unlike the idempotent() handler decorator -- the guard was skipped entirely and a genuinely still-running invocation's record fell through to the "orphan record" branch, which unconditionally overwrites the record with no NX guard. A second concurrent invocation with the same idempotency key would then proceed to execute the underlying function too, defeating idempotency (e.g. double-charging a customer). This is exactly what persistence/base.py's own warning at that call site flags ("Couldn't determine the remaining time left. Did you call register_lambda_context on IdempotencyConfig?") -- it warns, but nothing downstream actually failed closed on it. The DynamoDB persistence layer does not have this gap: its conditional expression requires attribute_exists(#in_progress_expiry) before allowing an expired-in-progress reclaim, so a missing attribute correctly blocks the competing writer instead of granting a reclaim. Fix: when status is INPROGRESS and in_progress_expiry_timestamp is None, treat the record as still in progress (fail closed) instead of falling through to the orphan-reclaim path, mirroring the DynamoDB layer's behavior. * test(idempotency): cover concurrent cache execution --------- Co-authored-by: Leandro --- .../idempotency/persistence/redis.py | 10 ++- .../idempotency/_redis/test_redis_layer.py | 79 +++++++++++++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py index 82a44e079de..ce7100bf215 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py @@ -425,10 +425,12 @@ def _put_in_progress_record(self, data_record: DataRecord) -> None: # (meaning the timestamp is greater than the current timestamp in milliseconds), then we have encountered # a valid in-progress record. This indicates that another process is currently handling the request, and # to maintain idempotency, we raise an error to prevent concurrent processing of the same request. - if ( - idempotency_record.status == STATUS_CONSTANTS["INPROGRESS"] - and idempotency_record.in_progress_expiry_timestamp - and idempotency_record.in_progress_expiry_timestamp > int(now.timestamp() * 1000) + # + # Without an in-progress expiry, we cannot safely distinguish an active invocation from a timed-out one. + # Fail closed until the record TTL expires, consistent with the DynamoDB persistence layer. + if idempotency_record.status == STATUS_CONSTANTS["INPROGRESS"] and ( + idempotency_record.in_progress_expiry_timestamp is None + or idempotency_record.in_progress_expiry_timestamp > int(now.timestamp() * 1000) ): raise IdempotencyItemAlreadyExistsError diff --git a/tests/functional/idempotency/_redis/test_redis_layer.py b/tests/functional/idempotency/_redis/test_redis_layer.py index 22c3b9a6d83..6adb97a64a4 100644 --- a/tests/functional/idempotency/_redis/test_redis_layer.py +++ b/tests/functional/idempotency/_redis/test_redis_layer.py @@ -3,6 +3,7 @@ import datetime import json import time as t +from threading import Event, Lock as ThreadLock, Thread from unittest import mock import pytest @@ -26,6 +27,7 @@ STATUS_CONSTANTS, DataRecord, ) +from aws_lambda_powertools.utilities.idempotency.persistence.cache import CachePersistenceLayer from aws_lambda_powertools.utilities.idempotency.persistence.redis import ( RedisCachePersistenceLayer, ) @@ -198,6 +200,16 @@ def valid_record(): ) +@pytest.fixture +def in_progress_record_missing_expiry(): + return DataRecord( + idempotency_key="test_orphan_key", + status=STATUS_CONSTANTS["INPROGRESS"], + expiry_timestamp=int(datetime.datetime.now().timestamp()) + 60, + in_progress_expiry_timestamp=None, + ) + + @mock.patch("aws_lambda_powertools.utilities.idempotency.persistence.redis.redis", MockRedis()) def test_redis_connection_standalone(): # when RedisCachePersistenceLayer is init with the following params @@ -303,6 +315,73 @@ def test_redis_orphan_record_lock(orphan_record, valid_record): ) +@mock.patch("aws_lambda_powertools.utilities.idempotency.persistence.redis.redis", MockRedis()) +def test_redis_in_progress_record_missing_expiry_is_not_treated_as_orphan(in_progress_record_missing_expiry): + layer = RedisCachePersistenceLayer(host="host") + layer._put_in_progress_record(in_progress_record_missing_expiry) + + contender = DataRecord( + idempotency_key=in_progress_record_missing_expiry.idempotency_key, + status=STATUS_CONSTANTS["INPROGRESS"], + expiry_timestamp=in_progress_record_missing_expiry.expiry_timestamp + 60, + in_progress_expiry_timestamp=None, + ) + + with pytest.raises(IdempotencyItemAlreadyExistsError): + layer._put_in_progress_record(contender) + + stored_record = layer._get_record(in_progress_record_missing_expiry.idempotency_key) + assert stored_record.status == STATUS_CONSTANTS["INPROGRESS"] + assert stored_record.expiry_timestamp == in_progress_record_missing_expiry.expiry_timestamp + + +@pytest.mark.filterwarnings("ignore:Couldn't determine the remaining time left") +def test_idempotent_function_blocks_concurrent_invocation_without_lambda_context(): + layer = CachePersistenceLayer(client=MockRedis(host="localhost")) + first_invocation_started = Event() + release_first_invocation = Event() + execution_lock = ThreadLock() + execution_count = 0 + first_result = [] + first_errors = [] + + @idempotent_function(data_keyword_argument="record", persistence_store=layer) + def process(record): + nonlocal execution_count + with execution_lock: + execution_count += 1 + current_execution = execution_count + + if current_execution == 1: + first_invocation_started.set() + if not release_first_invocation.wait(timeout=5): + raise TimeoutError("Timed out waiting to release the first invocation") + + return {"execution": current_execution} + + def invoke_first(): + try: + first_result.append(process(record={"id": "same"})) + except Exception as exc: + first_errors.append(exc) + + first_invocation = Thread(target=invoke_first) + first_invocation.start() + assert first_invocation_started.wait(timeout=2) + + try: + with pytest.raises(IdempotencyAlreadyInProgressError): + process(record={"id": "same"}) + finally: + release_first_invocation.set() + first_invocation.join(timeout=5) + + assert not first_invocation.is_alive() + assert first_errors == [] + assert first_result == [{"execution": 1}] + assert execution_count == 1 + + @mock.patch("aws_lambda_powertools.utilities.idempotency.persistence.redis.redis", MockRedis()) def test_redis_error_in_progress(valid_record): layer = RedisCachePersistenceLayer(host="host", mode="standalone")