From 3226c1ba7d3aef48b7129efc14adca61d10e9a0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:12:28 +0100 Subject: [PATCH 01/84] chore(deps): bump requests from 2.32.4 to 2.33.0 in /docs (#8070) Bumps [requests](https://github.com/psf/requests) from 2.32.4 to 2.33.0. - [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.32.4...v2.33.0) --- updated-dependencies: - dependency-name: requests dependency-version: 2.33.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 | 67 ++++++------------------------------------- 1 file changed, 8 insertions(+), 59 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index d1113254b7d..514279c944c 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 docs/requirements.in + # via -r requirements.in mkdocs-llmstxt==0.5.0 \ --hash=sha256:753c699913d2d619a9072604b26b6dc9f5fb6d257d9b107857f80c8a0b787533 \ --hash=sha256:b2fa9e6d68df41d7467e948a4745725b6c99434a36b36204857dbd7bb3dfe041 - # via -r docs/requirements.in + # via -r requirements.in mkdocs-material==9.7.6 \ --hash=sha256:00bdde50574f776d328b1862fe65daeaf581ec309bd150f7bff345a098c64a69 \ --hash=sha256:71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba - # via -r docs/requirements.in + # via -r 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 docs/requirements.in + # via -r requirements.in packaging==25.0 \ --hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \ --hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f @@ -397,9 +397,9 @@ pyyaml-env-tag==1.1 \ --hash=sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 \ --hash=sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff # via mkdocs -requests==2.32.4 \ - --hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \ - --hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422 +requests==2.33.0 \ + --hash=sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b \ + --hash=sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652 # via mkdocs-material six==1.17.0 \ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ @@ -415,61 +415,10 @@ soupsieve==2.7 \ --hash=sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4 \ --hash=sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a # via beautifulsoup4 -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 - # via mdformat typing-extensions==4.14.0 \ --hash=sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4 \ --hash=sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af - # via - # beautifulsoup4 - # mkdocstrings-python + # via beautifulsoup4 urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4 From 78f9cdfc5e3b5f38099abfc0bcb9fd1f3b22afa2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:14:14 +0100 Subject: [PATCH 02/84] chore(deps-dev): bump requests from 2.32.5 to 2.33.0 (#8069) Bumps [requests](https://github.com/psf/requests) from 2.32.5 to 2.33.0. - [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.32.5...v2.33.0) --- updated-dependencies: - dependency-name: requests dependency-version: 2.33.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 242e8d71083..d967ead5c06 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4114,25 +4114,26 @@ files = [ [[package]] name = "requests" -version = "2.32.5" +version = "2.33.0" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, - {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, + {file = "requests-2.33.0-py3-none-any.whl", hash = "sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b"}, + {file = "requests-2.33.0.tar.gz", hash = "sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652"}, ] [package.dependencies] -certifi = ">=2017.4.17" +certifi = ">=2023.5.7" charset_normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +urllib3 = ">=1.26,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +test = ["PySocks (>=1.5.6,!=1.5.7)", "pytest (>=3)", "pytest-cov", "pytest-httpbin (==2.1.0)", "pytest-mock", "pytest-xdist"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] name = "retry2" From 75a187e8c1b4cb638a420bba99aa44efa7731006 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:16:48 +0100 Subject: [PATCH 03/84] chore(deps-dev): bump aws-cdk from 2.1111.0 to 2.1113.0 in the aws-cdk group (#8058) 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.1111.0 to 2.1113.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1113.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1113.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 dfaf20a09cb..c35a27a65c9 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.1111.0" + "aws-cdk": "^2.1115.0" } }, "node_modules/aws-cdk": { - "version": "2.1111.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1111.0.tgz", - "integrity": "sha512-69AVF04cxbAhYzmeJYtUF5bs6ruNnH05EQZJfjadk5Lpg+HVaJY2NjG/2qgsMmKrfRgvLet73Ir8ehVlAaaGng==", + "version": "2.1115.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1115.0.tgz", + "integrity": "sha512-PpNNflDt1L2TxpMh2h7cPHnFkDVeY1hwIxuGuvswS08mA0syOT4OmZx8hZYdcLru6NceCsn0x/7uTHpb6Hzo5A==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 3bccdebc669..6cf64a2b8e6 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.1111.0" + "aws-cdk": "^2.1115.0" } } From eaa1fe6d7643aec070e15176cb85b7948b346dad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:37:12 +0100 Subject: [PATCH 04/84] chore(deps): bump the github-actions group across 1 directory with 10 updates (#8081) * chore(deps): bump the github-actions group across 1 directory with 10 updates Bumps the github-actions group with 10 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/setup-node](https://github.com/actions/setup-node) | `6.2.0` | `6.3.0` | | [aws-powertools/actions](https://github.com/aws-powertools/actions) | `1.5.0` | `1.5.1` | | [actions/setup-go](https://github.com/actions/setup-go) | `6.3.0` | `6.4.0` | | [actions/dependency-review-action](https://github.com/actions/dependency-review-action) | `4.8.3` | `4.9.0` | | [actions/download-artifact](https://github.com/actions/download-artifact) | `8.0.0` | `8.0.1` | | [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `3.7.0` | `4.0.0` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.12.0` | `4.0.0` | | [codecov/codecov-action](https://github.com/codecov/codecov-action) | `5.5.2` | `6.0.0` | | [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) | `6.2.0` | `7.1.1` | | [zgosalvez/github-actions-ensure-sha-pinned-actions](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions) | `5.0.1` | `5.0.4` | Updates `actions/setup-node` from 6.2.0 to 6.3.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/6044e13b5dc448c55e2357c09f80417699197238...53b83947a5a98c8d113130e565377fae1a50d02f) Updates `aws-powertools/actions` from 1.5.0 to 1.5.1 - [Release notes](https://github.com/aws-powertools/actions/releases) - [Commits](https://github.com/aws-powertools/actions/compare/3b5b8e2e58b7af07994be982e83584a94e8c76c5...828e78a26eee3554dc2e1d96048004548fbb169f) Updates `actions/setup-go` from 6.3.0 to 6.4.0 - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/4b73464bb391d4059bd26b0524d20df3927bd417...4a3601121dd01d1626a1e23e37211e3254c1c06c) Updates `actions/dependency-review-action` from 4.8.3 to 4.9.0 - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/05fe4576374b728f0c523d6a13d64c25081e0803...2031cfc080254a8a887f58cffee85186f0e49e48) Updates `actions/download-artifact` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c) Updates `docker/setup-qemu-action` from 3.7.0 to 4.0.0 - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/c7c53464625b32c7a7e944ae62b3e17d2b600130...ce360397dd3f832beb865e1373c09c0e9f86d70a) Updates `docker/setup-buildx-action` from 3.12.0 to 4.0.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/8d2750c68a42422c14e847fe6c8ac0403b4cbd6f...4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd) Updates `codecov/codecov-action` from 5.5.2 to 6.0.0 - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/671740ac38dd9b0130fbe1cec585b89eea48d3de...57e3a136b779b570ffcdbf80b3bdc90e7fab3de2) Updates `release-drafter/release-drafter` from 6.2.0 to 7.1.1 - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/6db134d15f3909ccc9eefd369f02bd1e9cffdf97...139054aeaa9adc52ab36ddf67437541f039b88e2) Updates `zgosalvez/github-actions-ensure-sha-pinned-actions` from 5.0.1 to 5.0.4 - [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/70c4af2ed5282c51ba40566d026d6647852ffa3e...ca46236c6ce584ae24bc6283ba8dcf4b3ec8a066) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: aws-powertools/actions dependency-version: 1.5.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/setup-go dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/dependency-review-action dependency-version: 4.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/download-artifact dependency-version: 8.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: docker/setup-qemu-action dependency-version: 4.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: docker/setup-buildx-action dependency-version: 4.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: codecov/codecov-action dependency-version: 6.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.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: zgosalvez/github-actions-ensure-sha-pinned-actions dependency-version: 5.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] * Fix actions braking changes --------- 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/dependency-review.yml | 2 +- .github/workflows/layer_govcloud.yml | 8 ++++---- .github/workflows/layer_govcloud_python313.yml | 8 ++++---- .github/workflows/layers_partition_verify.yml | 2 +- .github/workflows/layers_partitions.yml | 4 ++-- .github/workflows/pre-release.yml | 2 +- .github/workflows/publish_v3_layer.yml | 9 +++++---- .github/workflows/quality_check.yml | 2 +- .github/workflows/quality_code_cdk_constructor.yml | 7 ++++--- .github/workflows/release-drafter.yml | 4 +--- .github/workflows/reusable_deploy_v3_layer_stack.yml | 4 ++-- .github/workflows/reusable_deploy_v3_sar.yml | 4 ++-- .github/workflows/run-e2e-tests.yml | 2 +- .github/workflows/secure_workflows.yml | 2 +- layer_v3/layer_constructors/layer_stack.py | 1 + 16 files changed, 34 insertions(+), 33 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index b46c4020c0c..f7964960315 100644 --- a/.github/workflows/bootstrap_region.yml +++ b/.github/workflows/bootstrap_region.yml @@ -48,11 +48,11 @@ jobs: with: ref: ${{ github.sha }} - name: Setup Node.js - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: "22" - name: Setup dependencies - uses: aws-powertools/actions/.github/actions/cached-node-modules@3b5b8e2e58b7af07994be982e83584a94e8c76c5 + uses: aws-powertools/actions/.github/actions/cached-node-modules@828e78a26eee3554dc2e1d96048004548fbb169f - id: credentials name: AWS Credentials uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 @@ -103,7 +103,7 @@ jobs: mask-aws-account-id: true - id: go-setup name: Setup Go - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version: '>=1.23.0' - id: go-env diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 62612b20fa7..86dc50dd0eb 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -22,4 +22,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@05fe4576374b728f0c523d6a13d64c25081e0803 # v4.8.3 + uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 diff --git a/.github/workflows/layer_govcloud.yml b/.github/workflows/layer_govcloud.yml index aacdd4399a9..6106e538a09 100644 --- a/.github/workflows/layer_govcloud.yml +++ b/.github/workflows/layer_govcloud.yml @@ -106,11 +106,11 @@ jobs: environment: GovCloud ${{ inputs.environment }} (East) steps: - name: Download Zip - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.zip - name: Download Metadata - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.json - name: Verify Layer Signature @@ -176,11 +176,11 @@ jobs: name: GovCloud ${{ inputs.environment }} (West) steps: - name: Download Zip - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.zip - name: Download Metadata - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.json - name: Verify Layer Signature diff --git a/.github/workflows/layer_govcloud_python313.yml b/.github/workflows/layer_govcloud_python313.yml index 88cbd692333..c55c3123f3e 100644 --- a/.github/workflows/layer_govcloud_python313.yml +++ b/.github/workflows/layer_govcloud_python313.yml @@ -96,11 +96,11 @@ jobs: environment: GovCloud ${{ inputs.environment }} (East) steps: - name: Download Zip - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.zip - name: Download Metadata - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.json - name: Verify Layer Signature @@ -161,11 +161,11 @@ jobs: name: GovCloud ${{ inputs.environment }} (West) steps: - name: Download Zip - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.zip - name: Download Metadata - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.json - name: Verify Layer Signature diff --git a/.github/workflows/layers_partition_verify.yml b/.github/workflows/layers_partition_verify.yml index 4b06da595ee..acac8bbeceb 100644 --- a/.github/workflows/layers_partition_verify.yml +++ b/.github/workflows/layers_partition_verify.yml @@ -131,7 +131,7 @@ jobs: - x86_64 steps: - name: Download Metadata - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}-${{ matrix.arch }}.json - id: transform diff --git a/.github/workflows/layers_partitions.yml b/.github/workflows/layers_partitions.yml index 5c7560525fe..2da5ec66e38 100644 --- a/.github/workflows/layers_partitions.yml +++ b/.github/workflows/layers_partitions.yml @@ -135,11 +135,11 @@ jobs: - x86_64 steps: - name: Download Zip - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}-${{ matrix.arch }}.zip - name: Download Metadata - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ matrix.layer }}-${{ matrix.arch }}.json - name: Verify Layer Signature diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index c8889221bca..f638a77e62d 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -244,7 +244,7 @@ jobs: artifact_name: ${{ needs.seal.outputs.artifact_name }} - name: Download provenance - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{needs.provenance.outputs.provenance-name}} diff --git a/.github/workflows/publish_v3_layer.yml b/.github/workflows/publish_v3_layer.yml index a1ac4e57208..a4884039c5e 100644 --- a/.github/workflows/publish_v3_layer.yml +++ b/.github/workflows/publish_v3_layer.yml @@ -123,7 +123,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: Setup Node.js - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: "18.20.4" - name: Setup python @@ -139,16 +139,15 @@ jobs: pip install --require-hashes -r requirements.txt - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v2.0.0 + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.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@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 with: - install: true driver: docker platforms: linux/amd64,linux/arm64 @@ -165,6 +164,8 @@ jobs: - name: CDK build run: npx cdk synth --verbose --context version="${{ inputs.latest_published_version }}" --context pythonVersion="python${{ matrix.python-version }}" -o cdk.out + env: + BUILDX_BUILDER: ${{ steps.builder.outputs.name }} - name: zip output run: zip -r cdk.py${{ matrix.python-version }}.out.zip cdk.out - name: Archive CDK artifacts diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml index f1213e7a351..19dcb626f41 100644 --- a/.github/workflows/quality_check.yml +++ b/.github/workflows/quality_check.yml @@ -78,7 +78,7 @@ jobs: - name: Complexity baseline run: make complexity-baseline - name: Upload coverage to Codecov - uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # 5.5.2 + uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # 6.0.0 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./coverage.xml diff --git a/.github/workflows/quality_code_cdk_constructor.yml b/.github/workflows/quality_code_cdk_constructor.yml index e6f2f431c8f..497d0bea446 100644 --- a/.github/workflows/quality_code_cdk_constructor.yml +++ b/.github/workflows/quality_code_cdk_constructor.yml @@ -51,15 +51,14 @@ jobs: python-version: ${{ matrix.python-version }} cache: "poetry" - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v2.0.0 + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.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@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 with: - install: true driver: docker platforms: linux/amd64,linux/arm64 - name: Install dependencies @@ -68,3 +67,5 @@ jobs: poetry install - name: Test with pytest run: poetry run pytest tests + env: + BUILDX_BUILDER: ${{ steps.builder.outputs.name }} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 4f70494ec37..6e13b235559 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -27,6 +27,4 @@ jobs: permissions: contents: write # create release in draft mode steps: - - uses: release-drafter/release-drafter@6db134d15f3909ccc9eefd369f02bd1e9cffdf97 # v5.20.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: release-drafter/release-drafter@139054aeaa9adc52ab36ddf67437541f039b88e2 # v7.1.1 diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index d657f891644..b760b71b40c 100644 --- a/.github/workflows/reusable_deploy_v3_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v3_layer_stack.yml @@ -165,7 +165,7 @@ jobs: role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} mask-aws-account-id: true - name: Setup Node.js - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: "18.20.4" - name: Setup python @@ -187,7 +187,7 @@ jobs: - name: install deps run: poetry install - name: Download artifact - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: cdk-layer-artifact-py${{ matrix.python-version }} path: layer_v3 diff --git a/.github/workflows/reusable_deploy_v3_sar.yml b/.github/workflows/reusable_deploy_v3_sar.yml index 3d6f302e260..6b76d27578e 100644 --- a/.github/workflows/reusable_deploy_v3_sar.yml +++ b/.github/workflows/reusable_deploy_v3_sar.yml @@ -109,11 +109,11 @@ jobs: role-to-assume: ${{ secrets.AWS_SAR_V3_ROLE_ARN }} mask-aws-account-id: true - name: Setup Node.js - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ env.NODE_VERSION }} - name: Download artifact - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: cdk-layer-artifact-py${{ matrix.python-version }} - name: Unzip artefact diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 17d2c8637ea..812148974fc 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -62,7 +62,7 @@ jobs: architecture: "x64" cache: "poetry" - name: Setup Node.js - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: "20.10.0" - name: Install CDK CLI diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index e087b98fa5c..e2f187a40f2 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Ensure 3rd party workflows have SHA pinned - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@70c4af2ed5282c51ba40566d026d6647852ffa3e # v5.0.1 + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@ca46236c6ce584ae24bc6283ba8dcf4b3ec8a066 # v5.0.4 with: allowlist: | slsa-framework/slsa-github-generator diff --git a/layer_v3/layer_constructors/layer_stack.py b/layer_v3/layer_constructors/layer_stack.py index a718fba5e9a..66e03b82218 100644 --- a/layer_v3/layer_constructors/layer_stack.py +++ b/layer_v3/layer_constructors/layer_stack.py @@ -1,5 +1,6 @@ from __future__ import annotations +# trigger CI: validate docker/setup-buildx-action v4 compatibility from pathlib import Path from typing import TYPE_CHECKING From a03daf5a521dd779899aee315bd30283a81fd060 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:39:30 +0100 Subject: [PATCH 05/84] chore(deps): bump cryptography from 46.0.5 to 46.0.6 (#8072) Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.5 to 46.0.6. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/46.0.5...46.0.6) --- updated-dependencies: - dependency-name: cryptography dependency-version: 46.0.6 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 | 107 ++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/poetry.lock b/poetry.lock index d967ead5c06..dc65e9dec5a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1037,6 +1037,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"}, @@ -1123,7 +1124,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\""} @@ -1464,63 +1464,62 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" -version = "46.0.5" +version = "46.0.6" 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" groups = ["main", "dev"] files = [ - {file = "cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731"}, - {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82"}, - {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1"}, - {file = "cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48"}, - {file = "cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4"}, - {file = "cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663"}, - {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826"}, - {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d"}, - {file = "cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a"}, - {file = "cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4"}, - {file = "cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c"}, - {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4"}, - {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9"}, - {file = "cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72"}, - {file = "cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7"}, - {file = "cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d"}, + {file = "cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19"}, + {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738"}, + {file = "cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c"}, + {file = "cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f"}, + {file = "cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2"}, + {file = "cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124"}, + {file = "cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4"}, + {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a"}, + {file = "cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d"}, + {file = "cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736"}, + {file = "cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed"}, + {file = "cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4"}, + {file = "cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa"}, + {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58"}, + {file = "cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb"}, + {file = "cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72"}, + {file = "cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c"}, + {file = "cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f"}, + {file = "cryptography-46.0.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead"}, + {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8"}, + {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0"}, + {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b"}, + {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a"}, + {file = "cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e"}, + {file = "cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759"}, ] -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\""} @@ -1533,7 +1532,7 @@ 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.5)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test = ["certifi (>=2024)", "cryptography-vectors (==46.0.6)", "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]] @@ -3385,11 +3384,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 9e2a1ece560ec36478198356759e6019703b29f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:41:19 +0100 Subject: [PATCH 06/84] chore(deps-dev): bump sentry-sdk from 2.54.0 to 2.56.0 (#8082) Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.54.0 to 2.56.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.54.0...2.56.0) --- updated-dependencies: - dependency-name: sentry-sdk dependency-version: 2.56.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 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index dc65e9dec5a..6890d4ce252 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4357,14 +4357,14 @@ pathspec = ">=0.10.1" [[package]] name = "sentry-sdk" -version = "2.54.0" +version = "2.57.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "sentry_sdk-2.54.0-py2.py3-none-any.whl", hash = "sha256:fd74e0e281dcda63afff095d23ebcd6e97006102cdc8e78a29f19ecdf796a0de"}, - {file = "sentry_sdk-2.54.0.tar.gz", hash = "sha256:2620c2575128d009b11b20f7feb81e4e4e8ae08ec1d36cbc845705060b45cc1b"}, + {file = "sentry_sdk-2.57.0-py2.py3-none-any.whl", hash = "sha256:812c8bf5ff3d2f0e89c82f5ce80ab3a6423e102729c4706af7413fd1eb480585"}, + {file = "sentry_sdk-2.57.0.tar.gz", hash = "sha256:4be8d1e71c32fb27f79c577a337ac8912137bba4bcbc64a4ec1da4d6d8dc5199"}, ] [package.dependencies] @@ -4375,6 +4375,7 @@ urllib3 = ">=1.26.11" aiohttp = ["aiohttp (>=3.5)"] anthropic = ["anthropic (>=0.16)"] arq = ["arq (>=0.23)"] +asyncio = ["httpcore[asyncio] (==1.*)"] asyncpg = ["asyncpg (>=0.23)"] beam = ["apache-beam (>=2.12)"] bottle = ["bottle (>=0.12.13)"] @@ -4395,7 +4396,7 @@ huggingface-hub = ["huggingface_hub (>=0.22)"] langchain = ["langchain (>=0.0.210)"] langgraph = ["langgraph (>=0.6.6)"] launchdarkly = ["launchdarkly-server-sdk (>=9.8.0)"] -litellm = ["litellm (>=1.77.5)"] +litellm = ["litellm (>=1.77.5,!=1.82.7,!=1.82.8)"] litestar = ["litestar (>=2.0.0)"] loguru = ["loguru (>=0.5)"] mcp = ["mcp (>=1.15.0)"] From 7f18ddbffe51c726e61beb0393ab276e9c9bb12f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:43:55 +0100 Subject: [PATCH 07/84] chore(deps): bump valkey-glide from 2.2.7 to 2.3.0 (#8080) Bumps [valkey-glide](https://github.com/valkey-io/valkey-glide) from 2.2.7 to 2.3.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.2.7...v2.3.0) --- updated-dependencies: - dependency-name: valkey-glide dependency-version: 2.3.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 | 81 +++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6890d4ce252..342b087e35e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1037,7 +1037,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"}, @@ -1124,6 +1123,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 = "platform_python_implementation != \"PyPy\" and (extra == \"all\" or extra == \"datamasking\")", dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1520,6 +1520,7 @@ files = [ {file = "cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e"}, {file = "cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759"}, ] +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\""} @@ -3384,11 +3385,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" @@ -4913,50 +4914,50 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "valkey-glide" -version = "2.2.7" +version = "2.3.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.2.7-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:701b6ee036a54598ba63d7e6ecdee8f6ddd5b460cef67491f29414447deb7407"}, - {file = "valkey_glide-2.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:556dd3a906f61ff2d53f540fa782eee5c67a2048ed434f87089bb4f62cbd2564"}, - {file = "valkey_glide-2.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6622536445b7c78ae3f0f497ae449efac6a627f7c607b92c9ef934c5dd046c4b"}, - {file = "valkey_glide-2.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9bd390f66dc324ce3e937a6ac7592bfbd4e6cf9eb5d4c28838fc766645f149b"}, - {file = "valkey_glide-2.2.7-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e39a1db18d08f5a9995d87158b070af1a625a612dc7e57e27a9becee40f6144c"}, - {file = "valkey_glide-2.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:180aa1ee0cdfbcf34ae7322838fd063a720a6dae9e97a8e9462b8a12b1f65138"}, - {file = "valkey_glide-2.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44a9a6e85e8320220604468c35e0a84bea392dddbab2dcdf9cce9ece01b4a041"}, - {file = "valkey_glide-2.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7905c5f3efb67058c5f52b7906aa2d114288eff4aa76a5379107b312af6b8ec8"}, - {file = "valkey_glide-2.2.7-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:4db4ff570c0a63cc8a4551b780dd00069d61c8841a6e6eeaf2dda05d89ec0221"}, - {file = "valkey_glide-2.2.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f5ebe701f18b22d331a12af120e1250927391665b66fd78c273d563b2523c6"}, - {file = "valkey_glide-2.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca7aab86a175c678bb0573db29050d49d692adcf87c7dd01e2ff9da94bdac68f"}, - {file = "valkey_glide-2.2.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c81c7cb8bbae7a75c3efcfe9b05ebd97db6f332128606e5464e518ba5a7b8e02"}, - {file = "valkey_glide-2.2.7-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:1d40da535a77ce318367ac255b1d5de95cf0ca669b8cac79a158f678feed9fb3"}, - {file = "valkey_glide-2.2.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f435ed9c14d7de72df04322300034931aba528d1183770b2f7624dd8fc18d7c"}, - {file = "valkey_glide-2.2.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cad26daa0775ab6dd7ad5a1d8300c4b97ed4b39401c1f130200456f9f9b5234"}, - {file = "valkey_glide-2.2.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:340a9bdf31e811121e9ea7d95cb75161125c78690334581d4be08aae9c824f29"}, - {file = "valkey_glide-2.2.7-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:085c81403600555a7672cf45d68f2c786d1fac12d5759d8e6e3a3f7d5a79d8b7"}, - {file = "valkey_glide-2.2.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d2470a704f463600a0c12000b48adbcc888210be38fbb39fd33c7f36fe84bd66"}, - {file = "valkey_glide-2.2.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d1985f7c579c7b37bf7fc42125b141295dded29257d7b811d318bb5343343c8"}, - {file = "valkey_glide-2.2.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba5149f2019164024958778e5b314f05dc61187731e2c23411498cb884a9181b"}, - {file = "valkey_glide-2.2.7-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:20b586d2702a71cd90bb7c85380155f92585129f9534396450e2a64896e5b00c"}, - {file = "valkey_glide-2.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8316673b56632ae92b4cf22a990b8fc510fe87cbb29d3aac242496cf7a44d96c"}, - {file = "valkey_glide-2.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3c5ae19adbb299c212c0011c1934ea3769b1dc364126a6fb5b443842678c2ec"}, - {file = "valkey_glide-2.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec85da03bd00402df90152c5e647cade29c0e539311839c844e135e945f84dbc"}, - {file = "valkey_glide-2.2.7-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:47949c900e08de0e64fb5b59abfa069e09a62a9a4db2ba6756ca3a6b440f012a"}, - {file = "valkey_glide-2.2.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8d6ba5b86d8910545dcd8429807780bae705def558ce38ca8f2a10ee13aa7021"}, - {file = "valkey_glide-2.2.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ce02ce683b42687b72fc21a70b7dfe3597c79cb1594c6e707b464fa37e8f3a3"}, - {file = "valkey_glide-2.2.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02900b8e6ea539a5a158c0a74e63d92043b4487dd43f33cc1b0bb03a0aeac0"}, - {file = "valkey_glide-2.2.7-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:33e6a21430580499943f29d30c3d74bc9b53f421bb76ea190e43cead428fc832"}, - {file = "valkey_glide-2.2.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c2eff5bf9e30bb2e2efb4bad09ecf2568a7ca722e39b37f8a10d5244a512b3a"}, - {file = "valkey_glide-2.2.7-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:589e52f909bc7e7736e35af6e4b3d91e7dfcbf26b3bf13fca79668ad633d9ed4"}, - {file = "valkey_glide-2.2.7-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8c9beaff220439b10906e8b84c5a141d4b6515ea28db38f076191777e26c05"}, - {file = "valkey_glide-2.2.7-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:1e353efd6b7d6b511be246e0376be0176869b2a7bde4ba7c4d8d0e25c3bda07b"}, - {file = "valkey_glide-2.2.7-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ba90316717570f550ffbacdad36bc023ca404468c35c997f2ee4bbd8b1cbb634"}, - {file = "valkey_glide-2.2.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:170ab03fa9fb958bb1c9ed467a4e173444d7b23886d5be01b8719d7c4d8ced8d"}, - {file = "valkey_glide-2.2.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6b1ad67ff44d23850713c10191a701c19b8bd4d800ca3ef1a442267563ad92f"}, - {file = "valkey_glide-2.2.7.tar.gz", hash = "sha256:2cd05b8c871c7878cb89679ac34f294f100481b64f79d797cde325a1d051cdc9"}, + {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"}, ] [package.dependencies] From 234c88202a0769d207e0b18cf7877e28d6a1ddc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:46:22 +0100 Subject: [PATCH 08/84] chore(deps): bump mkdocs-material from 9.7.5 to 9.7.6 (#8079) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.7.5 to 9.7.6. - [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.5...9.7.6) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.7.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> Co-authored-by: Leandro Damascena --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 342b087e35e..46b706a510a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2780,14 +2780,14 @@ mdformat = ">=0.7.21" [[package]] name = "mkdocs-material" -version = "9.7.5" +version = "9.7.6" description = "Documentation that simply works" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "mkdocs_material-9.7.5-py3-none-any.whl", hash = "sha256:7cf9df2ff121fd098ff6e05c732b0be3699afca9642e2dfe4926c40eb5873eec"}, - {file = "mkdocs_material-9.7.5.tar.gz", hash = "sha256:f76bdab532bad1d9c57ca7187b37eccf64dd12e1586909307f8856db3be384ea"}, + {file = "mkdocs_material-9.7.6-py3-none-any.whl", hash = "sha256:71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba"}, + {file = "mkdocs_material-9.7.6.tar.gz", hash = "sha256:00bdde50574f776d328b1862fe65daeaf581ec309bd150f7bff345a098c64a69"}, ] [package.dependencies] From 4646da66c890a531c7247628f869c0bfaafcb7fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 12:17:56 +0100 Subject: [PATCH 09/84] chore(deps-dev): bump the dev-dependencies group across 1 directory with 4 updates (#8086) * chore(deps-dev): bump the dev-dependencies group across 1 directory with 4 updates Bumps the dev-dependencies group with 4 updates in the / directory: [coverage](https://github.com/coveragepy/coveragepy), [pytest-cov](https://github.com/pytest-dev/pytest-cov), [mypy](https://github.com/python/mypy) and [ruff](https://github.com/astral-sh/ruff). Updates `coverage` from 7.13.4 to 7.13.5 - [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.13.4...7.13.5) Updates `pytest-cov` from 7.0.0 to 7.1.0 - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v7.0.0...v7.1.0) Updates `mypy` from 1.19.1 to 1.20.0 - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.19.1...v1.20.0) Updates `ruff` from 0.14.14 to 0.15.8 - [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.14.14...0.15.8) --- updated-dependencies: - dependency-name: coverage dependency-version: 7.13.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: pytest-cov dependency-version: 7.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: mypy dependency-version: 1.20.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: ruff dependency-version: 0.15.8 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] * Fix actions braking changes --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .../utilities/data_masking/base.py | 2 +- .../utilities/feature_flags/feature_flags.py | 16 +- .../utilities/idempotency/persistence/base.py | 5 +- .../utilities/parameters/base.py | 2 +- poetry.lock | 352 +++++++++--------- pyproject.toml | 2 +- 6 files changed, 194 insertions(+), 185 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_masking/base.py b/aws_lambda_powertools/utilities/data_masking/base.py index 0c58ee2a861..f76f990b842 100644 --- a/aws_lambda_powertools/utilities/data_masking/base.py +++ b/aws_lambda_powertools/utilities/data_masking/base.py @@ -406,7 +406,7 @@ def _apply_action_to_fields( json_parse.update( data_parsed, - lambda field_value, fields, field_name: update_callback(field_value, fields, field_name), # type: ignore[misc] # noqa: B023 + update_callback, # type: ignore[misc] # noqa: B023 ) return data_parsed diff --git a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py index d62dbfc625f..1dfe89a40f7 100644 --- a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +++ b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py @@ -23,7 +23,7 @@ from aws_lambda_powertools.utilities.feature_flags.types import JSONType, P, T -RULE_ACTION_MAPPING = { +RULE_ACTION_MAPPING: dict[str, Callable[..., bool]] = { schema.RuleAction.EQUALS.value: lambda a, b: a == b, schema.RuleAction.NOT_EQUALS.value: lambda a, b: a != b, schema.RuleAction.KEY_GREATER_THAN_VALUE.value: lambda a, b: a > b, @@ -38,13 +38,13 @@ schema.RuleAction.KEY_NOT_IN_VALUE.value: lambda a, b: a not in b, schema.RuleAction.VALUE_IN_KEY.value: lambda a, b: b in a, schema.RuleAction.VALUE_NOT_IN_KEY.value: lambda a, b: b not in a, - schema.RuleAction.ALL_IN_VALUE.value: lambda a, b: compare_all_in_list(a, b), - schema.RuleAction.ANY_IN_VALUE.value: lambda a, b: compare_any_in_list(a, b), - schema.RuleAction.NONE_IN_VALUE.value: lambda a, b: compare_none_in_list(a, b), - schema.RuleAction.SCHEDULE_BETWEEN_TIME_RANGE.value: lambda a, b: compare_time_range(a, b), - schema.RuleAction.SCHEDULE_BETWEEN_DATETIME_RANGE.value: lambda a, b: compare_datetime_range(a, b), - schema.RuleAction.SCHEDULE_BETWEEN_DAYS_OF_WEEK.value: lambda a, b: compare_days_of_week(a, b), - schema.RuleAction.MODULO_RANGE.value: lambda a, b: compare_modulo_range(a, b), + schema.RuleAction.ALL_IN_VALUE.value: compare_all_in_list, + schema.RuleAction.ANY_IN_VALUE.value: compare_any_in_list, + schema.RuleAction.NONE_IN_VALUE.value: compare_none_in_list, + schema.RuleAction.SCHEDULE_BETWEEN_TIME_RANGE.value: compare_time_range, + schema.RuleAction.SCHEDULE_BETWEEN_DATETIME_RANGE.value: compare_datetime_range, + schema.RuleAction.SCHEDULE_BETWEEN_DAYS_OF_WEEK.value: compare_days_of_week, + schema.RuleAction.MODULO_RANGE.value: compare_modulo_range, } diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/base.py b/aws_lambda_powertools/utilities/idempotency/persistence/base.py index 2803e6f0f3a..3d54a01f018 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/base.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/base.py @@ -111,7 +111,10 @@ def _get_hashed_idempotency_key(self, data: dict[str, Any]) -> str | None: """ if self.event_key_jmespath: - data = self.event_key_compiled_jmespath.search(data, options=jmespath.Options(**self.jmespath_options)) + data = self.event_key_compiled_jmespath.search( + data, + options=jmespath.Options(**(self.jmespath_options or {})), + ) if self.is_missing_idempotency_key(data=data): if self.raise_on_no_idempotency_key: diff --git a/aws_lambda_powertools/utilities/parameters/base.py b/aws_lambda_powertools/utilities/parameters/base.py index 2daf4bb5642..99475edb3ea 100644 --- a/aws_lambda_powertools/utilities/parameters/base.py +++ b/aws_lambda_powertools/utilities/parameters/base.py @@ -271,7 +271,7 @@ def get_transform_method(value: str, transform: TransformOptions = None) -> Call transform_method = TRANSFORM_METHOD_MAPPING.get(transform) if transform == "auto": - key_suffix = value.rsplit(".")[-1] + key_suffix = value.rsplit(".", maxsplit=1)[-1] transform_method = TRANSFORM_METHOD_MAPPING.get(key_suffix, TRANSFORM_METHOD_MAPPING[None]) return cast(Callable, transform_method) # https://github.com/python/mypy/issues/10740 diff --git a/poetry.lock b/poetry.lock index 46b706a510a..2ebdcc258e8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1342,118 +1342,118 @@ typeguard = "2.13.3" [[package]] name = "coverage" -version = "7.13.4" +version = "7.13.5" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "coverage-7.13.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415"}, - {file = "coverage-7.13.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b"}, - {file = "coverage-7.13.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a"}, - {file = "coverage-7.13.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f"}, - {file = "coverage-7.13.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012"}, - {file = "coverage-7.13.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def"}, - {file = "coverage-7.13.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256"}, - {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda"}, - {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92"}, - {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c"}, - {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58"}, - {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9"}, - {file = "coverage-7.13.4-cp310-cp310-win32.whl", hash = "sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf"}, - {file = "coverage-7.13.4-cp310-cp310-win_amd64.whl", hash = "sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95"}, - {file = "coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053"}, - {file = "coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11"}, - {file = "coverage-7.13.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa"}, - {file = "coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7"}, - {file = "coverage-7.13.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00"}, - {file = "coverage-7.13.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef"}, - {file = "coverage-7.13.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903"}, - {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f"}, - {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299"}, - {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505"}, - {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6"}, - {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9"}, - {file = "coverage-7.13.4-cp311-cp311-win32.whl", hash = "sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9"}, - {file = "coverage-7.13.4-cp311-cp311-win_amd64.whl", hash = "sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f"}, - {file = "coverage-7.13.4-cp311-cp311-win_arm64.whl", hash = "sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f"}, - {file = "coverage-7.13.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459"}, - {file = "coverage-7.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3"}, - {file = "coverage-7.13.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634"}, - {file = "coverage-7.13.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3"}, - {file = "coverage-7.13.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa"}, - {file = "coverage-7.13.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3"}, - {file = "coverage-7.13.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a"}, - {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7"}, - {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc"}, - {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47"}, - {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985"}, - {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0"}, - {file = "coverage-7.13.4-cp312-cp312-win32.whl", hash = "sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246"}, - {file = "coverage-7.13.4-cp312-cp312-win_amd64.whl", hash = "sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126"}, - {file = "coverage-7.13.4-cp312-cp312-win_arm64.whl", hash = "sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d"}, - {file = "coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9"}, - {file = "coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac"}, - {file = "coverage-7.13.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea"}, - {file = "coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b"}, - {file = "coverage-7.13.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525"}, - {file = "coverage-7.13.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242"}, - {file = "coverage-7.13.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148"}, - {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a"}, - {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23"}, - {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80"}, - {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea"}, - {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a"}, - {file = "coverage-7.13.4-cp313-cp313-win32.whl", hash = "sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d"}, - {file = "coverage-7.13.4-cp313-cp313-win_amd64.whl", hash = "sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd"}, - {file = "coverage-7.13.4-cp313-cp313-win_arm64.whl", hash = "sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af"}, - {file = "coverage-7.13.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d"}, - {file = "coverage-7.13.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12"}, - {file = "coverage-7.13.4-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b"}, - {file = "coverage-7.13.4-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9"}, - {file = "coverage-7.13.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092"}, - {file = "coverage-7.13.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9"}, - {file = "coverage-7.13.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26"}, - {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2"}, - {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940"}, - {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c"}, - {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0"}, - {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b"}, - {file = "coverage-7.13.4-cp313-cp313t-win32.whl", hash = "sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9"}, - {file = "coverage-7.13.4-cp313-cp313t-win_amd64.whl", hash = "sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd"}, - {file = "coverage-7.13.4-cp313-cp313t-win_arm64.whl", hash = "sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997"}, - {file = "coverage-7.13.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601"}, - {file = "coverage-7.13.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689"}, - {file = "coverage-7.13.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c"}, - {file = "coverage-7.13.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129"}, - {file = "coverage-7.13.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552"}, - {file = "coverage-7.13.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a"}, - {file = "coverage-7.13.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356"}, - {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71"}, - {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5"}, - {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98"}, - {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5"}, - {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0"}, - {file = "coverage-7.13.4-cp314-cp314-win32.whl", hash = "sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb"}, - {file = "coverage-7.13.4-cp314-cp314-win_amd64.whl", hash = "sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505"}, - {file = "coverage-7.13.4-cp314-cp314-win_arm64.whl", hash = "sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2"}, - {file = "coverage-7.13.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056"}, - {file = "coverage-7.13.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc"}, - {file = "coverage-7.13.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9"}, - {file = "coverage-7.13.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf"}, - {file = "coverage-7.13.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55"}, - {file = "coverage-7.13.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72"}, - {file = "coverage-7.13.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a"}, - {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6"}, - {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3"}, - {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750"}, - {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39"}, - {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0"}, - {file = "coverage-7.13.4-cp314-cp314t-win32.whl", hash = "sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea"}, - {file = "coverage-7.13.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932"}, - {file = "coverage-7.13.4-cp314-cp314t-win_arm64.whl", hash = "sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b"}, - {file = "coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0"}, - {file = "coverage-7.13.4.tar.gz", hash = "sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91"}, + {file = "coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5"}, + {file = "coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0"}, + {file = "coverage-7.13.5-cp310-cp310-win32.whl", hash = "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58"}, + {file = "coverage-7.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e"}, + {file = "coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d"}, + {file = "coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8"}, + {file = "coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf"}, + {file = "coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9"}, + {file = "coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028"}, + {file = "coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01"}, + {file = "coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c"}, + {file = "coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf"}, + {file = "coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810"}, + {file = "coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de"}, + {file = "coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1"}, + {file = "coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17"}, + {file = "coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85"}, + {file = "coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b"}, + {file = "coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664"}, + {file = "coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d"}, + {file = "coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2"}, + {file = "coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a"}, + {file = "coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819"}, + {file = "coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911"}, + {file = "coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f"}, + {file = "coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0"}, + {file = "coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc"}, + {file = "coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633"}, + {file = "coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8"}, + {file = "coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b"}, + {file = "coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a"}, + {file = "coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215"}, + {file = "coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43"}, + {file = "coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45"}, + {file = "coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61"}, + {file = "coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179"}, ] [package.dependencies] @@ -2912,56 +2912,62 @@ dill = ">=0.4.1" [[package]] name = "mypy" -version = "1.19.1" +version = "1.20.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec"}, - {file = "mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b"}, - {file = "mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6"}, - {file = "mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74"}, - {file = "mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1"}, - {file = "mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac"}, - {file = "mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288"}, - {file = "mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab"}, - {file = "mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6"}, - {file = "mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331"}, - {file = "mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925"}, - {file = "mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042"}, - {file = "mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1"}, - {file = "mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e"}, - {file = "mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2"}, - {file = "mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8"}, - {file = "mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a"}, - {file = "mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13"}, - {file = "mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250"}, - {file = "mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b"}, - {file = "mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e"}, - {file = "mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef"}, - {file = "mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75"}, - {file = "mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd"}, - {file = "mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1"}, - {file = "mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718"}, - {file = "mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b"}, - {file = "mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045"}, - {file = "mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957"}, - {file = "mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f"}, - {file = "mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3"}, - {file = "mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a"}, - {file = "mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67"}, - {file = "mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e"}, - {file = "mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376"}, - {file = "mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24"}, - {file = "mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247"}, - {file = "mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba"}, + {file = "mypy-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8"}, + {file = "mypy-1.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a"}, + {file = "mypy-1.20.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865"}, + {file = "mypy-1.20.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca"}, + {file = "mypy-1.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018"}, + {file = "mypy-1.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13"}, + {file = "mypy-1.20.0-cp310-cp310-win_arm64.whl", hash = "sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281"}, + {file = "mypy-1.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b"}, + {file = "mypy-1.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367"}, + {file = "mypy-1.20.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62"}, + {file = "mypy-1.20.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0"}, + {file = "mypy-1.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f"}, + {file = "mypy-1.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e"}, + {file = "mypy-1.20.0-cp311-cp311-win_arm64.whl", hash = "sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442"}, + {file = "mypy-1.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214"}, + {file = "mypy-1.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e"}, + {file = "mypy-1.20.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651"}, + {file = "mypy-1.20.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5"}, + {file = "mypy-1.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78"}, + {file = "mypy-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489"}, + {file = "mypy-1.20.0-cp312-cp312-win_arm64.whl", hash = "sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33"}, + {file = "mypy-1.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134"}, + {file = "mypy-1.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c"}, + {file = "mypy-1.20.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe"}, + {file = "mypy-1.20.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f"}, + {file = "mypy-1.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726"}, + {file = "mypy-1.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69"}, + {file = "mypy-1.20.0-cp313-cp313-win_arm64.whl", hash = "sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e"}, + {file = "mypy-1.20.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948"}, + {file = "mypy-1.20.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5"}, + {file = "mypy-1.20.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188"}, + {file = "mypy-1.20.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83"}, + {file = "mypy-1.20.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2"}, + {file = "mypy-1.20.0-cp314-cp314-win_amd64.whl", hash = "sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732"}, + {file = "mypy-1.20.0-cp314-cp314-win_arm64.whl", hash = "sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef"}, + {file = "mypy-1.20.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1"}, + {file = "mypy-1.20.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436"}, + {file = "mypy-1.20.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6"}, + {file = "mypy-1.20.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526"}, + {file = "mypy-1.20.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787"}, + {file = "mypy-1.20.0-cp314-cp314t-win_amd64.whl", hash = "sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb"}, + {file = "mypy-1.20.0-cp314-cp314t-win_arm64.whl", hash = "sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd"}, + {file = "mypy-1.20.0-py3-none-any.whl", hash = "sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e"}, + {file = "mypy-1.20.0.tar.gz", hash = "sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3"}, ] [package.dependencies] -librt = {version = ">=0.6.2", markers = "platform_python_implementation != \"PyPy\""} +librt = {version = ">=0.8.0", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" -pathspec = ">=0.9.0" +pathspec = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing_extensions = ">=4.6.0" @@ -2970,6 +2976,7 @@ dmypy = ["psutil (>=4.0)"] faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] +native-parser = ["ast-serialize (>=0.1.1,<1.0.0)"] reports = ["lxml"] [[package]] @@ -3676,14 +3683,14 @@ histogram = ["pygal", "pygaljs", "setuptools"] [[package]] name = "pytest-cov" -version = "7.0.0" +version = "7.1.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861"}, - {file = "pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1"}, + {file = "pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678"}, + {file = "pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2"}, ] [package.dependencies] @@ -4295,31 +4302,30 @@ files = [ [[package]] name = "ruff" -version = "0.14.14" +version = "0.15.8" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed"}, - {file = "ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c"}, - {file = "ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974"}, - {file = "ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66"}, - {file = "ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13"}, - {file = "ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412"}, - {file = "ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3"}, - {file = "ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b"}, - {file = "ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167"}, - {file = "ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd"}, - {file = "ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c"}, - {file = "ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b"}, + {file = "ruff-0.15.8-py3-none-linux_armv6l.whl", hash = "sha256:cbe05adeba76d58162762d6b239c9056f1a15a55bd4b346cfd21e26cd6ad7bc7"}, + {file = "ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d3e3d0b6ba8dca1b7ef9ab80a28e840a20070c4b62e56d675c24f366ef330570"}, + {file = "ruff-0.15.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ee3ae5c65a42f273f126686353f2e08ff29927b7b7e203b711514370d500de3"}, + {file = "ruff-0.15.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdce027ada77baa448077ccc6ebb2fa9c3c62fd110d8659d601cf2f475858d94"}, + {file = "ruff-0.15.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12e617fc01a95e5821648a6df341d80456bd627bfab8a829f7cfc26a14a4b4a3"}, + {file = "ruff-0.15.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:432701303b26416d22ba696c39f2c6f12499b89093b61360abc34bcc9bf07762"}, + {file = "ruff-0.15.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d910ae974b7a06a33a057cb87d2a10792a3b2b3b35e33d2699fdf63ec8f6b17a"}, + {file = "ruff-0.15.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2033f963c43949d51e6fdccd3946633c6b37c484f5f98c3035f49c27395a8ab8"}, + {file = "ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f29b989a55572fb885b77464cf24af05500806ab4edf9a0fd8977f9759d85b1"}, + {file = "ruff-0.15.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:ac51d486bf457cdc985a412fb1801b2dfd1bd8838372fc55de64b1510eff4bec"}, + {file = "ruff-0.15.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c9861eb959edab053c10ad62c278835ee69ca527b6dcd72b47d5c1e5648964f6"}, + {file = "ruff-0.15.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8d9a5b8ea13f26ae90838afc33f91b547e61b794865374f114f349e9036835fb"}, + {file = "ruff-0.15.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c2a33a529fb3cbc23a7124b5c6ff121e4d6228029cba374777bd7649cc8598b8"}, + {file = "ruff-0.15.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:75e5cd06b1cf3f47a3996cfc999226b19aa92e7cce682dcd62f80d7035f98f49"}, + {file = "ruff-0.15.8-py3-none-win32.whl", hash = "sha256:bc1f0a51254ba21767bfa9a8b5013ca8149dcf38092e6a9eb704d876de94dc34"}, + {file = "ruff-0.15.8-py3-none-win_amd64.whl", hash = "sha256:04f79eff02a72db209d47d665ba7ebcad609d8918a134f86cb13dd132159fc89"}, + {file = "ruff-0.15.8-py3-none-win_arm64.whl", hash = "sha256:cf891fa8e3bb430c0e7fac93851a5978fc99c8fa2c053b57b118972866f8e5f2"}, + {file = "ruff-0.15.8.tar.gz", hash = "sha256:995f11f63597ee362130d1d5a327a87cb6f3f5eae3094c620bcc632329a4d26e"}, ] [[package]] @@ -5174,4 +5180,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "ade91e6e8ba781806bb5af43cda5f48fa585acd3005f449e182394d238625deb" +content-hash = "9940232941feeeaf77d11a9021a396418da512e2f825123285bee5b7511bec06" diff --git a/pyproject.toml b/pyproject.toml index 8a5e4cec44d..c0ff9174f37 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.14.15" +ruff = ">=0.5.1,<0.15.9" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.8" types-redis = "^4.6.0.7" From 31ff4266314a06b022f0da3bf3fcc18956da20ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 12:19:41 +0100 Subject: [PATCH 10/84] chore(deps): bump squidfunk/mkdocs-material from `8f41b60` to `868ad4d` in /docs (#8083) chore(deps): bump squidfunk/mkdocs-material in /docs Bumps squidfunk/mkdocs-material from `8f41b60` to `868ad4d`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 868ad4d39fb5865b72d00173ade00f4eae2b38dde7ff790a011cc44ce4a8ff8e 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 --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 7c4cd4e4a71..fc49b3a319a 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,5 +1,5 @@ # v9.1.18 -FROM squidfunk/mkdocs-material@sha256:8f41b6089700e1c32212c3857936f14e88a3306a35be4ffd1826420e2f3e4197 +FROM squidfunk/mkdocs-material@sha256:868ad4d39fb5865b72d00173ade00f4eae2b38dde7ff790a011cc44ce4a8ff8e # pip-compile --generate-hashes --output-file=requirements.txt requirements.in COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 8139f69f223347a88820bdd05e80c6ea4665a3b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 12:24:42 +0100 Subject: [PATCH 11/84] chore(deps-dev): bump pygments from 2.19.2 to 2.20.0 (#8077) Bumps [pygments](https://github.com/pygments/pygments) from 2.19.2 to 2.20.0. - [Release notes](https://github.com/pygments/pygments/releases) - [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES) - [Commits](https://github.com/pygments/pygments/compare/2.19.2...2.20.0) --- updated-dependencies: - dependency-name: pygments dependency-version: 2.20.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 --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2ebdcc258e8..380abb3d5ee 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3583,14 +3583,14 @@ yaml = ["pyyaml (>=6.0.1)"] [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, - {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, ] [package.extras] From b716437a01b836b7cba1e7f336a5a1f0bd6a5251 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 13:21:57 +0100 Subject: [PATCH 12/84] chore(deps-dev): bump ty from 0.0.23 to 0.0.26 (#8078) * chore(deps-dev): bump ty from 0.0.23 to 0.0.26 Bumps [ty](https://github.com/astral-sh/ty) from 0.0.23 to 0.0.26. - [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.23...0.0.26) --- updated-dependencies: - dependency-name: ty dependency-version: 0.0.26 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Fix actions braking changes --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .../api_gateway_authorizer_event.py | 6 +-- .../utilities/data_classes/common.py | 2 +- .../utilities/feature_flags/feature_flags.py | 2 +- .../utilities/kafka/deserializer/protobuf.py | 4 +- .../utilities/metadata/lambda_metadata.py | 1 + .../utilities/parameters/dynamodb.py | 4 +- .../utilities/parameters/secrets.py | 4 +- .../utilities/parameters/ssm.py | 4 +- poetry.lock | 38 +++++++++---------- pyproject.toml | 2 +- 10 files changed, 35 insertions(+), 32 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py b/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py index f1b9c4f5103..c73eb33b9fe 100644 --- a/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py +++ b/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py @@ -668,7 +668,7 @@ def from_route_arn( # Note: we need ignore[override] because we are removing the http_method field @override - def _add_route(self, effect: str, resource: str, conditions: list[dict] | None = None): # type: ignore[override] + def _add_route(self, effect: str, resource: str, conditions: list[dict] | None = None): # type: ignore[override] # ty: ignore[invalid-method-override] """Adds a route to the internal lists of allowed or denied routes. Each object in the internal list contains a resource ARN and a condition statement. The condition statement can be null.""" @@ -703,7 +703,7 @@ def deny_all_routes(self, http_method: str = HttpVerb.ALL.value): # type: ignor # Note: we need ignore[override] because we are removing the http_method field @override - def allow_route(self, resource: str, conditions: list[dict] | None = None): # type: ignore[override] + def allow_route(self, resource: str, conditions: list[dict] | None = None): # type: ignore[override] # ty: ignore[invalid-method-override] """ Add an API Gateway Websocket method to the list of allowed methods for the policy. @@ -732,7 +732,7 @@ def allow_route(self, resource: str, conditions: list[dict] | None = None): # t # Note: we need ignore[override] because we are removing the http_method field @override - def deny_route(self, resource: str, conditions: list[dict] | None = None): # type: ignore[override] + def deny_route(self, resource: str, conditions: list[dict] | None = None): # type: ignore[override] # ty: ignore[invalid-method-override] """ Add an API Gateway Websocket method to the list of allowed methods for the policy. diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index 08fd60f0679..a85d7b2d2a8 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -125,7 +125,7 @@ def _str_helper(self) -> dict[str, Any]: properties = self._properties() sensitive_properties = ["raw_event"] if hasattr(self, "_sensitive_properties"): - sensitive_properties.extend(self._sensitive_properties) # pyright: ignore # type: ignore[arg-type] + sensitive_properties.extend(self._sensitive_properties) # pyright: ignore # type: ignore[arg-type] # ty: ignore[invalid-argument-type] result: dict[str, Any] = {} for property_key in properties: diff --git a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py index 1dfe89a40f7..19e96a8641d 100644 --- a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +++ b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py @@ -432,5 +432,5 @@ def _lookup_exception_handler(self, exc: BaseException) -> Callable | None: # of an exception for cls in type(exc).__mro__: if cls in self._exception_handlers: - return self._exception_handlers[cls] # type: ignore[index] # index is correct + return self._exception_handlers[cls] # type: ignore[index] # ty: ignore[invalid-argument-type] return None diff --git a/aws_lambda_powertools/utilities/kafka/deserializer/protobuf.py b/aws_lambda_powertools/utilities/kafka/deserializer/protobuf.py index 16bb3bbc6ec..683b8432023 100644 --- a/aws_lambda_powertools/utilities/kafka/deserializer/protobuf.py +++ b/aws_lambda_powertools/utilities/kafka/deserializer/protobuf.py @@ -3,7 +3,9 @@ import logging from typing import Any -from google.protobuf.internal.decoder import _DecodeSignedVarint # type: ignore[attr-defined] +from google.protobuf.internal.decoder import ( # type: ignore[attr-defined] + _DecodeSignedVarint, # ty: ignore[unresolved-import] +) from google.protobuf.json_format import MessageToDict from aws_lambda_powertools.utilities.kafka.deserializer.base import DeserializerBase diff --git a/aws_lambda_powertools/utilities/metadata/lambda_metadata.py b/aws_lambda_powertools/utilities/metadata/lambda_metadata.py index 71bbece3aac..ee9e06dd8c3 100644 --- a/aws_lambda_powertools/utilities/metadata/lambda_metadata.py +++ b/aws_lambda_powertools/utilities/metadata/lambda_metadata.py @@ -9,6 +9,7 @@ import logging import os +import urllib.error import urllib.request from dataclasses import dataclass, field from json import JSONDecodeError diff --git a/aws_lambda_powertools/utilities/parameters/dynamodb.py b/aws_lambda_powertools/utilities/parameters/dynamodb.py index d80fd1b985a..9fe95518b8e 100644 --- a/aws_lambda_powertools/utilities/parameters/dynamodb.py +++ b/aws_lambda_powertools/utilities/parameters/dynamodb.py @@ -202,7 +202,7 @@ def _get(self, name: str, **sdk_options) -> str: # maintenance: look for better ways to correctly type DynamoDB multiple return types # without a breaking change within ABC return type - return self.table.get_item(**sdk_options)["Item"][self.value_attr] # type: ignore[return-value] + return self.table.get_item(**sdk_options)["Item"][self.value_attr] # type: ignore[return-value] # ty: ignore[invalid-return-type] def _get_multiple(self, path: str, **sdk_options) -> dict[str, str]: """ @@ -230,4 +230,4 @@ def _get_multiple(self, path: str, **sdk_options) -> dict[str, str]: # maintenance: look for better ways to correctly type DynamoDB multiple return types # without a breaking change within ABC return type - return {item[self.sort_attr]: item[self.value_attr] for item in items} # type: ignore[misc] + return {item[self.sort_attr]: item[self.value_attr] for item in items} # type: ignore[misc] # ty: ignore[invalid-return-type] diff --git a/aws_lambda_powertools/utilities/parameters/secrets.py b/aws_lambda_powertools/utilities/parameters/secrets.py index 0f80f003920..eff4e745738 100644 --- a/aws_lambda_powertools/utilities/parameters/secrets.py +++ b/aws_lambda_powertools/utilities/parameters/secrets.py @@ -130,7 +130,7 @@ def _get(self, name: str, **sdk_options) -> str | bytes: return secret_value["SecretBinary"] - def _get_multiple(self, names: list[str], **sdk_options) -> dict[str, Any]: # type: ignore[override] + def _get_multiple(self, names: list[str], **sdk_options) -> dict[str, Any]: # type: ignore[override] # ty: ignore[invalid-method-override] """ Retrieve multiple secrets using AWS Secrets Manager batch_get_secret_value API @@ -200,7 +200,7 @@ def _get_multiple(self, names: list[str], **sdk_options) -> dict[str, Any]: # t return secrets - def get_multiple( # type: ignore[override] + def get_multiple( # type: ignore[override] # ty: ignore[invalid-method-override] self, names: list[str], max_age: int | None = None, diff --git a/aws_lambda_powertools/utilities/parameters/ssm.py b/aws_lambda_powertools/utilities/parameters/ssm.py index b4e0de011c4..fde8d980494 100644 --- a/aws_lambda_powertools/utilities/parameters/ssm.py +++ b/aws_lambda_powertools/utilities/parameters/ssm.py @@ -133,7 +133,7 @@ def __init__( super().__init__(client=self.client) - def get_multiple( # type: ignore[override] + def get_multiple( # type: ignore[override] # ty: ignore[invalid-method-override] self, path: str, max_age: int | None = None, @@ -192,7 +192,7 @@ def get_multiple( # type: ignore[override] # We break Liskov substitution principle due to differences in signatures of this method and superclass get method # We ignore mypy error, as changes to the signature here or in a superclass is a breaking change to users - def get( # type: ignore[override] + def get( # type: ignore[override] # ty: ignore[invalid-method-override] self, name: str, max_age: int | None = None, diff --git a/poetry.lock b/poetry.lock index 380abb3d5ee..e074b55374a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4620,29 +4620,29 @@ files = [ [[package]] name = "ty" -version = "0.0.23" +version = "0.0.27" description = "An extremely fast Python type checker, written in Rust." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "ty-0.0.23-py3-none-linux_armv6l.whl", hash = "sha256:e810eef1a5f1cfc0731a58af8d2f334906a96835829767aed00026f1334a8dd7"}, - {file = "ty-0.0.23-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e43d36bd89a151ddcad01acaeff7dcc507cb73ff164c1878d2d11549d39a061c"}, - {file = "ty-0.0.23-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bd6a340969577b4645f231572c4e46012acba2d10d4c0c6570fe1ab74e76ae00"}, - {file = "ty-0.0.23-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:341441783e626eeb7b1ec2160432956aed5734932ab2d1c26f94d0c98b229937"}, - {file = "ty-0.0.23-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ce1dc66c26d4167e2c78d12fa870ef5a7ec9cc344d2baaa6243297cfa88bd52"}, - {file = "ty-0.0.23-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bae1e7a294bf8528836f7617dc5c360ea2dddb63789fc9471ae6753534adca05"}, - {file = "ty-0.0.23-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2b162768764d9dc177c83fb497a51532bb67cbebe57b8fa0f2668436bf53f3c"}, - {file = "ty-0.0.23-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d28384e48ca03b34e4e2beee0e230c39bbfb68994bb44927fec61ef3642900da"}, - {file = "ty-0.0.23-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:559d9a299df793cb7a7902caed5eda8a720ff69164c31c979673e928f02251ee"}, - {file = "ty-0.0.23-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:32a7b8a14a98e1d20a9d8d2af23637ed7efdb297ac1fa2450b8e465d05b94482"}, - {file = "ty-0.0.23-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6f803b9b9cca87af793467973b9abdd4b83e6b96d9b5e749d662cff7ead70b6d"}, - {file = "ty-0.0.23-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4a0bf086ec8e2197b7ea7ebfcf4be36cb6a52b235f8be61647ef1b2d99d6ffd3"}, - {file = "ty-0.0.23-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:252539c3fcd7aeb9b8d5c14e2040682c3e1d7ff640906d63fd2c4ce35865a4ba"}, - {file = "ty-0.0.23-py3-none-win32.whl", hash = "sha256:51b591d19eef23bbc3807aef77d38fa1f003c354e1da908aa80ea2dca0993f77"}, - {file = "ty-0.0.23-py3-none-win_amd64.whl", hash = "sha256:1e137e955f05c501cfbb81dd2190c8fb7d01ec037c7e287024129c722a83c9ad"}, - {file = "ty-0.0.23-py3-none-win_arm64.whl", hash = "sha256:a0399bd13fd2cd6683fd0a2d59b9355155d46546d8203e152c556ddbdeb20842"}, - {file = "ty-0.0.23.tar.gz", hash = "sha256:5fb05db58f202af366f80ef70f806e48f5237807fe424ec787c9f289e3f3a4ef"}, + {file = "ty-0.0.27-py3-none-linux_armv6l.whl", hash = "sha256:eb14456b8611c9e8287aa9b633f4d2a0d9f3082a31796969e0b50bdda8930281"}, + {file = "ty-0.0.27-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:02e662184703db7586118df611cf24a000d35dae38d950053d1dd7b6736fd2c4"}, + {file = "ty-0.0.27-py3-none-macosx_11_0_arm64.whl", hash = "sha256:be5fc2899441f7f8f7ef40f9ffd006075a5ff6b06c44e8d2aa30e1b900c12f51"}, + {file = "ty-0.0.27-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30231e652b14742a76b64755e54bf0cb1cd4c128bcaf625222e0ca92a2094887"}, + {file = "ty-0.0.27-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a119b1168f64261b3205a37e40b5b6c4aac8fd58e4587988f4e4b22c3c79847"}, + {file = "ty-0.0.27-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e38f4e187b6975d2cbebf0f1eb1221f8f64f6e509bad14d7bb2a91afc97e4956"}, + {file = "ty-0.0.27-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a07b1a8fbb23844f6d22091275430d9ac617175f34aa99159b268193de210389"}, + {file = "ty-0.0.27-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3ec4033031f240836bb0337274bac5c49dde312c7c6d7575451ed719bf8ffa3"}, + {file = "ty-0.0.27-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:924a8849afd500d260bf5b7296165a05b7424fbb6b19113f30f3b999d682873f"}, + {file = "ty-0.0.27-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d8270026c07e7423a1b3a3fd065b46ed1478748f0662518b523b57744f3fa025"}, + {file = "ty-0.0.27-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e26e9735d3bdfd95d881111ad1cf570eab8188d8c3be36d6bcaad044d38984d8"}, + {file = "ty-0.0.27-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7c09cc9a699810609acc0090af8d0db68adaee6e60a7c3e05ab80cc954a83db7"}, + {file = "ty-0.0.27-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2d3e02853bb037221a456e034b1898aaa573e6374fbb53884e33cb7513ccb85a"}, + {file = "ty-0.0.27-py3-none-win32.whl", hash = "sha256:34e7377f2047c14dbbb7bf5322e84114db7a5f2cb470db6bee63f8f3550cfc1e"}, + {file = "ty-0.0.27-py3-none-win_amd64.whl", hash = "sha256:3f7e4145aad8b815ed69b324c93b5b773eb864dda366ca16ab8693ff88ce6f36"}, + {file = "ty-0.0.27-py3-none-win_arm64.whl", hash = "sha256:95bf8d01eb96bb2ba3ffc39faff19da595176448e80871a7b362f4d2de58476c"}, + {file = "ty-0.0.27.tar.gz", hash = "sha256:d7a8de3421d92420b40c94fe7e7d4816037560621903964dd035cf9bd0204a73"}, ] [[package]] @@ -5180,4 +5180,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "9940232941feeeaf77d11a9021a396418da512e2f825123285bee5b7511bec06" +content-hash = "8ea7e1c9ec1c0ca0d1db0911890d085c1ce4e0d9128d710b3317299600f62154" diff --git a/pyproject.toml b/pyproject.toml index c0ff9174f37..9f23f734dd1 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" -ty = "^0.0.23" +ty = ">=0.0.23,<0.0.28" [tool.coverage.run] source = ["aws_lambda_powertools"] From 3f6fc29b6cad0384cb5bec15ed8c172d364c06ef Mon Sep 17 00:00:00 2001 From: Abhishek Chauhan <60182103+abhu85@users.noreply.github.com> Date: Thu, 2 Apr 2026 20:15:13 +0530 Subject: [PATCH 13/84] fix(idempotency): serialize Pydantic models with mode='json' for UUID/date support (#8075) * fix(idempotency): serialize Pydantic models with mode='json' for UUID/date support The `_prepare_data()` function was calling `model_dump()` without specifying `mode="json"`, which defaults to `mode="python"`. This caused Pydantic models containing UUIDs, dates, or datetimes to fail with "Object of type UUID is not JSON serializable" when used with `@idempotent_function`. Fixes #8065 * Fix tests --------- Co-authored-by: Leandro Damascena --- .../utilities/idempotency/base.py | 2 +- ...idempotency_pydantic_json_serialization.py | 185 ++++++++++++++++++ 2 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 tests/functional/idempotency/_pydantic/test_idempotency_pydantic_json_serialization.py diff --git a/aws_lambda_powertools/utilities/idempotency/base.py b/aws_lambda_powertools/utilities/idempotency/base.py index f93b9097611..f6a3563c103 100644 --- a/aws_lambda_powertools/utilities/idempotency/base.py +++ b/aws_lambda_powertools/utilities/idempotency/base.py @@ -60,7 +60,7 @@ def _prepare_data(data: Any) -> Any: # Convert from Pydantic model if callable(getattr(data, "model_dump", None)): - return data.model_dump() + return data.model_dump(mode="json") # Convert from event source data class if callable(getattr(data, "dict", None)): diff --git a/tests/functional/idempotency/_pydantic/test_idempotency_pydantic_json_serialization.py b/tests/functional/idempotency/_pydantic/test_idempotency_pydantic_json_serialization.py new file mode 100644 index 00000000000..624e4239e98 --- /dev/null +++ b/tests/functional/idempotency/_pydantic/test_idempotency_pydantic_json_serialization.py @@ -0,0 +1,185 @@ +""" +Test for issue #8065: @idempotent_function fails with non-JSON-serializable types in Pydantic models + +Bug: _prepare_data() calls model_dump() without mode="json", which doesn't +serialize UUIDs, dates, datetimes, Decimals, and Paths to JSON-compatible strings. +""" + +from datetime import date, datetime +from decimal import Decimal +from pathlib import PurePosixPath +from uuid import UUID + +from pydantic import BaseModel + +from aws_lambda_powertools.utilities.idempotency import ( + IdempotencyConfig, + idempotent_function, +) +from aws_lambda_powertools.utilities.idempotency.persistence.base import ( + BasePersistenceLayer, + DataRecord, +) +from tests.functional.idempotency.utils import hash_idempotency_key + +TESTS_MODULE_PREFIX = "test-func.tests.functional.idempotency._pydantic.test_idempotency_pydantic_json_serialization" + + +class MockPersistenceLayer(BasePersistenceLayer): + def __init__(self, expected_idempotency_key: str): + self.expected_idempotency_key = expected_idempotency_key + super().__init__() + + def _put_record(self, data_record: DataRecord) -> None: + assert data_record.idempotency_key == self.expected_idempotency_key + + def _update_record(self, data_record: DataRecord) -> None: + assert data_record.idempotency_key == self.expected_idempotency_key + + def _get_record(self, idempotency_key) -> DataRecord: ... + + def _delete_record(self, data_record: DataRecord) -> None: ... + + +# --- Models --- + + +class PaymentWithUUID(BaseModel): + payment_id: UUID + customer_id: str + + +class EventWithDate(BaseModel): + event_id: str + event_date: date + + +class OrderWithDatetime(BaseModel): + order_id: str + created_at: datetime + + +class InvoiceWithDecimal(BaseModel): + invoice_id: str + amount: Decimal + + +class ConfigWithPath(BaseModel): + config_id: str + file_path: PurePosixPath + + +def test_idempotent_function_with_uuid(): + # GIVEN + config = IdempotencyConfig(use_local_cache=True) + payment_uuid = UUID("12345678-1234-5678-1234-567812345678") + mock_event = {"payment_id": str(payment_uuid), "customer_id": "c-456"} + idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_with_uuid..collect_payment#{hash_idempotency_key(mock_event)}" # noqa E501 + persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key) + + @idempotent_function( + data_keyword_argument="payment", + persistence_store=persistence_layer, + config=config, + ) + def collect_payment(payment: PaymentWithUUID) -> dict: + return {"status": "ok"} + + # WHEN + payment = PaymentWithUUID(payment_id=payment_uuid, customer_id="c-456") + result = collect_payment(payment=payment) + + # THEN + assert result == {"status": "ok"} + + +def test_idempotent_function_with_date(): + # GIVEN + config = IdempotencyConfig(use_local_cache=True) + mock_event = {"event_id": "evt-001", "event_date": "2024-03-20"} + idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_with_date..process_event#{hash_idempotency_key(mock_event)}" # noqa E501 + persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key) + + @idempotent_function( + data_keyword_argument="event", + persistence_store=persistence_layer, + config=config, + ) + def process_event(event: EventWithDate) -> dict: + return {"status": "ok"} + + # WHEN + event = EventWithDate(event_id="evt-001", event_date=date(2024, 3, 20)) + result = process_event(event=event) + + # THEN + assert result == {"status": "ok"} + + +def test_idempotent_function_with_datetime(): + # GIVEN + config = IdempotencyConfig(use_local_cache=True) + mock_event = {"order_id": "ord-001", "created_at": "2024-03-20T14:30:00"} + idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_with_datetime..process_order#{hash_idempotency_key(mock_event)}" # noqa E501 + persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key) + + @idempotent_function( + data_keyword_argument="order", + persistence_store=persistence_layer, + config=config, + ) + def process_order(order: OrderWithDatetime) -> dict: + return {"status": "ok"} + + # WHEN + order = OrderWithDatetime(order_id="ord-001", created_at=datetime(2024, 3, 20, 14, 30, 0)) + result = process_order(order=order) + + # THEN + assert result == {"status": "ok"} + + +def test_idempotent_function_with_decimal(): + # GIVEN + config = IdempotencyConfig(use_local_cache=True) + mock_event = {"invoice_id": "inv-001", "amount": "199.99"} + idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_with_decimal..process_invoice#{hash_idempotency_key(mock_event)}" # noqa E501 + persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key) + + @idempotent_function( + data_keyword_argument="invoice", + persistence_store=persistence_layer, + config=config, + ) + def process_invoice(invoice: InvoiceWithDecimal) -> dict: + return {"status": "ok"} + + # WHEN + invoice = InvoiceWithDecimal(invoice_id="inv-001", amount=Decimal("199.99")) + result = process_invoice(invoice=invoice) + + # THEN + assert result == {"status": "ok"} + + +def test_idempotent_function_with_path(): + # GIVEN + config = IdempotencyConfig(use_local_cache=True) + mock_event = {"config_id": "cfg-001", "file_path": "/etc/app/config.yaml"} + idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_with_path..process_config#{hash_idempotency_key(mock_event)}" # noqa E501 + persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key) + + @idempotent_function( + data_keyword_argument="config", + persistence_store=persistence_layer, + config=config, + ) + def process_config(config: ConfigWithPath) -> dict: + return {"status": "ok"} + + # WHEN + cfg = ConfigWithPath(config_id="cfg-001", file_path=PurePosixPath("/etc/app/config.yaml")) + result = process_config(config=cfg) + + # THEN + assert result == {"status": "ok"} From dafed6aae579ae489a5e108f097b860fa090fa5c Mon Sep 17 00:00:00 2001 From: Simon Wydooghe Date: Thu, 2 Apr 2026 17:22:50 +0200 Subject: [PATCH 14/84] fix(event_handler): support finding type annotated resolver when merging schemas (#8074) * Support finding type annotated resolver * Fix tests --------- Co-authored-by: Leandro Damascena --- .../event_handler/openapi/merge.py | 15 ++++++++---- .../_pydantic/merge_handlers/typed_handler.py | 24 +++++++++++++++++++ .../_pydantic/test_openapi_merge.py | 16 +++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 tests/functional/event_handler/_pydantic/merge_handlers/typed_handler.py diff --git a/aws_lambda_powertools/event_handler/openapi/merge.py b/aws_lambda_powertools/event_handler/openapi/merge.py index 38b80914df3..9db9c0daa5c 100644 --- a/aws_lambda_powertools/event_handler/openapi/merge.py +++ b/aws_lambda_powertools/event_handler/openapi/merge.py @@ -67,11 +67,18 @@ def _file_has_resolver(file_path: Path, resolver_name: str) -> bool: return False for node in ast.walk(tree): + targets: list[ast.expr] = [] + value: ast.expr | None = None if isinstance(node, ast.Assign): - for target in node.targets: - if isinstance(target, ast.Name) and target.id == resolver_name: - if _is_resolver_call(node.value): - return True + targets = node.targets + value = node.value + elif isinstance(node, ast.AnnAssign): + targets = [node.target] + value = node.value + for target in targets: + if isinstance(target, ast.Name) and target.id == resolver_name: + if value is not None and _is_resolver_call(value): + return True return False diff --git a/tests/functional/event_handler/_pydantic/merge_handlers/typed_handler.py b/tests/functional/event_handler/_pydantic/merge_handlers/typed_handler.py new file mode 100644 index 00000000000..53c2b4e0a12 --- /dev/null +++ b/tests/functional/event_handler/_pydantic/merge_handlers/typed_handler.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from pydantic import BaseModel + +from aws_lambda_powertools.event_handler import APIGatewayRestResolver + +app: APIGatewayRestResolver = APIGatewayRestResolver(enable_validation=True) + + +class Product(BaseModel): + id: int + name: str + price: float + + +@app.get("/products") +def get_products() -> list[Product]: + return [ + Product(id=1, name="Widget", price=9.99), + ] + + +def handler(event, context): + return app.resolve(event, context) diff --git a/tests/functional/event_handler/_pydantic/test_openapi_merge.py b/tests/functional/event_handler/_pydantic/test_openapi_merge.py index b4dc1d70232..12d41566e32 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_merge.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_merge.py @@ -367,3 +367,19 @@ def test_openapi_merge_schema_is_cached(): # AND paths should not be duplicated assert len([p for p in schema1["paths"] if p == "/users"]) == 1 + + +def test_openapi_merge_discover_type_annotated_resolver(): + # GIVEN an OpenAPIMerge instance + merge = OpenAPIMerge(title="Typed API", version="1.0.0") + + # WHEN discovering a handler with a type-annotated resolver (app: Resolver = Resolver()) + merge.discover( + path=MERGE_HANDLERS_PATH, + pattern="**/typed_handler.py", + resolver_name="app", + ) + + # THEN it should find the resolver and include its routes in the schema + schema = merge.get_openapi_schema() + assert "/products" in schema["paths"] From 92a0db3d90b084a329055c5658c6c87d83cda593 Mon Sep 17 00:00:00 2001 From: Ran Isenberg <60175085+ran-isenberg@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:25:49 +0300 Subject: [PATCH 15/84] docs: fix ranthebuilder link in Update we_made_this.md (#8084) * dcos: fix ranthebuilder link in Update we_made_this.md Signed-off-by: Ran Isenberg <60175085+ran-isenberg@users.noreply.github.com> * replace /post with /blog --------- Signed-off-by: Ran Isenberg <60175085+ran-isenberg@users.noreply.github.com> Co-authored-by: Leandro Damascena --- docs/we_made_this.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/we_made_this.md b/docs/we_made_this.md index db3dc8a23b1..b8a3445cc4f 100644 --- a/docs/we_made_this.md +++ b/docs/we_made_this.md @@ -35,29 +35,29 @@ GitHub: [https://github.com/serverless-dna/powertools-mcp](https://github.com/se A collection of articles explaining in detail how Powertools for AWS Lambda helps with a Serverless adoption strategy and its challenges. -* [Part 1 - Logging](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-1-logging){target="_blank" rel="nofollow"} +* [Part 1 - Logging](https://ranthebuilder.cloud/blog/aws-lambda-cookbook-elevate-your-handler-s-code-part-1-logging/){target="_blank" rel="nofollow"} -* [Part 2 - Observability: monitoring and tracing](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-2-observability){target="_blank" rel="nofollow"} +* [Part 2 - Observability: monitoring and tracing](https://ranthebuilder.cloud/blog/aws-lambda-cookbook-elevate-your-handler-s-code-part-2-observability/){target="_blank" rel="nofollow"} -* [Part 3 - Business Domain Observability](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-3-business-domain-observability){target="_blank" rel="nofollow"} +* [Part 3 - Business Domain Observability](https://ranthebuilder.cloud/blog/aws-lambda-cookbook-elevate-your-handler-s-code-part-3-business-domain-observability/){target="_blank" rel="nofollow"} -* [Part 4 - Environment Variables](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-environment-variables){target="_blank" rel="nofollow"} +* [Part 4 - Environment Variables](https://ranthebuilder.cloud/blog/aws-lambda-cookbook-environment-variables/){target="_blank" rel="nofollow"} -* [Part 5 - Input Validation](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-5-input-validation){target="_blank" rel="nofollow"} +* [Part 5 - Input Validation](https://ranthebuilder.cloud/blog/aws-lambda-cookbook-elevate-your-handler-s-code-part-5-input-validation/){target="_blank" rel="nofollow"} -* [Part 6 - Configuration & Feature Flags](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-part-6-feature-flags-configuration-best-practices){target="_blank" rel="nofollow"} +* [Part 6 - Configuration & Feature Flags](https://ranthebuilder.cloud/blog/aws-lambda-cookbook-part-6-feature-flags-configuration-best-practices/){target="_blank" rel="nofollow"} -* [Serverless API Idempotency with AWS Powertools for AWS Lambda and CDK](https://www.ranthebuilder.cloud/post/serverless-api-idempotency-with-aws-lambda-powertools-and-cdk){target="_blank" rel="nofollow"} +* [Serverless API Idempotency with AWS Powertools for AWS Lambda and CDK](https://ranthebuilder.cloud/blog/serverless-api-idempotency-with-aws-lambda-powertools-and-cdk/){target="_blank" rel="nofollow"} -* [Effective Amazon SQS Batch Handling with Powertools for AWS Lambda (Python)](https://www.ranthebuilder.cloud/post/effective-amazon-sqs-batch-handling-with-aws-lambda-powertools){target="_blank" rel="nofollow"} +* [Effective Amazon SQS Batch Handling with Powertools for AWS Lambda (Python)](https://ranthebuilder.cloud/blog/effective-amazon-sqs-batch-handling-with-aws-lambda-powertools/){target="_blank" rel="nofollow"} -* [Serverless API Documentation with Powertools for AWS Lambda](https://www.ranthebuilder.cloud/post/serverless-open-api-documentation-with-aws-powertools){:target="_blank"} +* [Serverless API Documentation with Powertools for AWS Lambda](https://ranthebuilder.cloud/blog/serverless-open-api-documentation-with-aws-powertools/){:target="_blank"} * [Best practices for accelerating development with serverless blueprints](https://aws.amazon.com/blogs/infrastructure-and-automation/best-practices-for-accelerating-development-with-serverless-blueprints/){target="_blank" rel="nofollow"} -* [Build a Chatbot with Amazon Bedrock: Automate API Calls Using Powertools for AWS Lambda and CDK](https://www.ranthebuilder.cloud/post/automating-api-calls-with-agents-for-amazon-bedrock-with-powertools){target="_blank" rel="nofollow"} +* [Build a Chatbot with Amazon Bedrock: Automate API Calls Using Powertools for AWS Lambda and CDK](https://ranthebuilder.cloud/blog/automating-api-calls-with-agents-for-amazon-bedrock-with-powertools/){target="_blank" rel="nofollow"} -* [Build Serverless WebSockets with AWS AppSync Events and Powertools for AWS Lambda](https://www.ranthebuilder.cloud/post/aws-appsync-events-and-powertools-for-aws-lambda){target="_blank" rel="nofollow"} +* [Build Serverless WebSockets with AWS AppSync Events and Powertools for AWS Lambda](https://ranthebuilder.cloud/blog/aws-appsync-events-and-powertools-for-aws-lambda/){target="_blank" rel="nofollow"} #### Lambda MCP Server Cookbook @@ -138,7 +138,7 @@ This article will guide you through personalizing observability by integrating C > **Author: [Nathan Hanks](https://www.linkedin.com/in/nathan-hanks-25151815/){target="_blank" rel="nofollow"}** :material-linkedin: -[Creating a serverless API using Powertools for AWS Lambda and CDK](https://www.ranthebuilder.cloud/post/boost-app-engagement-with-aws-cloudwatch-metrics-powertools-for-aws){target="_blank" rel="nofollow"} +[Creating a serverless API using Powertools for AWS Lambda and CDK](https://ranthebuilder.cloud/blog/boost-app-engagement-with-aws-cloudwatch-metrics-powertools-for-aws/){target="_blank" rel="nofollow"} ### Streaming data with AWS Lambda & Powertools for AWS Lambda @@ -192,7 +192,7 @@ Are you developing AWS Lambda functions with Python? Always looking for tools to This session covers an opinionated approach to Python project setup, testing, profiling, deployments, and operations. Learn about many open source tools, including Powertools for AWS Lambda—a toolkit that can help you implement serverless best practices and increase developer velocity. -Join to discover tools and patterns for effective serverless development with Python. To maximize your learning experience, the session includes a sample application that implements what’s described. +Join to discover tools and patterns for effective serverless development with Python. To maximize your learning experience, the session includes a sample application that implements what's described. From 7323c058fdfb60b97fd563da97dfd36b35714dc8 Mon Sep 17 00:00:00 2001 From: Michael <100072485+oyiz-michael@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:35:36 +0100 Subject: [PATCH 16/84] feat(event_handler): add Request object for middleware access to resolved route and args (#8036) * feat(event_handler): add Request object for middleware access to resolved route and args Introduce a Request class that provides structured access to the resolved route pattern, path parameters, HTTP method, headers, query parameters, and body. Available via app.request in middleware and via type-annotation injection in route handlers. Closes #7992, #4609 * fix(event_handler): remove unused import and move NextMiddleware to TYPE_CHECKING block * style: fix import ordering in api_gateway.py and dependant.py * Improve workflow --------- Co-authored-by: Leandro Damascena --- .../event_handler/__init__.py | 2 + .../event_handler/api_gateway.py | 76 +++ .../event_handler/openapi/dependant.py | 6 + .../event_handler/request.py | 115 ++++ .../required_dependencies/test_request.py | 588 ++++++++++++++++++ 5 files changed, 787 insertions(+) create mode 100644 aws_lambda_powertools/event_handler/request.py create mode 100644 tests/functional/event_handler/required_dependencies/test_request.py diff --git a/aws_lambda_powertools/event_handler/__init__.py b/aws_lambda_powertools/event_handler/__init__.py index 6b926e6248a..582abd017c0 100644 --- a/aws_lambda_powertools/event_handler/__init__.py +++ b/aws_lambda_powertools/event_handler/__init__.py @@ -21,6 +21,7 @@ from aws_lambda_powertools.event_handler.lambda_function_url import ( LambdaFunctionUrlResolver, ) +from aws_lambda_powertools.event_handler.request import Request from aws_lambda_powertools.event_handler.vpc_lattice import VPCLatticeResolver, VPCLatticeV2Resolver __all__ = [ @@ -37,6 +38,7 @@ "CORSConfig", "HttpResolverLocal", "LambdaFunctionUrlResolver", + "Request", "Response", "VPCLatticeResolver", "VPCLatticeV2Resolver", diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index b1e0c9ff16d..f7294801460 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -42,6 +42,7 @@ validation_error_definition, validation_error_response_definition, ) +from aws_lambda_powertools.event_handler.request import Request from aws_lambda_powertools.event_handler.util import ( _FrozenDict, _FrozenListDict, @@ -466,6 +467,11 @@ def __init__( self.custom_response_validation_http_code = custom_response_validation_http_code + # Caches the name of any Request-typed parameter in the handler. + # Avoids re-scanning the signature on every invocation. + self.request_param_name: str | None = None + self.request_param_name_checked: bool = False + def __call__( self, router_middlewares: list[Callable], @@ -1608,6 +1614,47 @@ def clear_context(self): """Resets routing context""" self.context.clear() + @property + def request(self) -> Request: + """Current resolved :class:`Request` object. + + Available inside middleware and in route handlers that declare a parameter + typed as :class:`Request `. + + Raises + ------ + RuntimeError + When accessed before route resolution (i.e. outside of middleware / handler scope). + + Examples + -------- + **Middleware** + + ```python + def my_middleware(app, next_middleware): + req = app.request + print(req.route, req.method, req.path_parameters) + return next_middleware(app) + ``` + """ + cached: Request | None = self.context.get("_request") + if cached is not None: + return cached + + route: Route | None = self.context.get("_route") + if route is None: + raise RuntimeError( + "app.request is only available after route resolution. Use it inside middleware or a route handler.", + ) + + request = Request( + route_path=route.openapi_path, + path_parameters=self.context.get("_route_args", {}), + current_event=self.current_event, + ) + self.context["_request"] = request + return request + class MiddlewareFrame: """ @@ -1680,6 +1727,24 @@ def __call__(self, app: ApiGatewayResolver) -> dict | tuple | Response: return self.current_middleware(app, self.next_middleware) +def _find_request_param_name(func: Callable) -> str | None: + """Return the name of the first parameter annotated as ``Request``, or ``None``.""" + from typing import get_type_hints + + try: + # get_type_hints resolves string annotations from ``from __future__ import annotations`` + # using the function's own module globals. + hints = get_type_hints(func) + except Exception: + hints = {} + + for param_name, annotation in hints.items(): + if annotation is Request: + return param_name + + return None + + def _registered_api_adapter( app: ApiGatewayResolver, next_middleware: Callable[..., Any], @@ -1708,6 +1773,17 @@ def _registered_api_adapter( """ route_args: dict = app.context.get("_route_args", {}) logger.debug(f"Calling API Route Handler: {route_args}") + + # Inject a Request object when the handler declares a parameter typed as Request. + # Lookup is cached on the Route object to avoid repeated signature inspection. + route: Route | None = app.context.get("_route") + if route is not None: + if not route.request_param_name_checked: + route.request_param_name = _find_request_param_name(next_middleware) + route.request_param_name_checked = True + if route.request_param_name: + route_args = {**route_args, route.request_param_name: app.request} + return app._to_response(next_middleware(**route_args)) diff --git a/aws_lambda_powertools/event_handler/openapi/dependant.py b/aws_lambda_powertools/event_handler/openapi/dependant.py index 310cab68e66..197de9427d2 100644 --- a/aws_lambda_powertools/event_handler/openapi/dependant.py +++ b/aws_lambda_powertools/event_handler/openapi/dependant.py @@ -22,6 +22,7 @@ get_flat_dependant, ) from aws_lambda_powertools.event_handler.openapi.types import OpenAPIResponse, OpenAPIResponseContentModel +from aws_lambda_powertools.event_handler.request import Request if TYPE_CHECKING: from collections.abc import Callable @@ -187,6 +188,11 @@ def get_dependant( # Add each parameter to the dependant model for param_name, param in signature_params.items(): + # Request-typed parameters are injected by the resolver at call time; + # they carry no OpenAPI meaning and must be excluded from schema generation. + if param.annotation is Request: + continue + # If the parameter is a path parameter, we need to set the in_ field to "path". is_path_param = param_name in path_param_names diff --git a/aws_lambda_powertools/event_handler/request.py b/aws_lambda_powertools/event_handler/request.py new file mode 100644 index 00000000000..e402c094ded --- /dev/null +++ b/aws_lambda_powertools/event_handler/request.py @@ -0,0 +1,115 @@ +"""Resolved HTTP Request object for Event Handler.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from aws_lambda_powertools.utilities.data_classes.common import BaseProxyEvent + + +class Request: + """Represents the resolved HTTP request. + + Provides structured access to the matched route pattern, extracted path parameters, + HTTP method, headers, query parameters, and body. Available via ``app.request`` + inside middleware and, when added as a type-annotated parameter, inside route handlers. + + Examples + -------- + **Middleware usage** + + ```python + from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Request, Response + from aws_lambda_powertools.event_handler.middlewares import NextMiddleware + + app = APIGatewayRestResolver() + + def auth_middleware(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + request: Request = app.request + + route = request.route # "/applications/{application_id}" + path_params = request.path_parameters # {"application_id": "4da715ee-..."} + method = request.method # "PUT" + + if not is_authorized(route, method, path_params): + return Response(status_code=403, body="Forbidden") + + return next_middleware(app) + + app.use(middlewares=[auth_middleware]) + ``` + + **Route handler injection (type-annotated)** + + ```python + from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Request + + app = APIGatewayRestResolver() + + @app.get("/applications/") + def get_application(application_id: str, request: Request): + user_agent = request.headers.get("user-agent") + return {"id": application_id, "user_agent": user_agent} + ``` + """ + + __slots__ = ("_current_event", "_path_parameters", "_route_path") + + def __init__( + self, + route_path: str, + path_parameters: dict[str, Any], + current_event: BaseProxyEvent, + ) -> None: + self._route_path = route_path + self._path_parameters = path_parameters + self._current_event = current_event + + @property + def route(self) -> str: + """Matched route pattern in OpenAPI path-template format. + + Examples + -------- + For a route registered as ``/applications/`` the value is + ``/applications/{application_id}``. + """ + return self._route_path + + @property + def path_parameters(self) -> dict[str, Any]: + """Extracted path parameters for the matched route. + + Examples + -------- + For a request to ``/applications/4da715ee``, matched against + ``/applications/``, the value is + ``{"application_id": "4da715ee"}``. + """ + return self._path_parameters + + @property + def method(self) -> str: + """HTTP method in upper-case, e.g. ``"GET"``, ``"PUT"``.""" + return self._current_event.http_method.upper() + + @property + def headers(self) -> dict[str, str]: + """Request headers dict (lower-cased keys may vary by event source).""" + return self._current_event.headers or {} + + @property + def query_parameters(self) -> dict[str, str] | None: + """Query string parameters, or ``None`` when none are present.""" + return self._current_event.query_string_parameters + + @property + def body(self) -> str | None: + """Raw request body string, or ``None`` when the request has no body.""" + return self._current_event.body + + @property + def json_body(self) -> Any: + """Request body deserialized as a Python object (dict / list), or ``None``.""" + return self._current_event.json_body diff --git a/tests/functional/event_handler/required_dependencies/test_request.py b/tests/functional/event_handler/required_dependencies/test_request.py new file mode 100644 index 00000000000..02ae0da5b88 --- /dev/null +++ b/tests/functional/event_handler/required_dependencies/test_request.py @@ -0,0 +1,588 @@ +"""Tests for the Request object feature (GH #7992). + +Covers: +- ``app.request`` availability in global and route-level middleware +- ``Request`` type-annotation injection in route handlers +- ``Request`` properties: route, path_parameters, method, headers, query_parameters, body +- ``RuntimeError`` when ``app.request`` is accessed outside of resolution +- Backward compatibility: routes without ``Request`` continue to work unchanged +- ``APIGatewayHttpResolver`` and ``ALBResolver`` variants +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pytest + +from aws_lambda_powertools.event_handler import ( + ALBResolver, + APIGatewayHttpResolver, + APIGatewayRestResolver, + Request, + Response, +) +from tests.functional.utils import load_event + +if TYPE_CHECKING: + from aws_lambda_powertools.event_handler.middlewares import NextMiddleware + +# --------------------------------------------------------------------------- +# Shared test events +# --------------------------------------------------------------------------- + +API_REST_EVENT = load_event("apiGatewayProxyEvent.json") # GET /my/path +API_RESTV2_EVENT = load_event("apiGatewayProxyV2Event_GET.json") + + +def _make_rest_event(path: str, method: str = "GET", path_parameters: dict | None = None, body: str | None = None): + """Build a minimal API Gateway REST (v1) proxy event.""" + return { + "httpMethod": method, + "path": path, + "pathParameters": path_parameters, + "queryStringParameters": None, + "multiValueQueryStringParameters": None, + "headers": {"Content-Type": "application/json", "user-agent": "pytest"}, + "multiValueHeaders": {}, + "body": body, + "isBase64Encoded": False, + "requestContext": {"httpMethod": method, "resourcePath": path}, + "resource": path, + "stageVariables": None, + } + + +# --------------------------------------------------------------------------- +# app.request in global middleware +# --------------------------------------------------------------------------- + + +def test_request_available_in_global_middleware(): + app = APIGatewayRestResolver() + captured: list[Request] = [] + + def capture_middleware(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[capture_middleware]) + + @app.get("/my/path") + def handler(): + return {} + + app(API_REST_EVENT, {}) + + assert len(captured) == 1 + req = captured[0] + assert isinstance(req, Request) + assert req.route == "/my/path" + assert req.method == "GET" + + +def test_request_route_pattern_uses_openapi_format(): + """route property should use {param} OpenAPI notation, not Powertools notation.""" + app = APIGatewayRestResolver() + captured: list[Request] = [] + + def mw(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/applications/") + def handler(application_id: str): + return {} + + event = _make_rest_event( + "/applications/42", + path_parameters={"application_id": "42"}, + ) + app(event, {}) + + assert captured[0].route == "/applications/{application_id}" + + +def test_request_path_parameters_in_middleware(): + app = APIGatewayRestResolver() + captured: list[dict] = [] + + def mw(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + captured.append(app.request.path_parameters) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/applications/") + def handler(application_id: str): + return {} + + event = _make_rest_event( + "/applications/4da715ee", + path_parameters={"application_id": "4da715ee"}, + ) + app(event, {}) + + assert captured == [{"application_id": "4da715ee"}] + + +def test_request_method_in_middleware(): + app = APIGatewayRestResolver() + methods_seen: list[str] = [] + + def mw(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + methods_seen.append(app.request.method) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.put("/items/") + def handler(item_id: str): + return {} + + event = _make_rest_event("/items/99", method="PUT", path_parameters={"item_id": "99"}) + app(event, {}) + + assert methods_seen == ["PUT"] + + +def test_request_headers_in_middleware(): + app = APIGatewayRestResolver() + headers_seen: list[dict] = [] + + def mw(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + headers_seen.append(app.request.headers) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/my/path") + def handler(): + return {} + + app(API_REST_EVENT, {}) + + assert len(headers_seen) == 1 + # headers is a dict (may have varying casing depending on event source) + assert isinstance(headers_seen[0], dict) + + +def test_request_query_parameters_in_middleware(): + app = APIGatewayRestResolver() + captured: list = [] + + def mw(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + captured.append(app.request.query_parameters) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/search") + def handler(): + return {} + + event = _make_rest_event("/search") + event["queryStringParameters"] = {"q": "powertools"} + app(event, {}) + + assert captured == [{"q": "powertools"}] + + +def test_request_body_in_middleware(): + app = APIGatewayRestResolver() + bodies_seen: list = [] + + def mw(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + bodies_seen.append(app.request.body) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.post("/items") + def handler(): + return {} + + event = _make_rest_event("/items", method="POST", body='{"name": "widget"}') + event["httpMethod"] = "POST" + app(event, {}) + + assert bodies_seen == ['{"name": "widget"}'] + + +# --------------------------------------------------------------------------- +# Request injection in route handlers via type annotation +# --------------------------------------------------------------------------- + + +def test_request_injected_into_handler(): + app = APIGatewayRestResolver() + + received: list[Request] = [] + + @app.get("/my/path") + def handler(request: Request): + received.append(request) + return {} + + app(API_REST_EVENT, {}) + + assert len(received) == 1 + assert isinstance(received[0], Request) + assert received[0].route == "/my/path" + assert received[0].method == "GET" + + +def test_request_injected_alongside_path_params(): + app = APIGatewayRestResolver() + + received: list[tuple] = [] + + @app.get("/users/") + def handler(user_id: str, request: Request): + received.append((user_id, request)) + return {} + + event = _make_rest_event("/users/123", path_parameters={"user_id": "123"}) + app(event, {}) + + assert len(received) == 1 + user_id, req = received[0] + assert user_id == "123" + assert isinstance(req, Request) + assert req.path_parameters == {"user_id": "123"} + assert req.route == "/users/{user_id}" + + +def test_request_injection_parameter_name_is_flexible(): + """The parameter can be named anything as long as it is annotated as Request.""" + app = APIGatewayRestResolver() + + received: list[Request] = [] + + @app.get("/my/path") + def handler(req: Request): + received.append(req) + return {} + + app(API_REST_EVENT, {}) + + assert received[0].route == "/my/path" + + +def test_handler_without_request_annotation_unaffected(): + """Existing handlers with no Request annotation continue to work identically.""" + app = APIGatewayRestResolver() + + @app.get("/my/path") + def handler(): + return {"ok": True} + + result = app(API_REST_EVENT, {}) + assert result["statusCode"] == 200 + + +def test_handler_with_path_params_only_unaffected(): + """Handlers that only use path params continue to work identically.""" + app = APIGatewayRestResolver() + + @app.get("/users/") + def handler(user_id: str): + return {"id": user_id} + + event = _make_rest_event("/users/42", path_parameters={"user_id": "42"}) + result = app(event, {}) + assert result["statusCode"] == 200 + + +# --------------------------------------------------------------------------- +# Request injection caching (idempotency across multiple calls) +# --------------------------------------------------------------------------- + + +def test_request_injection_works_across_multiple_invocations(): + """Injection must work correctly on repeated calls (cached param name must stay valid).""" + app = APIGatewayRestResolver() + call_count = 0 + + @app.get("/counters/") + def handler(counter_id: str, request: Request): + nonlocal call_count + call_count += 1 + assert request.path_parameters["counter_id"] == counter_id + return {} + + for i in range(3): + event = _make_rest_event(f"/counters/{i}", path_parameters={"counter_id": str(i)}) + result = app(event, {}) + assert result["statusCode"] == 200 + + assert call_count == 3 + + +# --------------------------------------------------------------------------- +# RuntimeError when accessed outside of request resolution +# --------------------------------------------------------------------------- + + +def test_request_raises_before_resolution(): + app = APIGatewayRestResolver() + with pytest.raises(RuntimeError, match="app.request is only available after route resolution"): + _ = app.request + + +# --------------------------------------------------------------------------- +# Route-level middleware also gets app.request +# --------------------------------------------------------------------------- + + +def test_request_available_in_route_level_middleware(): + app = APIGatewayRestResolver() + captured: list[Request] = [] + + def route_mw(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + captured.append(app.request) + return next_middleware(app) + + @app.get("/protected/", middlewares=[route_mw]) + def handler(resource_id: str): + return {} + + event = _make_rest_event("/protected/abc", path_parameters={"resource_id": "abc"}) + app(event, {}) + + assert len(captured) == 1 + assert captured[0].route == "/protected/{resource_id}" + assert captured[0].path_parameters == {"resource_id": "abc"} + + +# --------------------------------------------------------------------------- +# Other resolver types +# --------------------------------------------------------------------------- + + +def test_request_available_in_http_resolver_middleware(): + app = APIGatewayHttpResolver() + captured: list[Request] = [] + + def mw(app, next_middleware): + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/my/path") + def handler(): + return {} + + app(API_RESTV2_EVENT, {}) + + assert len(captured) == 1 + assert captured[0].method == "GET" + + +def test_request_available_in_alb_middleware(): + alb_event = load_event("albEvent.json") + app = ALBResolver() + captured: list[Request] = [] + + def mw(app, next_middleware): + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[mw]) + + # Register a route that matches the ALB event's path + path = alb_event.get("path", "/lambda") + + @app.get(path) + def handler(): + return {} + + app(alb_event, {}) + + assert len(captured) == 1 + assert isinstance(captured[0], Request) + + +# --------------------------------------------------------------------------- +# Router / include_router pattern +# --------------------------------------------------------------------------- + + +def test_request_available_in_middleware_with_include_router(): + """app.request must work in middleware when routes come from an included Router.""" + from aws_lambda_powertools.event_handler.api_gateway import Router + + app = APIGatewayRestResolver() + router = Router() + captured: list[Request] = [] + + def mw(app, next_middleware): + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @router.get("/users/") + def get_user(user_id: str): + return {"id": user_id} + + app.include_router(router) + + event = _make_rest_event("/users/abc", path_parameters={"user_id": "abc"}) + result = app(event, {}) + + assert result["statusCode"] == 200 + assert len(captured) == 1 + assert captured[0].route == "/users/{user_id}" + assert captured[0].path_parameters == {"user_id": "abc"} + + +def test_request_injected_in_handler_with_include_router(): + """Request injection via type annotation must work when routes come from an included Router.""" + from aws_lambda_powertools.event_handler.api_gateway import Router + + app = APIGatewayRestResolver() + router = Router() + received: list[Request] = [] + + @router.get("/items/") + def get_item(item_id: str, request: Request): + received.append(request) + return {"id": item_id} + + app.include_router(router) + + event = _make_rest_event("/items/xyz", path_parameters={"item_id": "xyz"}) + result = app(event, {}) + + assert result["statusCode"] == 200 + assert len(received) == 1 + assert received[0].route == "/items/{item_id}" + assert received[0].path_parameters == {"item_id": "xyz"} + + +# --------------------------------------------------------------------------- +# Proxy+ use case (the original issue scenario) +# --------------------------------------------------------------------------- + + +def test_request_resolves_path_params_from_proxy_plus_event(): + """When API GW uses {proxy+}, app.current_event.pathParameters only has 'proxy'. + But app.request.path_parameters should have the *resolved* params from Powertools routing.""" + app = APIGatewayRestResolver() + captured: list[Request] = [] + + def auth_middleware(app, next_middleware): + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[auth_middleware]) + + @app.get("/applications/") + def get_application(application_id: str): + return {"id": application_id} + + @app.put("/applications/") + def put_application(application_id: str): + return {"updated": application_id} + + # Simulate a proxy+ event where API GW only knows about {proxy+} + event = { + "httpMethod": "PUT", + "path": "/applications/4da715ee-79d4-4e52-81cb-1ecc464708fb", + "pathParameters": {"proxy": "4da715ee-79d4-4e52-81cb-1ecc464708fb"}, + "queryStringParameters": None, + "multiValueQueryStringParameters": None, + "headers": {"Content-Type": "application/json"}, + "multiValueHeaders": {}, + "body": None, + "isBase64Encoded": False, + "requestContext": {"httpMethod": "PUT", "resourcePath": "/applications/{proxy+}"}, + "resource": "/applications/{proxy+}", + "stageVariables": None, + } + + result = app(event, {}) + + assert result["statusCode"] == 200 + assert len(captured) == 1 + + req = captured[0] + # Middleware sees the resolved route, NOT the proxy+ pattern + assert req.route == "/applications/{application_id}" + assert req.path_parameters == {"application_id": "4da715ee-79d4-4e52-81cb-1ecc464708fb"} + assert req.method == "PUT" + + +# --------------------------------------------------------------------------- +# Missing coverage: json_body, query_parameters=None, request caching +# --------------------------------------------------------------------------- + + +def test_request_json_body_in_middleware(): + app = APIGatewayRestResolver() + bodies_seen: list = [] + + def mw(app: APIGatewayRestResolver, next_middleware): + bodies_seen.append(app.request.json_body) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.post("/items") + def handler(): + return {} + + event = _make_rest_event("/items", method="POST", body='{"name": "widget"}') + app(event, {}) + + assert bodies_seen == [{"name": "widget"}] + + +def test_request_query_parameters_empty(): + """When no query string parameters are present, query_parameters returns empty or None.""" + app = APIGatewayRestResolver() + captured: list = [] + + def mw(app: APIGatewayRestResolver, next_middleware): + captured.append(app.request.query_parameters) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/my/path") + def handler(): + return {} + + event = _make_rest_event("/my/path") + app(event, {}) + + # No query params present — should be falsy (empty dict or None depending on event source) + assert not captured[0] + + +def test_request_is_cached_across_multiple_accesses(): + """Accessing app.request multiple times in the same invocation returns the same object.""" + app = APIGatewayRestResolver() + ids_seen: list[int] = [] + + def mw(app: APIGatewayRestResolver, next_middleware): + ids_seen.append(id(app.request)) + ids_seen.append(id(app.request)) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/my/path") + def handler(request: Request): + ids_seen.append(id(request)) + return {} + + app(API_REST_EVENT, {}) + + # All accesses should return the same cached instance + assert len(ids_seen) == 3 + assert ids_seen[0] == ids_seen[1] == ids_seen[2] From a3fc98cc172c63a0999c1575d777466e1ea9f168 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:29:56 +0800 Subject: [PATCH 17/84] chore(deps-dev): bump requests from 2.33.0 to 2.33.1 (#8104) Bumps [requests](https://github.com/psf/requests) from 2.33.0 to 2.33.1. - [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.0...v2.33.1) --- updated-dependencies: - dependency-name: requests dependency-version: 2.33.1 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> --- poetry.lock | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index e074b55374a..325992dbc03 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4121,14 +4121,14 @@ files = [ [[package]] name = "requests" -version = "2.33.0" +version = "2.33.1" description = "Python HTTP for Humans." optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "requests-2.33.0-py3-none-any.whl", hash = "sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b"}, - {file = "requests-2.33.0.tar.gz", hash = "sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652"}, + {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}, + {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}, ] [package.dependencies] @@ -4139,7 +4139,6 @@ urllib3 = ">=1.26,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -test = ["PySocks (>=1.5.6,!=1.5.7)", "pytest (>=3)", "pytest-cov", "pytest-httpbin (==2.1.0)", "pytest-mock", "pytest-xdist"] use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] From 8a6eb0b09b7084344080fd5c50a7095ac0a97e5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:31:31 +0800 Subject: [PATCH 18/84] chore(deps-dev): bump ruff from 0.15.8 to 0.15.9 in the dev-dependencies group (#8100) chore(deps-dev): bump ruff in the dev-dependencies group Bumps the dev-dependencies group with 1 update: [ruff](https://github.com/astral-sh/ruff). Updates `ruff` from 0.15.8 to 0.15.9 - [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.8...0.15.9) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.15.9 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 | 40 ++++++++++++++++++++-------------------- pyproject.toml | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/poetry.lock b/poetry.lock index 325992dbc03..cd7f97cdbdf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4301,30 +4301,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.8" +version = "0.15.9" 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.8-py3-none-linux_armv6l.whl", hash = "sha256:cbe05adeba76d58162762d6b239c9056f1a15a55bd4b346cfd21e26cd6ad7bc7"}, - {file = "ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d3e3d0b6ba8dca1b7ef9ab80a28e840a20070c4b62e56d675c24f366ef330570"}, - {file = "ruff-0.15.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ee3ae5c65a42f273f126686353f2e08ff29927b7b7e203b711514370d500de3"}, - {file = "ruff-0.15.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdce027ada77baa448077ccc6ebb2fa9c3c62fd110d8659d601cf2f475858d94"}, - {file = "ruff-0.15.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12e617fc01a95e5821648a6df341d80456bd627bfab8a829f7cfc26a14a4b4a3"}, - {file = "ruff-0.15.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:432701303b26416d22ba696c39f2c6f12499b89093b61360abc34bcc9bf07762"}, - {file = "ruff-0.15.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d910ae974b7a06a33a057cb87d2a10792a3b2b3b35e33d2699fdf63ec8f6b17a"}, - {file = "ruff-0.15.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2033f963c43949d51e6fdccd3946633c6b37c484f5f98c3035f49c27395a8ab8"}, - {file = "ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f29b989a55572fb885b77464cf24af05500806ab4edf9a0fd8977f9759d85b1"}, - {file = "ruff-0.15.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:ac51d486bf457cdc985a412fb1801b2dfd1bd8838372fc55de64b1510eff4bec"}, - {file = "ruff-0.15.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c9861eb959edab053c10ad62c278835ee69ca527b6dcd72b47d5c1e5648964f6"}, - {file = "ruff-0.15.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8d9a5b8ea13f26ae90838afc33f91b547e61b794865374f114f349e9036835fb"}, - {file = "ruff-0.15.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c2a33a529fb3cbc23a7124b5c6ff121e4d6228029cba374777bd7649cc8598b8"}, - {file = "ruff-0.15.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:75e5cd06b1cf3f47a3996cfc999226b19aa92e7cce682dcd62f80d7035f98f49"}, - {file = "ruff-0.15.8-py3-none-win32.whl", hash = "sha256:bc1f0a51254ba21767bfa9a8b5013ca8149dcf38092e6a9eb704d876de94dc34"}, - {file = "ruff-0.15.8-py3-none-win_amd64.whl", hash = "sha256:04f79eff02a72db209d47d665ba7ebcad609d8918a134f86cb13dd132159fc89"}, - {file = "ruff-0.15.8-py3-none-win_arm64.whl", hash = "sha256:cf891fa8e3bb430c0e7fac93851a5978fc99c8fa2c053b57b118972866f8e5f2"}, - {file = "ruff-0.15.8.tar.gz", hash = "sha256:995f11f63597ee362130d1d5a327a87cb6f3f5eae3094c620bcc632329a4d26e"}, + {file = "ruff-0.15.9-py3-none-linux_armv6l.whl", hash = "sha256:6efbe303983441c51975c243e26dff328aca11f94b70992f35b093c2e71801e1"}, + {file = "ruff-0.15.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4965bac6ac9ea86772f4e23587746f0b7a395eccabb823eb8bfacc3fa06069f7"}, + {file = "ruff-0.15.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf05aad70ca5b5a0a4b0e080df3a6b699803916d88f006efd1f5b46302daab8"}, + {file = "ruff-0.15.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9439a342adb8725f32f92732e2bafb6d5246bd7a5021101166b223d312e8fc59"}, + {file = "ruff-0.15.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c5e6faf9d97c8edc43877c3f406f47446fc48c40e1442d58cfcdaba2acea745"}, + {file = "ruff-0.15.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b34a9766aeec27a222373d0b055722900fbc0582b24f39661aa96f3fe6ad901"}, + {file = "ruff-0.15.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89dd695bc72ae76ff484ae54b7e8b0f6b50f49046e198355e44ea656e521fef9"}, + {file = "ruff-0.15.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce187224ef1de1bd225bc9a152ac7102a6171107f026e81f317e4257052916d5"}, + {file = "ruff-0.15.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b0c7c341f68adb01c488c3b7d4b49aa8ea97409eae6462d860a79cf55f431b6"}, + {file = "ruff-0.15.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:55cc15eee27dc0eebdfcb0d185a6153420efbedc15eb1d38fe5e685657b0f840"}, + {file = "ruff-0.15.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6537f6eed5cda688c81073d46ffdfb962a5f29ecb6f7e770b2dc920598997ed"}, + {file = "ruff-0.15.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6d3fcbca7388b066139c523bda744c822258ebdcfbba7d24410c3f454cc9af71"}, + {file = "ruff-0.15.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:058d8e99e1bfe79d8a0def0b481c56059ee6716214f7e425d8e737e412d69677"}, + {file = "ruff-0.15.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8e1ddb11dbd61d5983fa2d7d6370ef3eb210951e443cace19594c01c72abab4c"}, + {file = "ruff-0.15.9-py3-none-win32.whl", hash = "sha256:bde6ff36eaf72b700f32b7196088970bf8fdb2b917b7accd8c371bfc0fd573ec"}, + {file = "ruff-0.15.9-py3-none-win_amd64.whl", hash = "sha256:45a70921b80e1c10cf0b734ef09421f71b5aa11d27404edc89d7e8a69505e43d"}, + {file = "ruff-0.15.9-py3-none-win_arm64.whl", hash = "sha256:0694e601c028fd97dc5c6ee244675bc241aeefced7ef80cd9c6935a871078f53"}, + {file = "ruff-0.15.9.tar.gz", hash = "sha256:29cbb1255a9797903f6dde5ba0188c707907ff44a9006eb273b5a17bfa0739a2"}, ] [[package]] @@ -5179,4 +5179,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "8ea7e1c9ec1c0ca0d1db0911890d085c1ce4e0d9128d710b3317299600f62154" +content-hash = "ce9536cb09ab6326e9420027a1986fe78a8f4a803f924eed430a0e27a0ae65ff" diff --git a/pyproject.toml b/pyproject.toml index 9f23f734dd1..73bbaf680c7 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.9" +ruff = ">=0.5.1,<0.15.10" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.8" types-redis = "^4.6.0.7" From 779c85ce22502dfa62f26f34028961efb478f178 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:33:43 +0800 Subject: [PATCH 19/84] chore(deps-dev): bump types-requests from 2.32.4.20260107 to 2.33.0.20260402 (#8102) chore(deps-dev): bump types-requests Bumps [types-requests](https://github.com/python/typeshed) from 2.32.4.20260107 to 2.33.0.20260402. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-version: 2.33.0.20260402 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 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index cd7f97cdbdf..9ed51a3795a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4745,14 +4745,14 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.32.4.20260107" +version = "2.33.0.20260402" description = "Typing stubs for requests" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_requests-2.32.4.20260107-py3-none-any.whl", hash = "sha256:b703fe72f8ce5b31ef031264fe9395cac8f46a04661a79f7ed31a80fb308730d"}, - {file = "types_requests-2.32.4.20260107.tar.gz", hash = "sha256:018a11ac158f801bfa84857ddec1650750e393df8a004a8a9ae2a9bec6fcb24f"}, + {file = "types_requests-2.33.0.20260402-py3-none-any.whl", hash = "sha256:c98372d7124dd5d10af815ee25c013897592ff92af27b27e22c98984102c3254"}, + {file = "types_requests-2.33.0.20260402.tar.gz", hash = "sha256:1bdd3ada9b869741c5c4b887d2c8b4e38284a1449751823b5ebbccba3eefd9da"}, ] [package.dependencies] From 30e43c1507ef55db7293eed57c4a029130aef2c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:36:23 +0800 Subject: [PATCH 20/84] chore(deps-dev): bump aws-cdk-aws-lambda-python-alpha from 2.243.0a0 to 2.248.0a0 (#8103) 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.243.0a0 to 2.248.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.248.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 | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9ed51a3795a..d2ff34ced56 100644 --- a/poetry.lock +++ b/poetry.lock @@ -93,18 +93,18 @@ zstandard = ["zstandard"] [[package]] name = "aws-cdk-asset-awscli-v1" -version = "2.2.263" +version = "2.2.273" description = "A library that contains the AWS CLI for use in Lambda Layers" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_asset_awscli_v1-2.2.263-py3-none-any.whl", hash = "sha256:185150757d4216ea982d7b35596de5b3d767776be00cd78cacce02eaa08f8851"}, - {file = "aws_cdk_asset_awscli_v1-2.2.263.tar.gz", hash = "sha256:657605260ace055fac4ae30a6fb84a80504a6e24ce0b1d278913d4db4bafa266"}, + {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.125.0,<2.0.0" +jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" @@ -205,18 +205,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-lambda-python-alpha" -version = "2.243.0a0" +version = "2.248.0a0" description = "The CDK Construct Library for AWS Lambda in Python" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_aws_lambda_python_alpha-2.243.0a0-py3-none-any.whl", hash = "sha256:96f9d7281dd84f1bff3cc8b8e0d403589f957845c6ba2a34a570dd8d7b776e0e"}, - {file = "aws_cdk_aws_lambda_python_alpha-2.243.0a0.tar.gz", hash = "sha256:d97718daedab795f9652ab7799ac3d206a6dd33efa5e622b60c8fa5cc6a526d2"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.248.0a0-py3-none-any.whl", hash = "sha256:bf9303515649511fb5299ef36cfcdc042f3422de05321ed30f565dcb3642737f"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.248.0a0.tar.gz", hash = "sha256:2b5f4f3a2ca249355fd86509da800ae36b2e368cfec76372dc3dd25f25ef23af"}, ] [package.dependencies] -aws-cdk-lib = ">=2.243.0,<3.0.0" +aws-cdk-lib = ">=2.248.0,<3.0.0" constructs = ">=10.5.0,<11.0.0" jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" @@ -224,37 +224,37 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-cloud-assembly-schema" -version = "52.2.0" +version = "53.13.0" description = "Schema for the protocol between CDK framework and CDK CLI" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_cloud_assembly_schema-52.2.0-py3-none-any.whl", hash = "sha256:87b918589f7d627f45e330726f592ec0b39056e1403558f3a1ba8a2134dacd6f"}, - {file = "aws_cdk_cloud_assembly_schema-52.2.0.tar.gz", hash = "sha256:737309e2c7c7e4b46bd669cb9fe8799a36424c9a174523b54833cf1cd12b5e3f"}, + {file = "aws_cdk_cloud_assembly_schema-53.13.0-py3-none-any.whl", hash = "sha256:b6612da9451a23e1f1ddacfe94dc5359b5ca42bad91a923b04a3d12e14078016"}, + {file = "aws_cdk_cloud_assembly_schema-53.13.0.tar.gz", hash = "sha256:d0f4ed7f8122f57d62983c0274d10480909e4b15362d28ff1f9b505e2bd92a72"}, ] [package.dependencies] -jsii = ">=1.121.0,<2.0.0" +jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.243.0" +version = "2.248.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.243.0-py3-none-any.whl", hash = "sha256:9de49529fbca82680c7e4fa28040bf3895efd4250a32c812d31133c2274708b5"}, - {file = "aws_cdk_lib-2.243.0.tar.gz", hash = "sha256:ae39b90d0eef422293d22c6f2c67c5e1edfbfce7a5135a463f29e7c23538318c"}, + {file = "aws_cdk_lib-2.248.0-py3-none-any.whl", hash = "sha256:e89db288365371e6b42aaae8b45ad2064615dfbe87e95741a2f2bb7ec1f33dad"}, + {file = "aws_cdk_lib-2.248.0.tar.gz", hash = "sha256:a00c73bfa6865ef62d700d6f97dd4124979ccfe69dc1ef70f2526aa49c52bbc8"}, ] [package.dependencies] -"aws-cdk.asset-awscli-v1" = "2.2.263" +"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" = ">=52.1.0,<53.0.0" +"aws-cdk.cloud-assembly-schema" = ">=53.0.0,<54.0.0" constructs = ">=10.5.0,<11.0.0" jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" From 2b95d7fac406ef127969f28a1d60ec99a42d77fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:38:29 +0800 Subject: [PATCH 21/84] chore(deps-dev): bump isort from 7.0.0 to 8.0.1 (#8101) Bumps [isort](https://github.com/PyCQA/isort) from 7.0.0 to 8.0.1. - [Release notes](https://github.com/PyCQA/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/PyCQA/isort/compare/7.0.0...8.0.1) --- updated-dependencies: - dependency-name: isort dependency-version: 8.0.1 dependency-type: direct:development 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 | 9 ++++----- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index d2ff34ced56..f8d475fc473 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2224,19 +2224,18 @@ files = [ [[package]] name = "isort" -version = "7.0.0" +version = "8.0.1" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.10.0" groups = ["dev"] files = [ - {file = "isort-7.0.0-py3-none-any.whl", hash = "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1"}, - {file = "isort-7.0.0.tar.gz", hash = "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187"}, + {file = "isort-8.0.1-py3-none-any.whl", hash = "sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75"}, + {file = "isort-8.0.1.tar.gz", hash = "sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d"}, ] [package.extras] colors = ["colorama"] -plugins = ["setuptools"] [[package]] name = "jinja2" @@ -5179,4 +5178,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "ce9536cb09ab6326e9420027a1986fe78a8f4a803f924eed430a0e27a0ae65ff" +content-hash = "f89f84ee54e29c9efaca37b5102e899b8a15a84b862f78196aa6b26f3c21f180" diff --git a/pyproject.toml b/pyproject.toml index 73bbaf680c7..39598824dce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ kafka-consumer-protobuf = ["protobuf"] coverage = { extras = ["toml"], version = "^7.6" } pytest = ">=8.3.4,<10.0.0" boto3 = "^1.26.164" -isort = ">=5.13.2,<8.0.0" +isort = ">=5.13.2,<9.0.0" pytest-cov = ">=5,<8" pytest-mock = "^3.14.0" pytest-asyncio = ">=0.24,<1.4" From 74fbcc51cdfb45fea1146e2da7745afa3df5a301 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 15:58:40 +0800 Subject: [PATCH 22/84] fix(event_handler): sync middleware receives real response in async ASGI context (#8089) fix: resolve ASGI --- .../event_handler/http_resolver.py | 80 +++++++++++------ .../_pydantic/test_http_resolver_pydantic.py | 86 ++++++++++++++++++- 2 files changed, 140 insertions(+), 26 deletions(-) diff --git a/aws_lambda_powertools/event_handler/http_resolver.py b/aws_lambda_powertools/event_handler/http_resolver.py index 0be443bd200..93e2fdc932e 100644 --- a/aws_lambda_powertools/event_handler/http_resolver.py +++ b/aws_lambda_powertools/event_handler/http_resolver.py @@ -3,6 +3,7 @@ import asyncio import base64 import inspect +import threading import warnings from typing import TYPE_CHECKING, Any, Callable from urllib.parse import parse_qs @@ -324,36 +325,65 @@ async def final_handler(app): return await next_handler(self) def _wrap_middleware_async(self, middleware: Callable, next_handler: Callable) -> Callable: - """Wrap a middleware to work in async context.""" + """Wrap a middleware to work in async context. + + For sync middlewares, we split execution into pre/post phases around the + call to next(). The sync middleware runs its pre-processing (e.g. request + validation), then we intercept the next() call, await the async handler, + and resume the middleware with the real response so post-processing + (e.g. response validation) sees the actual data. + """ async def wrapped(app): - # Create a next_middleware that the sync middleware can call - def sync_next(app): - # This will be called by sync middleware - # We need to run the async next_handler - loop = asyncio.get_event_loop() - if loop.is_running(): - # We're in an async context, create a task - future = asyncio.ensure_future(next_handler(app)) - # Store for later await - app.context["_async_next_result"] = future - return Response(status_code=200, body="") # Placeholder - else: # pragma: no cover - return loop.run_until_complete(next_handler(app)) - - # Check if middleware is async if inspect.iscoroutinefunction(middleware): - result = await middleware(app, next_handler) - else: - # Sync middleware - need special handling - result = middleware(app, sync_next) + return await middleware(app, next_handler) - # Check if we stored an async result - if "_async_next_result" in app.context: - future = app.context.pop("_async_next_result") - result = await future + # We use an Event to coordinate: the sync middleware runs in a thread, + # calls sync_next which signals us to resolve the async handler, + # then waits for the real response. + middleware_called_next = asyncio.Event() + next_app_holder: list = [] + real_response_holder: list = [] + middleware_result_holder: list = [] + middleware_error_holder: list = [] - return result + def sync_next(app): + next_app_holder.append(app) + middleware_called_next.set() + # Block this thread until the real response is available + event = threading.Event() + next_app_holder.append(event) + event.wait() + return real_response_holder[0] + + def run_middleware(): + try: + result = middleware(app, sync_next) + middleware_result_holder.append(result) + except Exception as e: + middleware_error_holder.append(e) + + thread = threading.Thread(target=run_middleware, daemon=True) + thread.start() + + # Wait for the middleware to call next() + await middleware_called_next.wait() + + # Now resolve the async next_handler + real_response = await next_handler(next_app_holder[0]) + real_response_holder.append(real_response) + + # Signal the thread that the response is ready + threading_event = next_app_holder[1] + threading_event.set() + + # Wait for the middleware thread to finish + thread.join() + + if middleware_error_holder: + raise middleware_error_holder[0] + + return middleware_result_holder[0] return wrapped 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 d31185f3239..7cab58a1b70 100644 --- a/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py +++ b/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py @@ -209,7 +209,6 @@ def search( # ============================================================================= -@pytest.mark.skip("Due to issue #7981.") @pytest.mark.asyncio async def test_async_handler_with_validation(): # GIVEN an app with async handler and validation @@ -241,6 +240,91 @@ async def create_user(user: UserModel) -> UserResponse: assert body["user"]["name"] == "AsyncUser" +@pytest.mark.asyncio +async def test_async_handler_invalid_response_returns_422(): + # GIVEN an app with async handler and validation + app = HttpResolverLocal(enable_validation=True) + + @app.get("/user") + async def get_user() -> UserResponse: + await asyncio.sleep(0.001) + return {"name": "John"} # type: ignore # Missing required fields + + scope = { + "type": "http", + "method": "GET", + "path": "/user", + "query_string": b"", + "headers": [(b"content-type", b"application/json")], + } + + receive = make_asgi_receive() + send, captured = make_asgi_send() + + # WHEN called via ASGI interface + await app(scope, receive, send) + + # THEN it returns 422 for invalid response + assert captured["status_code"] == 422 + + +@pytest.mark.asyncio +async def test_sync_handler_with_validation_via_asgi(): + # GIVEN an app with a sync handler and validation, called via ASGI + app = HttpResolverLocal(enable_validation=True) + + @app.post("/users") + def create_user(user: UserModel) -> UserResponse: + return UserResponse(id="sync-123", user=user) + + scope = { + "type": "http", + "method": "POST", + "path": "/users", + "query_string": b"", + "headers": [(b"content-type", b"application/json")], + } + + receive = make_asgi_receive(b'{"name": "SyncUser", "age": 30}') + send, captured = make_asgi_send() + + # WHEN called via ASGI interface + await app(scope, receive, send) + + # THEN validation works with sync handler + assert captured["status_code"] == 200 + body = json.loads(captured["body"]) + assert body["id"] == "sync-123" + assert body["user"]["name"] == "SyncUser" + + +@pytest.mark.asyncio +async def test_sync_handler_invalid_response_returns_422_via_asgi(): + # GIVEN an app with a sync handler and validation, called via ASGI + app = HttpResolverLocal(enable_validation=True) + + @app.get("/user") + def get_user() -> UserResponse: + return {"name": "John"} # type: ignore # Missing required fields + + scope = { + "type": "http", + "method": "GET", + "path": "/user", + "query_string": b"", + "headers": [(b"content-type", b"application/json")], + } + + receive = make_asgi_receive() + send, captured = make_asgi_send() + + # WHEN called via ASGI interface + await app(scope, receive, send) + + # THEN it returns 422 for invalid response + assert captured["status_code"] == 422 + + # ============================================================================= # OpenAPI Tests # ============================================================================= From ccdc52e1bd64c5bc48e796fad18af29ef757ee9e Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 16:06:25 +0800 Subject: [PATCH 23/84] fix(data_classes): support {proxy+} and path parameters in authorizer response (#8092) --- .../api_gateway_authorizer_event.py | 2 +- .../test_api_gateway_authorizer.py | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py b/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py index c73eb33b9fe..6d05984128e 100644 --- a/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py +++ b/aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py @@ -437,7 +437,7 @@ class APIGatewayAuthorizerResponse: - https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html """ - path_regex = r"^[/.a-zA-Z0-9-_\*]+$" + path_regex = r"^[/.a-zA-Z0-9\-_\*\{\}\+]+$" """The regular expression used to validate resource paths for the policy""" def __init__( diff --git a/tests/unit/data_classes/required_dependencies/test_api_gateway_authorizer.py b/tests/unit/data_classes/required_dependencies/test_api_gateway_authorizer.py index 1fad5176672..c26c1a417e7 100644 --- a/tests/unit/data_classes/required_dependencies/test_api_gateway_authorizer.py +++ b/tests/unit/data_classes/required_dependencies/test_api_gateway_authorizer.py @@ -200,6 +200,40 @@ def test_authorizer_response_allow_route_with_underscore(builder: APIGatewayAuth } +def test_authorizer_response_allow_route_with_proxy_plus(builder: APIGatewayAuthorizerResponse): + builder.allow_route(http_method="GET", resource="/{proxy+}") + assert builder.asdict() == { + "principalId": "foo", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "execute-api:Invoke", + "Effect": "Allow", + "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/GET/{proxy+}"], + }, + ], + }, + } + + +def test_authorizer_response_allow_route_with_path_parameter(builder: APIGatewayAuthorizerResponse): + builder.allow_route(http_method="GET", resource="/users/{user_id}") + assert builder.asdict() == { + "principalId": "foo", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "execute-api:Invoke", + "Effect": "Allow", + "Resource": ["arn:aws:execute-api:us-west-1:123456789:fantom/dev/GET/users/{user_id}"], + }, + ], + }, + } + + def test_parse_api_gateway_arn_with_resource(): mock_event = { "type": "TOKEN", From 7c9589ced1703e595f976f605db4396d2b186cf6 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 16:14:08 +0800 Subject: [PATCH 24/84] feat(event_handler): add Cookie parameter support for OpenAPI utility (#8095) feat(event_handler): add support for cookie field in OpenAPI utility --- .../middlewares/openapi_validation.py | 9 +- .../event_handler/openapi/params.py | 73 +++++ .../data_classes/api_gateway_proxy_event.py | 11 + .../utilities/data_classes/common.py | 41 +++ .../test_openapi_validation_middleware.py | 295 ++++++++++++++++++ 5 files changed, 428 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py index dbfc0a6f9d7..1bfe416dac7 100644 --- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py @@ -96,10 +96,17 @@ def handler(self, app: EventHandlerInstance, next_middleware: NextMiddleware) -> headers, ) + # Process cookie values + cookie_values, cookie_errors = _request_params_to_args( + route.dependant.cookie_params, + app.current_event.resolved_cookies_field, + ) + values.update(path_values) values.update(query_values) values.update(header_values) - errors += path_errors + query_errors + header_errors + values.update(cookie_values) + errors += path_errors + query_errors + header_errors + cookie_errors # Process the request body, if it exists if route.dependant.body_params: diff --git a/aws_lambda_powertools/event_handler/openapi/params.py b/aws_lambda_powertools/event_handler/openapi/params.py index 8b70b7cb074..534a20a5686 100644 --- a/aws_lambda_powertools/event_handler/openapi/params.py +++ b/aws_lambda_powertools/event_handler/openapi/params.py @@ -658,6 +658,79 @@ def alias(self, value: str | None = None): self._alias = value.lower() +class Cookie(Param): # type: ignore[misc] + """ + A class used internally to represent a cookie parameter in a path operation. + """ + + in_ = ParamTypes.cookie + + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + # MAINTENANCE: update when deprecating Pydantic v1, import these types + # str | AliasPath | AliasChoices | None + validation_alias: str | None = _Unset, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: bool | None = None, + include_in_schema: bool = True, + json_schema_extra: dict[str, Any] | None = None, + **extra: Any, + ): + super().__init__( + default=default, + default_factory=default_factory, + annotation=annotation, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, + examples=examples, + openapi_examples=openapi_examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + class Body(FieldInfo): # type: ignore[misc] """ A class used internally to represent a body parameter in a path operation. diff --git a/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py b/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py index 540e86a5c51..6e24873e6d7 100644 --- a/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py +++ b/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py @@ -280,6 +280,17 @@ def raw_query_string(self) -> str: def cookies(self) -> list[str]: return self.get("cookies") or [] + @property + def resolved_cookies_field(self) -> dict[str, str]: + """ + Parse cookies from the dedicated ``cookies`` field in API Gateway HTTP API v2 format. + + The ``cookies`` field contains a list of strings like ``["session=abc", "theme=dark"]``. + """ + from aws_lambda_powertools.utilities.data_classes.common import _parse_cookie_string + + return _parse_cookie_string("; ".join(self.cookies)) + @property def request_context(self) -> RequestContextV2: return RequestContextV2(self["requestContext"]) diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index a85d7b2d2a8..c35a02cc3ce 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -29,6 +29,17 @@ ) +def _parse_cookie_string(cookie_string: str) -> dict[str, str]: + """Parse a cookie string (``key=value; key2=value2``) into a dict.""" + cookies: dict[str, str] = {} + for segment in cookie_string.split(";"): + stripped = segment.strip() + if "=" in stripped: + name, _, value = stripped.partition("=") + cookies[name.strip()] = value.strip() + return cookies + + class CaseInsensitiveDict(dict): """Case insensitive dict implementation. Assumes string keys only.""" @@ -203,6 +214,36 @@ def resolved_headers_field(self) -> dict[str, str]: """ return self.headers + @property + def resolved_cookies_field(self) -> dict[str, str]: + """ + This property extracts cookies from the request as a dict of name-value pairs. + + By default, cookies are parsed from the ``Cookie`` header. + Uses ``self.headers`` (CaseInsensitiveDict) first for reliable case-insensitive + lookup, then falls back to ``resolved_headers_field`` for proxies that only + populate multi-value headers (e.g., ALB without single-value headers). + Subclasses may override this for event formats that provide cookies + in a dedicated field (e.g., API Gateway HTTP API v2). + """ + # Primary: self.headers is CaseInsensitiveDict — case-insensitive lookup + cookie_value: str | list[str] = self.headers.get("cookie") or "" + + # Fallback: resolved_headers_field covers ALB/REST v1 multi-value headers + # where the event may not have a single-value 'headers' dict at all + if not cookie_value: + headers = self.resolved_headers_field or {} + cookie_value = headers.get("cookie") or headers.get("Cookie") or "" + + # Multi-value headers (ALB, REST v1) may return a list + if isinstance(cookie_value, list): + cookie_value = "; ".join(cookie_value) + + if not cookie_value: + return {} + + return _parse_cookie_string(cookie_value) + @property def is_base64_encoded(self) -> bool | None: return self.get("isBase64Encoded") 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 21bc9b26e0a..01935d3aba3 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py @@ -3327,3 +3327,298 @@ def handler(items: Annotated[Union[_Item, List[_Item]], Body()]) -> Dict[str, An status, body = _post_json(app, "/items", big_payload) assert status == 200 assert body["count"] == 100 + + +# ---------- Cookie parameter tests ---------- + + +def test_cookie_param_basic(gw_event): + """Test basic cookie parameter extraction from REST API v1 (Cookie header).""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler(session_id: Annotated[str, Cookie()]): + return {"session_id": session_id} + + gw_event["path"] = "/me" + gw_event["headers"]["cookie"] = "session_id=abc123; theme=dark" + # Clear multiValueHeaders to avoid interference + gw_event.pop("multiValueHeaders", None) + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["session_id"] == "abc123" + + +def test_cookie_param_missing_required(gw_event): + """Test that a missing required cookie returns 422.""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler(session_id: Annotated[str, Cookie()]): + return {"session_id": session_id} + + gw_event["path"] = "/me" + gw_event["headers"]["cookie"] = "theme=dark" + gw_event.pop("multiValueHeaders", None) + + result = app(gw_event, {}) + assert result["statusCode"] == 422 + + +def test_cookie_param_with_default(gw_event): + """Test cookie parameter with a default value when cookie is absent.""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler(theme: Annotated[str, Cookie()] = "light"): + return {"theme": theme} + + gw_event["path"] = "/me" + gw_event["headers"].pop("cookie", None) + gw_event.pop("multiValueHeaders", None) + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["theme"] == "light" + + +def test_cookie_param_multiple_cookies(gw_event): + """Test extracting multiple cookie parameters.""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler( + session_id: Annotated[str, Cookie()], + theme: Annotated[str, Cookie()] = "light", + ): + return {"session_id": session_id, "theme": theme} + + gw_event["path"] = "/me" + gw_event["headers"]["cookie"] = "session_id=abc123; theme=dark" + gw_event.pop("multiValueHeaders", None) + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["session_id"] == "abc123" + assert body["theme"] == "dark" + + +def test_cookie_param_int_validation(gw_event): + """Test cookie parameter with int type validation.""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler(visits: Annotated[int, Cookie()]): + return {"visits": visits} + + gw_event["path"] = "/me" + gw_event["headers"]["cookie"] = "visits=42" + gw_event.pop("multiValueHeaders", None) + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["visits"] == 42 + + # Invalid int + gw_event["headers"]["cookie"] = "visits=not_a_number" + result = app(gw_event, {}) + assert result["statusCode"] == 422 + + +def test_cookie_param_http_api_v2(gw_event_http): + """Test cookie parameter with HTTP API v2 (dedicated cookies field).""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/me") + def handler(session_id: Annotated[str, Cookie()]): + return {"session_id": session_id} + + gw_event_http["rawPath"] = "/me" + gw_event_http["requestContext"]["http"]["method"] = "GET" + gw_event_http["cookies"] = ["session_id=xyz789", "theme=dark"] + + result = app(gw_event_http, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["session_id"] == "xyz789" + + +def test_cookie_param_lambda_function_url(gw_event_lambda_url): + """Test cookie parameter with Lambda Function URL (v2 format).""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = LambdaFunctionUrlResolver(enable_validation=True) + + @app.get("/me") + def handler(session_id: Annotated[str, Cookie()]): + return {"session_id": session_id} + + gw_event_lambda_url["rawPath"] = "/me" + gw_event_lambda_url["requestContext"]["http"]["method"] = "GET" + gw_event_lambda_url["cookies"] = ["session_id=fn_url_abc"] + + result = app(gw_event_lambda_url, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["session_id"] == "fn_url_abc" + + +def test_cookie_param_alb(gw_event_alb): + """Test cookie parameter with ALB (Cookie header in multiValueHeaders).""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = ALBResolver(enable_validation=True) + + @app.get("/me") + def handler(session_id: Annotated[str, Cookie()]): + return {"session_id": session_id} + + gw_event_alb["path"] = "/me" + gw_event_alb["httpMethod"] = "GET" + gw_event_alb["multiValueHeaders"]["cookie"] = ["session_id=alb_abc"] + + result = app(gw_event_alb, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["session_id"] == "alb_abc" + + +def test_cookie_param_openapi_schema(): + """Test that Cookie() generates correct OpenAPI schema with in=cookie.""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler( + session_id: Annotated[str, Cookie(description="Session identifier")], + theme: Annotated[str, Cookie(description="UI theme")] = "light", + ): + return {"session_id": session_id} + + schema = app.get_openapi_schema() + schema_dict = schema.model_dump(mode="json", by_alias=True, exclude_none=True) + + path = schema_dict["paths"]["/me"]["get"] + params = path["parameters"] + + cookie_params = [p for p in params if p["in"] == "cookie"] + assert len(cookie_params) == 2 + + session_param = next(p for p in cookie_params if p["name"] == "session_id") + assert session_param["required"] is True + assert session_param["description"] == "Session identifier" + + theme_param = next(p for p in cookie_params if p["name"] == "theme") + assert theme_param.get("required") is not True + assert theme_param["description"] == "UI theme" + + +def test_cookie_param_with_query_and_header(gw_event): + """Test that Cookie(), Query(), and Header() work together.""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler( + user_id: Annotated[str, Query()], + x_request_id: Annotated[str, Header()], + session_id: Annotated[str, Cookie()], + ): + return { + "user_id": user_id, + "x_request_id": x_request_id, + "session_id": session_id, + } + + gw_event["path"] = "/me" + gw_event["queryStringParameters"] = {"user_id": "u123"} + gw_event["multiValueQueryStringParameters"] = {"user_id": ["u123"]} + gw_event["headers"]["x-request-id"] = "req-456" + gw_event["multiValueHeaders"] = {"x-request-id": ["req-456"], "cookie": ["session_id=sess-789"]} + gw_event["headers"]["cookie"] = "session_id=sess-789" + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["user_id"] == "u123" + assert body["x_request_id"] == "req-456" + assert body["session_id"] == "sess-789" + + +def test_cookie_param_no_cookies_in_request(gw_event): + """Test that empty cookies dict is handled gracefully.""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/me") + def handler(theme: Annotated[str, Cookie()] = "light"): + return {"theme": theme} + + gw_event["path"] = "/me" + gw_event["headers"] = {} + gw_event.pop("multiValueHeaders", None) + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["theme"] == "light" + + +def test_cookie_param_vpc_lattice_v2(gw_event_vpc_lattice): + """Test cookie parameter with VPC Lattice v2 (headers are lists).""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = VPCLatticeV2Resolver(enable_validation=True) + + @app.get("/me") + def handler(session_id: Annotated[str, Cookie()]): + return {"session_id": session_id} + + gw_event_vpc_lattice["method"] = "GET" + gw_event_vpc_lattice["path"] = "/me" + gw_event_vpc_lattice["headers"]["cookie"] = ["session_id=lattice_abc"] + + result = app(gw_event_vpc_lattice, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["session_id"] == "lattice_abc" + + +def test_cookie_param_vpc_lattice_v1(gw_event_vpc_lattice_v1): + """Test cookie parameter with VPC Lattice v1 (comma-separated headers).""" + from aws_lambda_powertools.event_handler.openapi.params import Cookie + + app = VPCLatticeResolver(enable_validation=True) + + @app.get("/me") + def handler(session_id: Annotated[str, Cookie()]): + return {"session_id": session_id} + + gw_event_vpc_lattice_v1["method"] = "GET" + gw_event_vpc_lattice_v1["raw_path"] = "/me" + gw_event_vpc_lattice_v1["headers"]["cookie"] = "session_id=lattice_v1_abc" + + result = app(gw_event_vpc_lattice_v1, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["session_id"] == "lattice_v1_abc" From a26d64b55cf4cf89535b0601a8ac0ed1415ed80a Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 16:50:31 +0800 Subject: [PATCH 25/84] feat(event_handler): add File parameter support for multipart/form-data uploads (#8093) * feat(event_handler): add support for File field in OpenAPI utility * feat(event_handler): add support for File field in OpenAPI utility * feat(event_handler): add support for File field in OpenAPI utility --- .../middlewares/openapi_validation.py | 170 ++++- .../event_handler/openapi/dependant.py | 8 +- .../event_handler/openapi/params.py | 52 +- docs/core/event_handler/api_gateway.md | 51 ++ .../src/working_with_file_uploads.py | 17 + .../src/working_with_file_uploads_metadata.py | 21 + .../src/working_with_file_uploads_mixed.py | 29 + .../test_openapi_validation_middleware.py | 605 ++++++++++++++++++ 8 files changed, 944 insertions(+), 9 deletions(-) create mode 100644 examples/event_handler_rest/src/working_with_file_uploads.py create mode 100644 examples/event_handler_rest/src/working_with_file_uploads_metadata.py create mode 100644 examples/event_handler_rest/src/working_with_file_uploads_mixed.py diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py index 1bfe416dac7..05306b5ca8b 100644 --- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py @@ -1,8 +1,10 @@ from __future__ import annotations +import base64 import dataclasses import json import logging +import warnings from typing import TYPE_CHECKING, Any, Callable, Mapping, MutableMapping, Sequence, Union, cast from urllib.parse import parse_qs @@ -25,7 +27,7 @@ RequestValidationError, ResponseValidationError, ) -from aws_lambda_powertools.event_handler.openapi.params import Param +from aws_lambda_powertools.event_handler.openapi.params import Param, UploadFile from aws_lambda_powertools.event_handler.openapi.types import UnionType if TYPE_CHECKING: @@ -44,6 +46,7 @@ CONTENT_DISPOSITION_NAME_PARAM = "name=" APPLICATION_JSON_CONTENT_TYPE = "application/json" APPLICATION_FORM_CONTENT_TYPE = "application/x-www-form-urlencoded" +MULTIPART_FORM_DATA_CONTENT_TYPE = "multipart/form-data" class OpenAPIRequestValidationMiddleware(BaseMiddlewareHandler): @@ -141,14 +144,18 @@ def _get_body(self, app: EventHandlerInstance) -> dict[str, Any]: elif content_type.startswith(APPLICATION_FORM_CONTENT_TYPE): return self._parse_form_data(app) + # Handle multipart/form-data (file uploads) + elif content_type.startswith(MULTIPART_FORM_DATA_CONTENT_TYPE): + return self._parse_multipart_data(app, content_type) + else: raise RequestUnsupportedContentType( - "Only JSON body or Form() are supported", + "Unsupported content type", errors=[ { "type": "unsupported_content_type", "loc": ("body",), - "msg": "Only JSON body or Form() are supported", + "msg": f"Unsupported content type: {content_type}", "input": {}, "ctx": {}, }, @@ -195,6 +202,49 @@ def _parse_form_data(self, app: EventHandlerInstance) -> dict[str, Any]: ], ) from e + def _parse_multipart_data(self, app: EventHandlerInstance, content_type: str) -> dict[str, Any]: + """Parse multipart/form-data from the request body (file uploads).""" + try: + # Extract the boundary from the content-type header + boundary = _extract_multipart_boundary(content_type) + if not boundary: + raise ValueError("Missing boundary in multipart/form-data content-type header") + + # Get raw body bytes + raw_body = app.current_event.body or "" + if app.current_event.is_base64_encoded: + body_bytes = base64.b64decode(raw_body) + else: + warnings.warn( + "Received multipart/form-data without base64 encoding. " + "Binary file uploads may be corrupted. " + "If using API Gateway REST API (v1), configure Binary Media Types " + "to include 'multipart/form-data'. " + "See: https://docs.aws.amazon.com/apigateway/latest/developerguide/" + "api-gateway-payload-encodings.html", + stacklevel=2, + ) + # Use latin-1 to preserve all byte values (0-255) since the body + # may contain raw binary data that isn't valid UTF-8 + body_bytes = raw_body.encode("latin-1") + + return _parse_multipart_body(body_bytes, boundary) + + except ValueError: + raise + except Exception as e: + raise RequestValidationError( + [ + { + "type": "multipart_invalid", + "loc": ("body",), + "msg": "Multipart form data parsing error", + "input": {}, + "ctx": {"error": str(e)}, + }, + ], + ) from e + class OpenAPIResponseValidationMiddleware(BaseMiddlewareHandler): """ @@ -398,7 +448,12 @@ def _request_body_to_args( continue value = _normalize_field_value(value=value, field_info=field.field_info) - values[field.name] = _validate_field(field=field, value=value, loc=loc, existing_errors=errors) + + # UploadFile objects bypass Pydantic validation — they're already constructed + if isinstance(value, UploadFile): + values[field.name] = value + else: + values[field.name] = _validate_field(field=field, value=value, loc=loc, existing_errors=errors) return values, errors @@ -474,6 +529,10 @@ def _is_or_contains_sequence(annotation: Any) -> bool: def _normalize_field_value(value: Any, field_info: FieldInfo) -> Any: """Normalize field value, converting lists to single values for non-sequence fields.""" + # When annotation is bytes but value is UploadFile, extract raw content + if isinstance(value, UploadFile) and field_info.annotation is bytes: + return value.content + if _is_or_contains_sequence(field_info.annotation): return value elif isinstance(value, list) and value: @@ -587,3 +646,106 @@ def _get_param_value( value = input_dict.get(field_name) return value + + +def _extract_multipart_boundary(content_type: str) -> str | None: + """Extract the boundary string from a multipart/form-data content-type header.""" + for segment in content_type.split(";"): + stripped = segment.strip() + if stripped.startswith("boundary="): + boundary = stripped[len("boundary=") :] + # Remove optional quotes around boundary + if boundary.startswith('"') and boundary.endswith('"'): + boundary = boundary[1:-1] + return boundary + return None + + +def _parse_multipart_body(body: bytes, boundary: str) -> dict[str, Any]: + """ + Parse a multipart/form-data body into a dict of field names to values. + + File fields get bytes values; regular form fields get string values. + Multiple values for the same field name are collected into lists. + """ + delimiter = f"--{boundary}".encode() + end_delimiter = f"--{boundary}--".encode() + + result: dict[str, Any] = {} + + # Split body by the boundary delimiter + raw_parts = body.split(delimiter) + + for raw_part in raw_parts: + # Skip the preamble (before first boundary) and epilogue (after closing boundary) + if not raw_part or raw_part.strip() == b"" or raw_part.strip() == b"--": + continue + + # Remove the end delimiter marker if present + chunk = raw_part + if chunk.endswith(end_delimiter): + chunk = chunk[: -len(end_delimiter)] + + # Strip leading \r\n + if chunk.startswith(b"\r\n"): + chunk = chunk[2:] + + # Strip trailing \r\n + if chunk.endswith(b"\r\n"): + chunk = chunk[:-2] + + # Split headers from body at the double CRLF + header_end = chunk.find(b"\r\n\r\n") + if header_end == -1: + continue + + header_section = chunk[:header_end].decode("utf-8") + body_section = chunk[header_end + 4 :] + + # Parse Content-Disposition to get the field name and optional filename + field_name = None + filename = None + content_type_header = None + + for header_line in header_section.split("\r\n"): + header_lower = header_line.lower() + if header_lower.startswith("content-disposition:"): + field_name = _extract_header_param(header_line, "name") + filename = _extract_header_param(header_line, "filename") + elif header_lower.startswith("content-type:"): + content_type_header = header_line.split(":", 1)[1].strip() + + if field_name is None: + continue + + # If it has a filename, it's a file upload — wrap as UploadFile + # Otherwise it's a regular form field — decode to string + if filename is not None: + value: Any = UploadFile(content=body_section, filename=filename, content_type=content_type_header) + else: + value = body_section.decode("utf-8") + + # Collect multiple values for same field name into a list + if field_name in result: + existing = result[field_name] + if isinstance(existing, list): + existing.append(value) + else: + result[field_name] = [existing, value] + else: + result[field_name] = value + + return result + + +def _extract_header_param(header_line: str, param_name: str) -> str | None: + """Extract a parameter value from a header line (e.g., name="file" from Content-Disposition).""" + search = f'{param_name}="' + idx = header_line.find(search) + if idx == -1: + return None + start = idx + len(search) + end = header_line.find('"', start) + if end == -1: + return None + return header_line[start:end] diff --git a/aws_lambda_powertools/event_handler/openapi/dependant.py b/aws_lambda_powertools/event_handler/openapi/dependant.py index 197de9427d2..ec8414a7dd2 100644 --- a/aws_lambda_powertools/event_handler/openapi/dependant.py +++ b/aws_lambda_powertools/event_handler/openapi/dependant.py @@ -13,10 +13,10 @@ from aws_lambda_powertools.event_handler.openapi.params import ( Body, Dependant, + File, Form, Param, ParamTypes, - _File, analyze_param, create_response_field, get_flat_dependant, @@ -370,9 +370,9 @@ def get_body_field_info( if not required: body_field_info_kwargs["default"] = None - if any(isinstance(f.field_info, _File) for f in flat_dependant.body_params): - # MAINTENANCE: body_field_info: type[Body] = _File - raise NotImplementedError("_File fields are not supported in request bodies") + if any(isinstance(f.field_info, File) for f in flat_dependant.body_params): + body_field_info = Body + body_field_info_kwargs["media_type"] = "multipart/form-data" elif any(isinstance(f.field_info, Form) for f in flat_dependant.body_params): body_field_info = Body body_field_info_kwargs["media_type"] = "application/x-www-form-urlencoded" diff --git a/aws_lambda_powertools/event_handler/openapi/params.py b/aws_lambda_powertools/event_handler/openapi/params.py index 534a20a5686..3da928ca236 100644 --- a/aws_lambda_powertools/event_handler/openapi/params.py +++ b/aws_lambda_powertools/event_handler/openapi/params.py @@ -902,7 +902,57 @@ def __init__( ) -class _File(Form): # type: ignore[misc] +class UploadFile: + """ + Represents an uploaded file with its metadata. + + Use with ``Annotated[UploadFile, File()]`` to receive file content along with + filename and content type. For raw bytes only, use ``Annotated[bytes, File()]``. + + Attributes + ---------- + filename : str | None + The original filename from the upload. + content_type : str | None + The MIME type declared by the client (e.g. ``image/jpeg``). + content : bytes + The raw file content. + """ + + __slots__ = ("content", "content_type", "filename") + + def __init__(self, *, content: bytes, filename: str | None = None, content_type: str | None = None): + self.content = content + self.filename = filename + self.content_type = content_type + + def __len__(self) -> int: + return len(self.content) + + def __repr__(self) -> str: + return f"UploadFile(filename={self.filename!r}, content_type={self.content_type!r}, size={len(self.content)})" + + @classmethod + def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> Any: + from pydantic_core import core_schema + + return core_schema.no_info_plain_validator_function( + cls._validate, + serialization=core_schema.plain_serializer_function_ser_schema(lambda v: v, info_arg=False), + ) + + @classmethod + def _validate(cls, v: Any) -> UploadFile: + if isinstance(v, cls): + return v + raise ValueError(f"Expected UploadFile, got {type(v).__name__}") + + @classmethod + def __get_pydantic_json_schema__(cls, _schema: Any, handler: Any) -> dict[str, Any]: + return {"type": "string", "format": "binary"} + + +class File(Form): # type: ignore[misc] """ A class used to represent a file parameter in a path operation. """ diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index e262613046c..cd8fcc57791 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -605,6 +605,57 @@ You can use the `Form` type to tell the Event Handler that a parameter expects f --8<-- "examples/event_handler_rest/src/working_with_form_data.py" ``` +#### Handling file uploads + +!!! info "You must set `enable_validation=True` to handle file uploads via type annotation." + +You can use the `File` type to accept `multipart/form-data` file uploads. This automatically sets the correct OpenAPI schema, and Swagger UI will render a file picker for each `File()` parameter. + +There are two ways to receive uploaded files: + +* **`bytes`** — receive raw file content only +* **`UploadFile`** — receive file content along with metadata (filename, content type) + +=== "working_with_file_uploads.py" + + ```python hl_lines="4 12" + --8<-- "examples/event_handler_rest/src/working_with_file_uploads.py" + ``` + + 1. `File` is a special OpenAPI type for `multipart/form-data` file uploads. When annotated as `bytes`, you receive the raw file content. + +=== "working_with_file_uploads_metadata.py" + + ```python hl_lines="4 11 15-16" + --8<-- "examples/event_handler_rest/src/working_with_file_uploads_metadata.py" + ``` + + 1. Using `UploadFile` instead of `bytes` gives you access to file metadata. + 2. `filename` and `content_type` come from the multipart headers sent by the client. + +=== "working_with_file_uploads_mixed.py" + + You can combine `File()` and `Form()` parameters in the same route to accept file uploads with additional form fields. + + ```python hl_lines="6 14-15" + --8<-- "examples/event_handler_rest/src/working_with_file_uploads_mixed.py" + ``` + + 1. File upload parameter — receives the uploaded file with metadata. + 2. Regular form field — receives a string value from the same multipart request. + +!!! warning "API Gateway REST API (v1) requires Binary Media Types configuration" + When using API Gateway REST API (v1), you must configure Binary Media Types to include `multipart/form-data`, otherwise binary file content will be corrupted. + + ```yaml title="SAM template.yaml" + Globals: + Api: + BinaryMediaTypes: + - "multipart~1form-data" + ``` + + API Gateway HTTP API (v2), Lambda Function URL, and ALB handle binary encoding automatically — no extra configuration needed. + #### Supported types for response serialization With data validation enabled, we natively support serializing the following data types to JSON: diff --git a/examples/event_handler_rest/src/working_with_file_uploads.py b/examples/event_handler_rest/src/working_with_file_uploads.py new file mode 100644 index 00000000000..bebf72939fe --- /dev/null +++ b/examples/event_handler_rest/src/working_with_file_uploads.py @@ -0,0 +1,17 @@ +from typing import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.event_handler.openapi.params import File + +app = APIGatewayRestResolver(enable_validation=True) + + +@app.post("/upload") +def upload_file( + file_data: Annotated[bytes, File(description="File to upload")], # (1)! +): + return {"file_size": len(file_data)} + + +def lambda_handler(event, context): + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/working_with_file_uploads_metadata.py b/examples/event_handler_rest/src/working_with_file_uploads_metadata.py new file mode 100644 index 00000000000..07da798f350 --- /dev/null +++ b/examples/event_handler_rest/src/working_with_file_uploads_metadata.py @@ -0,0 +1,21 @@ +from typing import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + +app = APIGatewayRestResolver(enable_validation=True) + + +@app.post("/upload") +def upload_file( + file_data: Annotated[UploadFile, File(description="File to upload")], # (1)! +): + return { + "filename": file_data.filename, # (2)! + "content_type": file_data.content_type, + "file_size": len(file_data), + } + + +def lambda_handler(event, context): + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/working_with_file_uploads_mixed.py b/examples/event_handler_rest/src/working_with_file_uploads_mixed.py new file mode 100644 index 00000000000..e0c3859c58e --- /dev/null +++ b/examples/event_handler_rest/src/working_with_file_uploads_mixed.py @@ -0,0 +1,29 @@ +import csv +import io +from typing import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.event_handler.openapi.params import File, Form, UploadFile + +app = APIGatewayRestResolver(enable_validation=True) + + +@app.post("/upload-csv") +def upload_csv( + file_data: Annotated[UploadFile, File(description="CSV file to parse")], # (1)! + separator: Annotated[str, Form(description="CSV separator")] = ",", # (2)! +): + text = file_data.content.decode("utf-8") + reader = csv.DictReader(io.StringIO(text), delimiter=separator) + rows = list(reader) + + return { + "filename": file_data.filename, + "total_rows": len(rows), + "columns": list(rows[0].keys()) if rows else [], + "data": rows, + } + + +def lambda_handler(event, context): + return app.resolve(event, context) 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 01935d3aba3..e7199adc9c5 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py @@ -1,6 +1,7 @@ import base64 import datetime import json +import warnings from dataclasses import dataclass from enum import Enum from pathlib import PurePath @@ -3329,6 +3330,610 @@ def handler(items: Annotated[Union[_Item, List[_Item]], Body()]) -> Dict[str, An assert body["count"] == 100 +# ---------- File upload (multipart/form-data) ---------- + + +def _build_multipart_body(fields: List[Dict], boundary: str = "----TestBoundary") -> Tuple[str, str]: + """ + Build a multipart/form-data body and return (base64_body, content_type). + + Each field dict can have: + - name: field name (required) + - value: str or bytes (required) + - filename: optional filename (makes it a file part) + - content_type: optional content type for the part + """ + parts = [] + for field in fields: + headers = f'Content-Disposition: form-data; name="{field["name"]}"' + if "filename" in field: + headers += f'; filename="{field["filename"]}"' + if "content_type" in field: + headers += f"\r\nContent-Type: {field['content_type']}" + value = field["value"] + if isinstance(value, str): + value = value.encode("utf-8") + parts.append((headers, value)) + + body = b"" + for headers, value in parts: + body += f"--{boundary}\r\n".encode() + body += f"{headers}\r\n\r\n".encode() + body += value + body += b"\r\n" + body += f"--{boundary}--\r\n".encode() + + content_type = f"multipart/form-data; boundary={boundary}" + return base64.b64encode(body).decode("utf-8"), content_type + + +def test_file_upload_basic(gw_event): + """Test basic file upload with File() parameter.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File()]): + return {"size": len(file_data)} + + body, content_type = _build_multipart_body( + [ + {"name": "file_data", "value": b"hello world", "filename": "test.txt"}, + ], + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = content_type + gw_event["body"] = body + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"size": 11} + + +def test_file_upload_with_form_field(gw_event): + """Test file upload mixed with a regular form field.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload( + description: Annotated[str, Form()], + file_data: Annotated[bytes, File()], + ): + return {"description": description, "size": len(file_data)} + + body, content_type = _build_multipart_body( + [ + {"name": "description", "value": "my file"}, + {"name": "file_data", "value": b"\x89PNG\r\n\x1a\n", "filename": "image.png", "content_type": "image/png"}, + ], + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = content_type + gw_event["body"] = body + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + parsed = json.loads(result["body"]) + assert parsed["description"] == "my file" + assert parsed["size"] == 8 + + +def test_file_upload_missing_required(gw_event): + """Test that missing required File() parameter returns 422.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File()]): + return {"size": len(file_data)} + + # Send empty multipart body (no file_data field) + body, content_type = _build_multipart_body( + [ + {"name": "other_field", "value": "some value"}, + ], + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = content_type + gw_event["body"] = body + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 422 + assert "missing" in result["body"] + + +def test_file_upload_openapi_schema(): + """Test that File() parameters generate correct OpenAPI schema.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File(description="The file to upload")]): + return {"size": len(file_data)} + + schema = app.get_openapi_schema() + path = schema.paths["/upload"] + post_op = path.post + + # Should have a request body with multipart/form-data + assert post_op.requestBody is not None + content = post_op.requestBody.content + assert "multipart/form-data" in content + + # The schema should reference a binary format field + multipart_schema = content["multipart/form-data"].schema_ + assert multipart_schema is not None + + +def test_file_upload_non_base64(gw_event): + """Test file upload when body is not base64-encoded (edge case).""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File()]): + return {"size": len(file_data)} + + # Build multipart body without base64 encoding + boundary = "----TestBoundary" + raw_body = ( + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="test.txt"\r\n' + f"\r\n" + f"hello world\r\n" + f"--{boundary}--\r\n" + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = f"multipart/form-data; boundary={boundary}" + gw_event["body"] = raw_body + gw_event["isBase64Encoded"] = False + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"size": 11} + + +def test_file_upload_non_base64_emits_warning(gw_event): + """Test that non-base64 multipart body emits a warning about API Gateway config.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File()]): + return {"size": len(file_data)} + + boundary = "----TestBoundary" + raw_body = ( + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="test.txt"\r\n' + f"\r\n" + f"hello world\r\n" + f"--{boundary}--\r\n" + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = f"multipart/form-data; boundary={boundary}" + gw_event["body"] = raw_body + gw_event["isBase64Encoded"] = False + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + result = app(gw_event, {}) + + assert result["statusCode"] == 200 + assert len(w) == 1 + assert "Binary Media Types" in str(w[0].message) + + +def test_file_upload_non_base64_binary_content(gw_event): + """Test file upload with raw binary bytes (e.g. JPEG) without base64 encoding.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File()]): + return {"size": len(file_data)} + + # Simulate binary content with bytes that are NOT valid UTF-8 (like JPEG header 0xFF 0xD8) + binary_content = b"\xff\xd8\xff\xe0\x00\x10JFIF\x00" + boundary = "----TestBoundary" + raw_bytes = ( + ( + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="photo.jpg"\r\n' + f"Content-Type: image/jpeg\r\n" + f"\r\n" + ).encode("latin-1") + + binary_content + + f"\r\n--{boundary}--\r\n".encode("latin-1") + ) + + # Without binary mode, API Gateway passes body as latin-1 compatible string + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = f"multipart/form-data; boundary={boundary}" + gw_event["body"] = raw_bytes.decode("latin-1") + gw_event["isBase64Encoded"] = False + + with warnings.catch_warnings(record=True): + warnings.simplefilter("always") + result = app(gw_event, {}) + + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"size": len(binary_content)} + + +def test_upload_file_with_metadata(gw_event): + """Test UploadFile annotation provides filename and content_type.""" + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[UploadFile, File()]): + return { + "filename": file_data.filename, + "content_type": file_data.content_type, + "size": len(file_data), + } + + body, content_type = _build_multipart_body( + [ + {"name": "file_data", "value": b"fake jpeg", "filename": "photo.jpg", "content_type": "image/jpeg"}, + ], + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = content_type + gw_event["body"] = body + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + parsed = json.loads(result["body"]) + assert parsed["filename"] == "photo.jpg" + assert parsed["content_type"] == "image/jpeg" + assert parsed["size"] == 9 + + +def test_upload_file_mixed_with_form(gw_event): + """Test UploadFile + Form fields together.""" + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload( + file_data: Annotated[UploadFile, File()], + title: Annotated[str, Form()], + ): + return { + "title": title, + "filename": file_data.filename, + "size": len(file_data), + } + + body, content_type = _build_multipart_body( + [ + {"name": "title", "value": "My Document"}, + { + "name": "file_data", + "value": b"pdf content here", + "filename": "doc.pdf", + "content_type": "application/pdf", + }, + ], + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = content_type + gw_event["body"] = body + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + parsed = json.loads(result["body"]) + assert parsed["title"] == "My Document" + assert parsed["filename"] == "doc.pdf" + assert parsed["size"] == 16 + + +def test_upload_file_openapi_schema(): + """Test UploadFile generates correct OpenAPI schema.""" + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[UploadFile, File(description="A file")]): + return {} + + schema = app.get_openapi_schema() + schema_dict = schema.model_dump(exclude_none=True, by_alias=True) + upload_path = schema_dict["paths"]["/upload"]["post"] + content = upload_path["requestBody"]["content"] + assert "multipart/form-data" in content + + # Resolve $ref to get the actual schema + ref = content["multipart/form-data"]["schema"]["$ref"] + schema_name = ref.split("/")[-1] + props = schema_dict["components"]["schemas"][schema_name]["properties"] + assert props["file_data"]["type"] == "string" + assert props["file_data"]["format"] == "binary" + + +def test_multipart_missing_boundary(gw_event): + """Test that missing boundary in content-type raises ValueError.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File()]): + return {"size": len(file_data)} + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = "multipart/form-data" # no boundary + gw_event["body"] = base64.b64encode(b"some data").decode() + gw_event["isBase64Encoded"] = True + + with pytest.raises(ValueError, match="Missing boundary"): + app(gw_event, {}) + + +def test_multipart_quoted_boundary(gw_event): + """Test that boundary with quotes is parsed correctly.""" + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[bytes, File()]): + return {"size": len(file_data)} + + boundary = "----TestBoundary" + body, _ = _build_multipart_body( + [ + {"name": "file_data", "value": b"hello", "filename": "test.txt"}, + ], + boundary=boundary, + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + # Use quoted boundary + gw_event["headers"]["content-type"] = f'multipart/form-data; boundary="{boundary}"' + gw_event["body"] = body + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"size": 5} + + +def test_multipart_multiple_values_same_field(gw_event): + """Test multiple values for the same field name are collected as list.""" + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[List[UploadFile], File()]): + return {"count": len(file_data), "filenames": [f.filename for f in file_data]} + + # Build body with two parts having the same field name + boundary = "----TestBoundary" + raw = ( + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="a.txt"\r\n' + f"\r\n" + f"content a\r\n" + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="b.txt"\r\n' + f"\r\n" + f"content b\r\n" + f"--{boundary}--\r\n" + ).encode() + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = f"multipart/form-data; boundary={boundary}" + gw_event["body"] = base64.b64encode(raw).decode() + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + parsed = json.loads(result["body"]) + assert parsed["count"] == 2 + assert parsed["filenames"] == ["a.txt", "b.txt"] + + +def test_multipart_three_values_same_field(gw_event): + """Test three or more values for same field name builds onto existing list.""" + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[List[UploadFile], File()]): + return {"count": len(file_data), "filenames": [f.filename for f in file_data]} + + boundary = "----TestBoundary" + raw = ( + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="a.txt"\r\n' + f"\r\n" + f"aaa\r\n" + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="b.txt"\r\n' + f"\r\n" + f"bbb\r\n" + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="c.txt"\r\n' + f"\r\n" + f"ccc\r\n" + f"--{boundary}--\r\n" + ).encode() + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = f"multipart/form-data; boundary={boundary}" + gw_event["body"] = base64.b64encode(raw).decode() + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + parsed = json.loads(result["body"]) + assert parsed["count"] == 3 + assert parsed["filenames"] == ["a.txt", "b.txt", "c.txt"] + + +def test_multipart_part_without_headers_separator(gw_event): + """Test that a malformed part missing the header/body separator is skipped.""" + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[UploadFile, File()]): + return {"filename": file_data.filename} + + # Build a body with one malformed part (no \r\n\r\n) and one valid part + boundary = "----TestBoundary" + raw = ( + f"--{boundary}\r\n" + f"This part has no header separator at all\r\n" + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="good.txt"\r\n' + f"\r\n" + f"good content\r\n" + f"--{boundary}--\r\n" + ).encode() + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = f"multipart/form-data; boundary={boundary}" + gw_event["body"] = base64.b64encode(raw).decode() + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + parsed = json.loads(result["body"]) + assert parsed["filename"] == "good.txt" + + +def test_multipart_part_without_field_name(gw_event): + """Test that a part missing the name parameter in Content-Disposition is skipped.""" + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[UploadFile, File()]): + return {"filename": file_data.filename} + + # Build a body with one part that has no name= param and one valid part + boundary = "----TestBoundary" + raw = ( + f"--{boundary}\r\n" + f"Content-Disposition: form-data\r\n" + f"\r\n" + f"orphan content\r\n" + f"--{boundary}\r\n" + f'Content-Disposition: form-data; name="file_data"; filename="valid.txt"\r\n' + f"\r\n" + f"valid content\r\n" + f"--{boundary}--\r\n" + ).encode() + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = f"multipart/form-data; boundary={boundary}" + gw_event["body"] = base64.b64encode(raw).decode() + gw_event["isBase64Encoded"] = True + + result = app(gw_event, {}) + assert result["statusCode"] == 200 + parsed = json.loads(result["body"]) + assert parsed["filename"] == "valid.txt" + + +def test_upload_file_validate_error(): + """Test UploadFile._validate raises ValueError for non-UploadFile values.""" + from aws_lambda_powertools.event_handler.openapi.params import UploadFile + + with pytest.raises(ValueError, match="Expected UploadFile, got str"): + UploadFile._validate("not an upload file") + + with pytest.raises(ValueError, match="Expected UploadFile, got int"): + UploadFile._validate(42) + + +def test_multipart_unclosed_quote_in_header(): + """Test that _extract_header_param returns None when quote is unclosed.""" + from aws_lambda_powertools.event_handler.middlewares.openapi_validation import _extract_header_param + + # name=" is present but closing quote is missing + result = _extract_header_param('Content-Disposition: form-data; name="broken', "name") + assert result is None + + +def test_multipart_generic_parse_error(gw_event): + """Test that non-ValueError exceptions during multipart parsing produce 422.""" + from unittest.mock import patch + + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/upload") + def upload(file_data: Annotated[UploadFile, File()]): + return {"filename": file_data.filename} + + body_b64, content_type = _build_multipart_body( + [{"name": "file_data", "value": b"data", "filename": "test.txt"}], + ) + + gw_event["httpMethod"] = "POST" + gw_event["path"] = "/upload" + gw_event["headers"]["content-type"] = content_type + gw_event["body"] = body_b64 + gw_event["isBase64Encoded"] = True + + # Patch _parse_multipart_body to raise a non-ValueError (e.g. TypeError) + with patch( + "aws_lambda_powertools.event_handler.middlewares.openapi_validation._parse_multipart_body", + side_effect=TypeError("unexpected type"), + ): + result = app(gw_event, {}) + assert result["statusCode"] == 422 + body = json.loads(result["body"]) + assert body["detail"][0]["type"] == "multipart_invalid" + + # ---------- Cookie parameter tests ---------- From bf7e555159c6c75e38c7ed46667e600e644239ed Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 17:56:30 +0800 Subject: [PATCH 26/84] docs: adding docs to Request object (#8105) --- docs/core/event_handler/api_gateway.md | 46 ++++++++++++++++++- .../middleware_request_handler_injection.py | 16 +++++++ .../src/middleware_request_object.py | 30 ++++++++++++ poetry.lock | 25 +++++----- 4 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 examples/event_handler_rest/src/middleware_request_handler_injection.py create mode 100644 examples/event_handler_rest/src/middleware_request_object.py diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index cd8fcc57791..b5b312e7a26 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -943,6 +943,50 @@ Here's a sample middleware that extracts and injects correlation ID, using `APIG --8<-- "examples/event_handler_rest/src/middleware_getting_started_output.json" ``` +#### Accessing the Request object + +After route resolution, Event Handler creates a `Request` object with the **resolved** route context. You can access it in two ways: + +1. **`app.request`** - available in middleware functions. +2. **`request: Request` type annotation** - injected automatically into route handlers as a parameter. + +`Request` gives you the resolved route context that `app.current_event` doesn't have: + +| Property | Example | Description | +| --------------------- | ---------------------------------------- | ----------------------------------------------------- | +| `route` | `/todos/{todo_id}` | Matched route pattern in OpenAPI path-template format | +| `path_parameters` | `{"todo_id": "123"}` | Powertools-resolved path parameters | +| `method` | `GET` | HTTP method (upper-case) | +| `headers` | `{"content-type": "application/json"}` | Request headers | +| `query_parameters` | `{"page": "1"}` | Query string parameters | +| `body` | `'{"name": "task"}'` | Raw request body | +| `json_body` | `{"name": "task"}` | Deserialized request body | + +=== "Using `app.request` in middleware" + + ```python hl_lines="10 13-15 21" title="Accessing Request via app.request" + --8<-- "examples/event_handler_rest/src/middleware_request_object.py" + ``` + + 1. Access the resolved `Request` object from the app instance. + 2. `request.route` returns the matched route pattern, e.g. `/todos/{todo_id}`. + 3. `request.path_parameters` returns the Powertools-resolved parameters, e.g. `{"todo_id": "123"}`. + 4. You can include route metadata in the response headers. + +=== "Using `request: Request` in route handlers" + + ```python hl_lines="7 10" title="Accessing Request via type annotation" + --8<-- "examples/event_handler_rest/src/middleware_request_handler_injection.py" + ``` + + 1. Add `request: Request` as a parameter - Event Handler injects it automatically. + 2. Access resolved route, path parameters, headers, query parameters, and body. + +???+ note "When to use `Request` vs `app.current_event`" + Use `Request` for **route-aware** logic like authorization, logging, and metrics - it gives you the matched route pattern and Powertools-resolved path parameters. + + Use `app.current_event` when you need the **raw event** data like request context, stage variables, or authorizer context that is available from the start of the request, before route resolution. + #### Global middlewares
@@ -1112,7 +1156,7 @@ Keep the following in mind when authoring middlewares for Event Handler: 2. **Call the next middleware**. Return the result of `next_middleware(app)`, or a [Response object](#fine-grained-responses) when you want to [return early](#returning-early). 3. **Keep a lean scope**. Focus on a single task per middleware to ease composability and maintenance. In [debug mode](#debug-mode), we also print out the order middlewares will be triggered to ease operations. 4. **Catch your own exceptions**. Catch and handle known exceptions to your logic. Unless you want to raise [HTTP Errors](#raising-http-errors), or propagate specific exceptions to the client. To catch all and any exceptions, we recommend you use the [exception_handler](#exception-handling) decorator. -5. **Use context to share data**. Use `app.append_context` to [share contextual data](#sharing-contextual-data) between middlewares and route handlers, and `app.context.get(key)` to fetch them. We clear all contextual data at the end of every request. +5. **Use context to share data**. Use `app.append_context` to [share contextual data](#sharing-contextual-data) between middlewares and route handlers, and `app.context.get(key)` to fetch them. We clear all contextual data at the end of every request. For route-aware request data, use [`app.request`](#accessing-the-request-object) instead. ### Fine grained responses diff --git a/examples/event_handler_rest/src/middleware_request_handler_injection.py b/examples/event_handler_rest/src/middleware_request_handler_injection.py new file mode 100644 index 00000000000..9304fcb1021 --- /dev/null +++ b/examples/event_handler_rest/src/middleware_request_handler_injection.py @@ -0,0 +1,16 @@ +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Request + +app = APIGatewayRestResolver() + + +@app.get("/todos/") +def get_todo(todo_id: str, request: Request): # (1)! + return { + "id": todo_id, + "route": request.route, # (2)! + "user_agent": request.headers.get("user-agent", ""), + } + + +def lambda_handler(event, context): + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/middleware_request_object.py b/examples/event_handler_rest/src/middleware_request_object.py new file mode 100644 index 00000000000..9f58460888d --- /dev/null +++ b/examples/event_handler_rest/src/middleware_request_object.py @@ -0,0 +1,30 @@ +from aws_lambda_powertools import Logger +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response +from aws_lambda_powertools.event_handler.middlewares import NextMiddleware + +app = APIGatewayRestResolver() +logger = Logger() + + +def request_context_middleware(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: + request = app.request # (1)! + + logger.append_keys( + route=request.route, # (2)! + method=request.method, + path_parameters=request.path_parameters, # (3)! + ) + + response = next_middleware(app) + + response.headers["x-route-pattern"] = request.route # (4)! + return response + + +@app.get("/todos/", middlewares=[request_context_middleware]) +def get_todo(todo_id: str): + return {"id": todo_id} + + +def lambda_handler(event, context): + return app.resolve(event, context) diff --git a/poetry.lock b/poetry.lock index f8d475fc473..37583604a7e 100644 --- a/poetry.lock +++ b/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.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" @@ -325,7 +325,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"}, @@ -1830,7 +1830,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"}, @@ -1912,7 +1912,6 @@ 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] @@ -1931,7 +1930,6 @@ 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] @@ -1947,7 +1945,6 @@ python-versions = ">=3.10" groups = ["dev"] files = [ {file = "griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f"}, - {file = "griffelib-2.0.0.tar.gz", hash = "sha256:e504d637a089f5cab9b5daf18f7645970509bf4f53eda8d79ed71cce8bd97934"}, ] [package.extras] @@ -3408,7 +3405,7 @@ files = [ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3550,7 +3547,7 @@ files = [ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -3597,14 +3594,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.21" +version = "10.21.2" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pymdown_extensions-10.21-py3-none-any.whl", hash = "sha256:91b879f9f864d49794c2d9534372b10150e6141096c3908a455e45ca72ad9d3f"}, - {file = "pymdown_extensions-10.21.tar.gz", hash = "sha256:39f4a020f40773f6b2ff31d2cd2546c2c04d0a6498c31d9c688d2be07e1767d5"}, + {file = "pymdown_extensions-10.21.2-py3-none-any.whl", hash = "sha256:5c0fd2a2bea14eb39af8ff284f1066d898ab2187d81b889b75d46d4348c01638"}, + {file = "pymdown_extensions-10.21.2.tar.gz", hash = "sha256:c3f55a5b8a1d0edf6699e35dcbea71d978d34ff3fa79f3d807b8a5b3fa90fbdc"}, ] [package.dependencies] @@ -4804,7 +4801,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" @@ -5122,7 +5119,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" From a03795f825928c39157b9199744e674096213424 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 22:29:39 +0800 Subject: [PATCH 27/84] ci: remove me-south-1 region (#8108) --- .github/workflows/reusable_deploy_v3_layer_stack.yml | 4 +--- .github/workflows/update_ssm.yml | 2 +- docs/includes/_layer_homepage_arm64.md | 10 ---------- docs/includes/_layer_homepage_x86.md | 10 ---------- 4 files changed, 2 insertions(+), 24 deletions(-) diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index b760b71b40c..9d8d12e928a 100644 --- a/.github/workflows/reusable_deploy_v3_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v3_layer_stack.yml @@ -76,7 +76,7 @@ jobs: "ap-south-1", "ap-south-2", "ap-southeast-1", "ap-southeast-2", "ap-southeast-3", "ap-southeast-4", "ap-southeast-5", "ap-southeast-7", "ca-central-1", "ca-west-1", "eu-central-1", "eu-central-2", "eu-north-1", "eu-south-1", "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3", - "il-central-1", "me-south-1", "mx-central-1", "sa-east-1", "us-east-1", + "il-central-1", "mx-central-1", "sa-east-1", "us-east-1", "us-east-2", "us-west-1", "us-west-2"] python-version: ["3.10","3.11","3.12","3.13","3.14"] include: @@ -128,8 +128,6 @@ jobs: has_arm64_support: "true" - region: "il-central-1" has_arm64_support: "true" - - region: "me-south-1" - has_arm64_support: "true" - region: "mx-central-1" has_arm64_support: "true" - region: "sa-east-1" diff --git a/.github/workflows/update_ssm.yml b/.github/workflows/update_ssm.yml index 53a3851a7f1..78aff7e8172 100644 --- a/.github/workflows/update_ssm.yml +++ b/.github/workflows/update_ssm.yml @@ -78,7 +78,7 @@ jobs: "ap-south-1", "ap-south-2", "ap-southeast-1", "ap-southeast-2", "ap-southeast-3", "ap-southeast-4", "ap-southeast-5", "ap-southeast-7", "ca-central-1", "ca-west-1", "eu-central-1", "eu-central-2", "eu-north-1", "eu-south-1", "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3", - "il-central-1", "me-south-1", "mx-central-1", "sa-east-1", "us-east-1", + "il-central-1", "mx-central-1", "sa-east-1", "us-east-1", "us-east-2", "us-west-1", "us-west-2"] permissions: diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index 8c6437a47ca..5a715cd6627 100644 --- a/docs/includes/_layer_homepage_arm64.md +++ b/docs/includes/_layer_homepage_arm64.md @@ -29,8 +29,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | @@ -65,8 +63,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | @@ -101,8 +97,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | @@ -137,8 +131,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | @@ -173,8 +165,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 7160f26f385..96fc8ecb72d 100644 --- a/docs/includes/_layer_homepage_x86.md +++ b/docs/includes/_layer_homepage_x86.md @@ -29,8 +29,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | @@ -66,8 +64,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | @@ -103,8 +99,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | @@ -140,8 +134,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | @@ -177,8 +169,6 @@ | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`me-central-1`** | **arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`me-south-1`** | **arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | From 3f920005ad70043cca701a1bdc6da578f2a05582 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 23:11:12 +0800 Subject: [PATCH 28/84] chore(ci): bump version to 3.27.0 (#8109) 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 b2c4ff3ba90..60d93d7d3d7 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.26.0" +VERSION = "3.27.0" diff --git a/pyproject.toml b/pyproject.toml index 39598824dce..5c4c2433566 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "3.26.0" +version = "3.27.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 8e816fb67f4214ad15a7a6a4b2e79cfdc161341f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 23:17:42 +0800 Subject: [PATCH 29/84] chore(ci): layer docs update (#8110) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Leandro Damascena --- CHANGELOG.md | 24 +- 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, 341 insertions(+), 319 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30278b30259..8ba57cc87b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,36 @@ # Unreleased + +## [v3.27.0] - 2026-04-06 +## Maintenance + +* version bump + + ## [v3.26.0] - 2026-03-20 +## Bug Fixes + +* **ci:** add ty check to dataclasses utility ([#8038](https://github.com/aws-powertools/powertools-lambda-python/issues/8038)) +* **ci:** add ty check to parser folder ([#8037](https://github.com/aws-powertools/powertools-lambda-python/issues/8037)) +* **ci:** add ty check to parameters folder ([#8035](https://github.com/aws-powertools/powertools-lambda-python/issues/8035)) +* **openapi:** correct response validation for falsy objects ([#7990](https://github.com/aws-powertools/powertools-lambda-python/issues/7990)) + ## Features * add ldms feature ([#8051](https://github.com/aws-powertools/powertools-lambda-python/issues/8051)) +* **batch:** add Kafka/MSK batch processing support ([#7941](https://github.com/aws-powertools/powertools-lambda-python/issues/7941)) +* **buffer-handler:** add buffering support for external loggers ([#7994](https://github.com/aws-powertools/powertools-lambda-python/issues/7994)) ## Maintenance * version bump +* **deps:** bump aws-encryption-sdk from 4.0.3 to 4.0.4 ([#8027](https://github.com/aws-powertools/powertools-lambda-python/issues/8027)) +* **deps:** bump valkey-glide from 2.2.5 to 2.2.7 ([#8030](https://github.com/aws-powertools/powertools-lambda-python/issues/8030)) +* **deps-dev:** bump types-python-dateutil from 2.9.0.20260124 to 2.9.0.20260305 ([#8029](https://github.com/aws-powertools/powertools-lambda-python/issues/8029)) +* **deps-dev:** bump ijson from 3.4.0.post0 to 3.5.0 ([#8028](https://github.com/aws-powertools/powertools-lambda-python/issues/8028)) +* **deps-dev:** bump aws-cdk from 2.1108.0 to 2.1110.0 in the aws-cdk group ([#8023](https://github.com/aws-powertools/powertools-lambda-python/issues/8023)) @@ -7551,7 +7572,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.26.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.27.0...HEAD +[v3.27.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.26.0...v3.27.0 [v3.26.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.25.0...v3.26.0 [v3.25.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.24.0...v3.25.0 [v3.24.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.23.0...v3.24.0 diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index 5a715cd6627..fd0bc7b39c5 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:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 96fc8ecb72d..39270dc4c70 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:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:30**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | diff --git a/examples/build_recipes/cdk/basic/app.py b/examples/build_recipes/cdk/basic/app.py index f5d3d759ed8..069c26f469c 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:30", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31", ) # 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 7bb1f3f578f..5e72d667f31 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:30", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31", ) 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 636beea0d67..a4fab0f25d1 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:30 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31 - !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 9fac52a8127..90352866e9e 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:30 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31 - !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:30 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31 - !Ref DependenciesLayer Events: SQSEvent: diff --git a/examples/homepage/install/arm64/amplify.txt b/examples/homepage/install/arm64/amplify.txt index 4c426a23c01..3a97584cf65 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:30 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31 ❯ 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:30 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31 ? 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 a9b6ed9d01f..21f06a602da 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:30", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/arm64/pulumi_arm64.py b/examples/homepage/install/arm64/pulumi_arm64.py index 99115287ef0..c73e2b10192 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:30", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/arm64/sam.yaml b/examples/homepage/install/arm64/sam.yaml index fa1833c7be1..081e34d550b 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:30 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31 diff --git a/examples/homepage/install/arm64/serverless.yml b/examples/homepage/install/arm64/serverless.yml index 4ef384f4d99..a453cfb548b 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:30 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31 diff --git a/examples/homepage/install/arm64/terraform.tf b/examples/homepage/install/arm64/terraform.tf index 679c422939f..c5fb60e62aa 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:30"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31"] 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 63cdcc42b41..48de3e9ad3c 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:30 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 ❯ 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:30 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 ? 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 b70637672c2..d1bf26202d9 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:30", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31", ) 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 067a6036ae7..a0e6f9db425 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:30", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml index b26723ca830..0192664e0a6 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:30 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml index d55c246c4c6..4ac86076f24 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:30 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf index 53f7088f950..fcc999a872f 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:30"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 9fc1ee20500..1b1cd0e41a2 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:30 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index 0e080111506..af840ffe615 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:30 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 Resources: CaptureLambdaHandlerExample: diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml index cc89c955374..66697f68760 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:30 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 # 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 67a7e7ead41..cd21c5f1b3c 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:30 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31 Resources: CaptureLambdaHandlerExample: From ae16510dab08f198d16bbfd8602c57d62789e1c7 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 23:25:27 +0800 Subject: [PATCH 30/84] refactor(event_handler): extract OpenAPI schema generation from Route class (#8098) --- .../event_handler/api_gateway.py | 445 ++------------ .../event_handler/bedrock_agent.py | 17 +- .../event_handler/openapi/constants.py | 2 + .../event_handler/openapi/schema_generator.py | 549 ++++++++++++++++++ 4 files changed, 600 insertions(+), 413 deletions(-) create mode 100644 aws_lambda_powertools/event_handler/openapi/schema_generator.py diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index f7294801460..ad1e14d3122 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -1,7 +1,6 @@ from __future__ import annotations import base64 -import copy import json import logging import re @@ -23,6 +22,8 @@ from aws_lambda_powertools.event_handler.openapi.config import OpenAPIConfig from aws_lambda_powertools.event_handler.openapi.constants import ( DEFAULT_API_VERSION, + DEFAULT_CONTENT_TYPE, + DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, DEFAULT_OPENAPI_TITLE, DEFAULT_OPENAPI_VERSION, ) @@ -34,13 +35,8 @@ ) from aws_lambda_powertools.event_handler.openapi.types import ( COMPONENT_REF_PREFIX, - METHODS_WITH_BODY, OpenAPIResponse, - OpenAPIResponseContentModel, - OpenAPIResponseContentSchema, response_validation_error_response_definition, - validation_error_definition, - validation_error_response_definition, ) from aws_lambda_powertools.event_handler.request import Request from aws_lambda_powertools.event_handler.util import ( @@ -73,10 +69,8 @@ # API GW/ALB decode non-safe URI chars; we must support them too _UNSAFE_URI = r"%<> \[\]{}|^" _NAMED_GROUP_BOUNDARY_PATTERN = rf"(?P\1[{_SAFE_URI}{_UNSAFE_URI}\\w]+)" -_DEFAULT_OPENAPI_RESPONSE_DESCRIPTION = "Successful Response" _ROUTE_REGEX = "^{}$" _JSON_DUMP_CALL = partial(json.dumps, separators=(",", ":"), cls=Encoder) -_DEFAULT_CONTENT_TYPE = "application/json" ResponseEventT = TypeVar("ResponseEventT", bound=BaseProxyEvent) ResponseT = TypeVar("ResponseT") @@ -95,7 +89,7 @@ Server, Tag, ) - from aws_lambda_powertools.event_handler.openapi.params import Dependant, Param + from aws_lambda_powertools.event_handler.openapi.params import Dependant from aws_lambda_powertools.event_handler.openapi.swagger_ui.oauth2 import ( OAuth2Config, ) @@ -279,7 +273,7 @@ def __init__( self, body: Any = None, status_code: int = 200, - content_type: str = _DEFAULT_CONTENT_TYPE, + content_type: str = DEFAULT_CONTENT_TYPE, session_attributes: dict[str, Any] | None = None, prompt_session_attributes: dict[str, Any] | None = None, knowledge_bases_configuration: list[dict[str, Any]] | None = None, @@ -355,7 +349,7 @@ def is_json(self) -> bool: content_type = self.headers.get("Content-Type", "") if isinstance(content_type, list): content_type = content_type[0] - return content_type.startswith(_DEFAULT_CONTENT_TYPE) + return content_type.startswith(DEFAULT_CONTENT_TYPE) class Route: @@ -617,7 +611,7 @@ def body_field(self) -> ModelField | None: return self._body_field - def _get_openapi_path( # noqa PLR0912 + def _get_openapi_path( self, *, dependant: Dependant, @@ -628,393 +622,32 @@ def _get_openapi_path( # noqa PLR0912 ) -> tuple[dict[str, Any], dict[str, Any]]: """ Returns the OpenAPI path and definitions for the route. - """ - from aws_lambda_powertools.event_handler.openapi.dependant import get_flat_params - - definitions: dict[str, Any] = {} - - # Gather all the route parameters - operation = self._openapi_operation_metadata(operation_ids=operation_ids) - parameters: list[dict[str, Any]] = [] - all_route_params = get_flat_params(dependant) - operation_params = self._openapi_operation_parameters( - all_route_params=all_route_params, - model_name_map=model_name_map, - field_mapping=field_mapping, - ) - parameters.extend(operation_params) - - # Add security if present - if self.security: - operation["security"] = self.security - - # Add OpenAPI extensions if present - if self.openapi_extensions: - operation.update(self.openapi_extensions) - - # Add the parameters to the OpenAPI operation - if parameters: - all_parameters = {(param["in"], param["name"]): param for param in parameters} - required_parameters = {(param["in"], param["name"]): param for param in parameters if param.get("required")} - all_parameters.update(required_parameters) - operation["parameters"] = list(all_parameters.values()) - - # Add the request body to the OpenAPI operation, if applicable - if self.method.upper() in METHODS_WITH_BODY: - request_body_oai = self._openapi_operation_request_body( - body_field=self.body_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - ) - if request_body_oai: - operation["requestBody"] = request_body_oai - - operation_responses: dict[int, OpenAPIResponse] = {} - - if enable_validation: - # Validation failure response (422) is added only if Enable Validation feature is true - operation_responses = { - 422: { - "description": "Validation Error", - "content": { - _DEFAULT_CONTENT_TYPE: {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}HTTPValidationError"}}, - }, - }, - } - - # Add custom response validation response, if exists - if self.custom_response_validation_http_code: - http_code = self.custom_response_validation_http_code.value - operation_responses[http_code] = { - "description": "Response Validation Error", - "content": { - _DEFAULT_CONTENT_TYPE: {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}ResponseValidationError"}}, - }, - } - # Add model definition - definitions["ResponseValidationError"] = response_validation_error_response_definition - - # Add the response to the OpenAPI operation - if self.responses: - for status_code in list(self.responses): - # Create a deep copy to prevent mutation of the shared dictionary - response = copy.deepcopy(self.responses[status_code]) - - # Case 1: there is not 'content' key - if "content" not in response: - response["content"] = { - _DEFAULT_CONTENT_TYPE: self._openapi_operation_return( - param=dependant.return_param, - model_name_map=model_name_map, - field_mapping=field_mapping, - ), - } - - # Case 2: there is a 'content' key - else: - # Need to iterate to transform any 'model' into a 'schema' - for content_type, payload in response["content"].items(): - # Case 2.1: the 'content' has a model - if "model" in payload: - # Find the model in the dependant's extra models - model_payload_typed = cast(OpenAPIResponseContentModel, payload) - return_field = next( - filter( - lambda model: model.type_ is model_payload_typed["model"], - self.dependant.response_extra_models, - ), - ) - if not return_field: - raise AssertionError("Model declared in custom responses was not found") - - model_payload = self._openapi_operation_return( - param=return_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - ) - - # Preserve existing fields like examples, encoding, etc. - new_payload: OpenAPIResponseContentSchema = {} - for key, value in payload.items(): - if key != "model": - new_payload[key] = value # type: ignore[literal-required] - new_payload.update(model_payload) # Add/override with model schema - - # Case 2.2: the 'content' has a schema - else: - # Do nothing! We already have what we need! - new_payload = cast(OpenAPIResponseContentSchema, payload) - - response["content"][content_type] = new_payload - - # Merge the user provided response with the default responses - operation_responses[status_code] = response - else: - # Set the default 200 response - response_schema = self._openapi_operation_return( - param=dependant.return_param, - model_name_map=model_name_map, - field_mapping=field_mapping, - ) - - # Add the response schema to the OpenAPI 200 response - operation_responses[200] = { - "description": self.response_description or _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, - "content": {_DEFAULT_CONTENT_TYPE: response_schema}, - } - - operation["responses"] = operation_responses - path = {self.method.lower(): operation} - # Add the validation error schema to the definitions, but only if it hasn't been added yet - if "ValidationError" not in definitions: - definitions.update( - { - "ValidationError": validation_error_definition, - "HTTPValidationError": validation_error_response_definition, - }, - ) - - # Generate the response schema - return path, definitions - - def _openapi_operation_summary(self) -> str: - """ - Returns the OpenAPI operation summary. If the user has not provided a summary, we - generate one based on the route path and method. - """ - return self.summary or f"{self.method.upper()} {self.openapi_path}" - - def _openapi_operation_metadata(self, operation_ids: set[str]) -> dict[str, Any]: - """ - Returns the OpenAPI operation metadata. If the user has not provided a description, we - generate one based on the route path and method. - """ - operation: dict[str, Any] = {} - - # Ensure tags is added to the operation - if self.tags: - operation["tags"] = self.tags - - # Ensure summary is added to the operation - operation["summary"] = self._openapi_operation_summary() - - # Ensure description is added to the operation - if self.description: - operation["description"] = self.description - - # Ensure operationId is unique - if self.operation_id in operation_ids: - message = f"Duplicate Operation ID {self.operation_id} for function {self.func.__name__}" - file_name = getattr(self.func, "__globals__", {}).get("__file__") - if file_name: - message += f" in {file_name}" - warnings.warn(message, stacklevel=1) - - # Adds the operation - operation_ids.add(self.operation_id) - operation["operationId"] = self.operation_id - - # Mark as deprecated if necessary - operation["deprecated"] = self.deprecated or None - - return operation - - @staticmethod - def _openapi_operation_request_body( - *, - body_field: ModelField | None, - model_name_map: dict[TypeModelOrEnum, str], - field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], - ) -> dict[str, Any] | None: - """ - Returns the OpenAPI operation request body. - """ - from aws_lambda_powertools.event_handler.openapi.compat import ModelField, get_schema_from_model_field - from aws_lambda_powertools.event_handler.openapi.params import Body - - # Check that there is a body field and it's a Pydantic's model field - if not body_field: - return None - - if not isinstance(body_field, ModelField): - raise AssertionError(f"Expected ModelField, got {body_field}") - - # Generate the request body schema - body_schema = get_schema_from_model_field( - field=body_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - ) - - field_info = cast(Body, body_field.field_info) - request_media_type = field_info.media_type - required = body_field.required - request_body_oai: dict[str, Any] = {} - if required: - request_body_oai["required"] = required - - if field_info.description: - request_body_oai["description"] = field_info.description - # Generate the request body media type - request_media_content: dict[str, Any] = {"schema": body_schema} - if field_info.openapi_examples: - request_media_content["examples"] = field_info.openapi_examples - request_body_oai["content"] = {request_media_type: request_media_content} - return request_body_oai - - @staticmethod - def _openapi_operation_parameters( - *, - all_route_params: Sequence[ModelField], - model_name_map: dict[TypeModelOrEnum, str], - field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], - ) -> list[dict[str, Any]]: - """ - Returns the OpenAPI operation parameters. - """ - from aws_lambda_powertools.event_handler.openapi.params import Param - - parameters: list[dict[str, Any]] = [] - - for param in all_route_params: - field_info = cast(Param, param.field_info) - if not field_info.include_in_schema: - continue - - # Check if this is a Pydantic model that should be expanded - if Route._is_pydantic_model_param(field_info): - parameters.extend(Route._expand_pydantic_model_parameters(field_info)) - else: - parameters.append(Route._create_regular_parameter(param, model_name_map, field_mapping)) - - return parameters - - @staticmethod - def _is_pydantic_model_param(field_info: Param) -> bool: - """Check if the field info represents a Pydantic model parameter.""" - from pydantic import BaseModel - - from aws_lambda_powertools.event_handler.openapi.compat import lenient_issubclass - - return lenient_issubclass(field_info.annotation, BaseModel) - - @staticmethod - def _expand_pydantic_model_parameters(field_info: Param) -> list[dict[str, Any]]: - """Expand a Pydantic model into individual OpenAPI parameters.""" - from pydantic import BaseModel - - model_class = cast(type[BaseModel], field_info.annotation) - parameters: list[dict[str, Any]] = [] - - for field_name, field_def in model_class.model_fields.items(): - param_name = field_def.alias or field_name - individual_param = Route._create_pydantic_field_parameter( - param_name=param_name, - field_def=field_def, - param_location=field_info.in_.value, - ) - parameters.append(individual_param) - - return parameters - - @staticmethod - def _create_pydantic_field_parameter( - param_name: str, - field_def: Any, - param_location: str, - ) -> dict[str, Any]: - """Create an OpenAPI parameter from a Pydantic field definition.""" - individual_param: dict[str, Any] = { - "name": param_name, - "in": param_location, - "required": field_def.is_required() if hasattr(field_def, "is_required") else field_def.default is ..., - "schema": Route._get_basic_type_schema(field_def.annotation or type(None)), - } - - if field_def.description: - individual_param["description"] = field_def.description - - return individual_param - - @staticmethod - def _create_regular_parameter( - param: ModelField, - model_name_map: dict[TypeModelOrEnum, str], - field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], - ) -> dict[str, Any]: - """Create an OpenAPI parameter from a regular ModelField.""" - from aws_lambda_powertools.event_handler.openapi.compat import get_schema_from_model_field - from aws_lambda_powertools.event_handler.openapi.params import Param - - field_info = cast(Param, param.field_info) - param_schema = get_schema_from_model_field( - field=param, - model_name_map=model_name_map, - field_mapping=field_mapping, - ) - - parameter: dict[str, Any] = { - "name": param.alias, - "in": field_info.in_.value, - "required": param.required, - "schema": param_schema, - } - - # Add optional attributes if present - if field_info.description: - parameter["description"] = field_info.description - if field_info.openapi_examples: - parameter["examples"] = field_info.openapi_examples - if field_info.deprecated: - parameter["deprecated"] = field_info.deprecated - - return parameter - - @staticmethod - def _get_basic_type_schema(param_type: type) -> dict[str, str]: - """ - Get basic OpenAPI schema for simple types - """ - try: - # Check bool before int, since bool is a subclass of int in Python - if issubclass(param_type, bool): - return {"type": "boolean"} - elif issubclass(param_type, int): - return {"type": "integer"} - elif issubclass(param_type, float): - return {"type": "number"} - else: - return {"type": "string"} - except TypeError: - # param_type may not be a type (e.g., typing.Optional[int]), fallback to string - return {"type": "string"} - - @staticmethod - def _openapi_operation_return( - *, - param: ModelField | None, - model_name_map: dict[TypeModelOrEnum, str], - field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], - ) -> OpenAPIResponseContentSchema: - """ - Returns the OpenAPI operation return. - """ - if param is None: - return {} - - from aws_lambda_powertools.event_handler.openapi.compat import ( - get_schema_from_model_field, - ) - - return_schema = get_schema_from_model_field( - field=param, + Delegates to openapi.schema_generator for the actual generation logic. + """ + from aws_lambda_powertools.event_handler.openapi.schema_generator import generate_openapi_path + + return generate_openapi_path( + method=self.method, + operation_id=self.operation_id, + summary=self.summary, + description=self.description, + openapi_path=self.openapi_path, + tags=self.tags, + deprecated=self.deprecated, + security=self.security, + openapi_extensions=self.openapi_extensions, + responses=self.responses, + response_description=self.response_description, + body_field=self.body_field, + custom_response_validation_http_code=self.custom_response_validation_http_code, + dependant=dependant, + operation_ids=operation_ids, model_name_map=model_name_map, field_mapping=field_mapping, + enable_validation=enable_validation, ) - return {"schema": return_schema} - def _generate_operation_id(self) -> str: operation_id = self.func.__name__ + self.openapi_path operation_id = re.sub(r"\W", "_", operation_id) @@ -1155,7 +788,7 @@ def route( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -1218,7 +851,7 @@ def get( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -1281,7 +914,7 @@ def post( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -1345,7 +978,7 @@ def put( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -1409,7 +1042,7 @@ def delete( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -1472,7 +1105,7 @@ def patch( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -1538,7 +1171,7 @@ def head( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -1921,7 +1554,7 @@ def _add_resolver_response_validation_error_response_to_route( response_validation_error_response = { "description": "Response Validation Error", "content": { - _DEFAULT_CONTENT_TYPE: { + DEFAULT_CONTENT_TYPE: { "schema": {"$ref": f"{COMPONENT_REF_PREFIX}ResponseValidationError"}, }, }, @@ -2622,7 +2255,7 @@ def swagger_handler(): if query_params.get("format") == "json": return Response( status_code=200, - content_type=_DEFAULT_CONTENT_TYPE, + content_type=DEFAULT_CONTENT_TYPE, body=escaped_spec, ) @@ -2674,7 +2307,7 @@ def route( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -3237,7 +2870,7 @@ def route( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str | None = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str | None = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -3355,7 +2988,7 @@ def route( summary: str | None = None, description: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, diff --git a/aws_lambda_powertools/event_handler/bedrock_agent.py b/aws_lambda_powertools/event_handler/bedrock_agent.py index 4593715e88d..e9aa82ee01f 100644 --- a/aws_lambda_powertools/event_handler/bedrock_agent.py +++ b/aws_lambda_powertools/event_handler/bedrock_agent.py @@ -7,12 +7,15 @@ from aws_lambda_powertools.event_handler import ApiGatewayResolver from aws_lambda_powertools.event_handler.api_gateway import ( - _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, BedrockResponse, ProxyEventType, ResponseBuilder, ) -from aws_lambda_powertools.event_handler.openapi.constants import DEFAULT_API_VERSION, DEFAULT_OPENAPI_VERSION +from aws_lambda_powertools.event_handler.openapi.constants import ( + DEFAULT_API_VERSION, + DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + DEFAULT_OPENAPI_VERSION, +) if TYPE_CHECKING: from collections.abc import Callable @@ -118,7 +121,7 @@ def get( # type: ignore[override] cache_control: str | None = None, summary: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -161,7 +164,7 @@ def post( # type: ignore[override] cache_control: str | None = None, summary: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -204,7 +207,7 @@ def put( # type: ignore[override] cache_control: str | None = None, summary: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -247,7 +250,7 @@ def patch( # type: ignore[override] cache_control: str | None = None, summary: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, @@ -290,7 +293,7 @@ def delete( # type: ignore[override] cache_control: str | None = None, summary: str | None = None, responses: dict[int, OpenAPIResponse] | None = None, - response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + response_description: str = DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, tags: list[str] | None = None, operation_id: str | None = None, include_in_schema: bool = True, diff --git a/aws_lambda_powertools/event_handler/openapi/constants.py b/aws_lambda_powertools/event_handler/openapi/constants.py index debe1d56736..c125e89d0e7 100644 --- a/aws_lambda_powertools/event_handler/openapi/constants.py +++ b/aws_lambda_powertools/event_handler/openapi/constants.py @@ -1,3 +1,5 @@ DEFAULT_API_VERSION = "1.0.0" DEFAULT_OPENAPI_VERSION = "3.1.0" DEFAULT_OPENAPI_TITLE = "Powertools for AWS Lambda (Python) API" +DEFAULT_CONTENT_TYPE = "application/json" +DEFAULT_OPENAPI_RESPONSE_DESCRIPTION = "Successful Response" diff --git a/aws_lambda_powertools/event_handler/openapi/schema_generator.py b/aws_lambda_powertools/event_handler/openapi/schema_generator.py new file mode 100644 index 00000000000..5d409693937 --- /dev/null +++ b/aws_lambda_powertools/event_handler/openapi/schema_generator.py @@ -0,0 +1,549 @@ +""" +OpenAPI schema generation for individual routes. + +Extracted from Route to keep route configuration and schema generation +as separate concerns. All functions here are internal. +""" + +from __future__ import annotations + +import copy +import warnings +from typing import TYPE_CHECKING, Any, Literal, cast + +from aws_lambda_powertools.event_handler.openapi.types import ( + COMPONENT_REF_PREFIX, + METHODS_WITH_BODY, + OpenAPIResponse, + OpenAPIResponseContentModel, + OpenAPIResponseContentSchema, + response_validation_error_response_definition, + validation_error_definition, + validation_error_response_definition, +) + +if TYPE_CHECKING: + from collections.abc import Sequence + from http import HTTPStatus + + from aws_lambda_powertools.event_handler.openapi.compat import ( + JsonSchemaValue, + ModelField, + ) + from aws_lambda_powertools.event_handler.openapi.params import Dependant, Param + from aws_lambda_powertools.event_handler.openapi.types import TypeModelOrEnum + +from aws_lambda_powertools.event_handler.openapi.constants import ( + DEFAULT_CONTENT_TYPE, + DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, +) + + +def generate_openapi_path( + *, + method: str, + operation_id: str, + summary: str | None, + description: str | None, + openapi_path: str, + tags: list[str], + deprecated: bool, + security: list[dict[str, list[str]]] | None, + openapi_extensions: dict[str, Any] | None, + responses: dict[int, OpenAPIResponse] | None, + response_description: str | None, + body_field: ModelField | None, + custom_response_validation_http_code: HTTPStatus | None, + dependant: Dependant, + operation_ids: set[str], + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], + enable_validation: bool = False, +) -> tuple[dict[str, Any], dict[str, Any]]: + """ + Generate the OpenAPI path spec and definitions for a single route. + """ + from aws_lambda_powertools.event_handler.openapi.dependant import get_flat_params + + definitions: dict[str, Any] = {} + + # Build operation metadata + operation = _build_operation_metadata( + method=method, + operation_id=operation_id, + summary=summary, + description=description, + openapi_path=openapi_path, + tags=tags, + deprecated=deprecated, + operation_ids=operation_ids, + func_name=dependant.call.__name__ if dependant.call else "", + func_file=getattr(dependant.call, "__globals__", {}).get("__file__") if dependant.call else None, + ) + + _apply_optional_fields(operation, security=security, openapi_extensions=openapi_extensions) + + # Build parameters + all_route_params = get_flat_params(dependant) + parameters = _build_operation_parameters( + all_route_params=all_route_params, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + if parameters: + operation["parameters"] = _deduplicate_parameters(parameters) + + # Build request body + _apply_request_body( + operation, + method=method, + body_field=body_field, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + # Build responses + operation_responses, response_definitions = _build_responses( + responses=responses, + response_description=response_description, + custom_response_validation_http_code=custom_response_validation_http_code, + dependant=dependant, + model_name_map=model_name_map, + field_mapping=field_mapping, + enable_validation=enable_validation, + ) + definitions.update(response_definitions) + + operation["responses"] = operation_responses + path = {method.lower(): operation} + + _add_validation_error_definitions(definitions) + + return path, definitions + + +def _build_operation_metadata( + *, + method: str, + operation_id: str, + summary: str | None, + description: str | None, + openapi_path: str, + tags: list[str], + deprecated: bool, + operation_ids: set[str], + func_name: str, + func_file: str | None, +) -> dict[str, Any]: + """Build the OpenAPI operation metadata (tags, summary, operationId, etc.).""" + _warn_duplicate_operation_id(operation_id, operation_ids, func_name, func_file) + operation_ids.add(operation_id) + + operation: dict[str, Any] = { + "summary": summary or f"{method.upper()} {openapi_path}", + "operationId": operation_id, + "deprecated": deprecated or None, + } + + if tags: + operation["tags"] = tags + if description: + operation["description"] = description + + return operation + + +def _build_operation_parameters( + *, + all_route_params: Sequence[ModelField], + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], +) -> list[dict[str, Any]]: + """Build the list of OpenAPI operation parameters.""" + from aws_lambda_powertools.event_handler.openapi.params import Param + + parameters: list[dict[str, Any]] = [] + + for param in all_route_params: + field_info = cast(Param, param.field_info) + if not field_info.include_in_schema: + continue + + if _is_pydantic_model_param(field_info): + parameters.extend(_expand_pydantic_model_parameters(field_info)) + else: + parameters.append(_create_regular_parameter(param, model_name_map, field_mapping)) + + return parameters + + +def _build_request_body( + *, + body_field: ModelField | None, + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], +) -> dict[str, Any] | None: + """Build the OpenAPI request body spec.""" + from aws_lambda_powertools.event_handler.openapi.compat import ModelField as ModelFieldClass + from aws_lambda_powertools.event_handler.openapi.compat import get_schema_from_model_field + from aws_lambda_powertools.event_handler.openapi.params import Body + + if not body_field: + return None + + if not isinstance(body_field, ModelFieldClass): + raise AssertionError(f"Expected ModelField, got {body_field}") + + body_schema = get_schema_from_model_field( + field=body_field, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + field_info = cast(Body, body_field.field_info) + + request_body_oai: dict[str, Any] = {} + if body_field.required: + request_body_oai["required"] = body_field.required + if field_info.description: + request_body_oai["description"] = field_info.description + + request_body_oai["content"] = { + field_info.media_type: _build_media_content(body_schema, field_info.openapi_examples), + } + return request_body_oai + + +def _build_responses( + *, + responses: dict[int, OpenAPIResponse] | None, + response_description: str | None, + custom_response_validation_http_code: HTTPStatus | None, + dependant: Dependant, + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], + enable_validation: bool, +) -> tuple[dict[int, OpenAPIResponse], dict[str, Any]]: + """Build the OpenAPI response specs and any extra definitions.""" + definitions: dict[str, Any] = {} + operation_responses: dict[int, OpenAPIResponse] = {} + + _add_validation_responses(operation_responses, enable_validation=enable_validation) + _add_response_validation_error( + operation_responses, + definitions, + custom_response_validation_http_code=custom_response_validation_http_code, + ) + + if responses: + for status_code in list(responses): + operation_responses[status_code] = _build_custom_response( + response=copy.deepcopy(responses[status_code]), + dependant=dependant, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + else: + response_schema = _build_return_schema( + param=dependant.return_param, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + operation_responses[200] = { + "description": response_description or DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + "content": {DEFAULT_CONTENT_TYPE: response_schema}, + } + + return operation_responses, definitions + + +def _build_return_schema( + *, + param: ModelField | None, + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], +) -> OpenAPIResponseContentSchema: + """Build the response schema for a return parameter.""" + if param is None: + return {} + + from aws_lambda_powertools.event_handler.openapi.compat import get_schema_from_model_field + + return_schema = get_schema_from_model_field( + field=param, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + return {"schema": return_schema} + + +def _is_pydantic_model_param(field_info: Param) -> bool: + """Check if the field info represents a Pydantic model parameter.""" + from pydantic import BaseModel + + from aws_lambda_powertools.event_handler.openapi.compat import lenient_issubclass + + return lenient_issubclass(field_info.annotation, BaseModel) + + +def _expand_pydantic_model_parameters(field_info: Param) -> list[dict[str, Any]]: + """Expand a Pydantic model into individual OpenAPI parameters.""" + from pydantic import BaseModel + + model_class = cast(type[BaseModel], field_info.annotation) + parameters: list[dict[str, Any]] = [] + + for field_name, field_def in model_class.model_fields.items(): + param_name = field_def.alias or field_name + individual_param = _create_pydantic_field_parameter( + param_name=param_name, + field_def=field_def, + param_location=field_info.in_.value, + ) + parameters.append(individual_param) + + return parameters + + +def _create_pydantic_field_parameter( + param_name: str, + field_def: Any, + param_location: str, +) -> dict[str, Any]: + """Create an OpenAPI parameter from a Pydantic field definition.""" + individual_param: dict[str, Any] = { + "name": param_name, + "in": param_location, + "required": field_def.is_required() if hasattr(field_def, "is_required") else field_def.default is ..., + "schema": _get_basic_type_schema(field_def.annotation or type(None)), + } + + if field_def.description: + individual_param["description"] = field_def.description + + return individual_param + + +def _create_regular_parameter( + param: ModelField, + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], +) -> dict[str, Any]: + """Create an OpenAPI parameter from a regular ModelField.""" + from aws_lambda_powertools.event_handler.openapi.compat import get_schema_from_model_field + from aws_lambda_powertools.event_handler.openapi.params import Param + + field_info = cast(Param, param.field_info) + param_schema = get_schema_from_model_field( + field=param, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + parameter: dict[str, Any] = { + "name": param.alias, + "in": field_info.in_.value, + "required": param.required, + "schema": param_schema, + } + + if field_info.description: + parameter["description"] = field_info.description + if field_info.openapi_examples: + parameter["examples"] = field_info.openapi_examples + if field_info.deprecated: + parameter["deprecated"] = field_info.deprecated + + return parameter + + +def _get_basic_type_schema(param_type: type) -> dict[str, str]: + """Get basic OpenAPI schema for simple types.""" + type_map: dict[type, str] = {bool: "boolean", int: "integer", float: "number"} + try: + for base_type, schema_type in type_map.items(): + if issubclass(param_type, base_type): + return {"type": schema_type} + return {"type": "string"} + except TypeError: + return {"type": "string"} + + +def _apply_optional_fields( + operation: dict[str, Any], + *, + security: list[dict[str, list[str]]] | None, + openapi_extensions: dict[str, Any] | None, +) -> None: + """Apply optional security and extension fields to the operation.""" + if security: + operation["security"] = security + if openapi_extensions: + operation.update(openapi_extensions) + + +def _apply_request_body( + operation: dict[str, Any], + *, + method: str, + body_field: ModelField | None, + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], +) -> None: + """Build and apply request body to operation if applicable.""" + if method.upper() not in METHODS_WITH_BODY: + return + + request_body_oai = _build_request_body( + body_field=body_field, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + if request_body_oai: + operation["requestBody"] = request_body_oai + + +def _add_validation_responses( + operation_responses: dict[int, OpenAPIResponse], + *, + enable_validation: bool, +) -> None: + """Add 422 validation error response if validation is enabled.""" + if not enable_validation: + return + + operation_responses[422] = { + "description": "Validation Error", + "content": { + DEFAULT_CONTENT_TYPE: {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}HTTPValidationError"}}, + }, + } + + +def _add_response_validation_error( + operation_responses: dict[int, OpenAPIResponse], + definitions: dict[str, Any], + *, + custom_response_validation_http_code: HTTPStatus | None, +) -> None: + """Add response validation error if a custom HTTP code is configured.""" + if not custom_response_validation_http_code: + return + + http_code = custom_response_validation_http_code.value + operation_responses[http_code] = { + "description": "Response Validation Error", + "content": { + DEFAULT_CONTENT_TYPE: {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}ResponseValidationError"}}, + }, + } + definitions["ResponseValidationError"] = response_validation_error_response_definition + + +def _deduplicate_parameters(parameters: list[dict[str, Any]]) -> list[dict[str, Any]]: + """Deduplicate parameters, giving priority to required ones.""" + all_parameters = {(param["in"], param["name"]): param for param in parameters} + required_parameters = {(param["in"], param["name"]): param for param in parameters if param.get("required")} + all_parameters.update(required_parameters) + return list(all_parameters.values()) + + +def _add_validation_error_definitions(definitions: dict[str, Any]) -> None: + """Add standard validation error schema definitions if not already present.""" + if "ValidationError" not in definitions: + definitions["ValidationError"] = validation_error_definition + definitions["HTTPValidationError"] = validation_error_response_definition + + +def _warn_duplicate_operation_id( + operation_id: str, + operation_ids: set[str], + func_name: str, + func_file: str | None, +) -> None: + """Warn if an operationId has already been used.""" + if operation_id not in operation_ids: + return + + message = f"Duplicate Operation ID {operation_id} for function {func_name}" + if func_file: + message += f" in {func_file}" + warnings.warn(message, stacklevel=1) + + +def _build_media_content( + body_schema: dict[str, Any], + openapi_examples: dict[str, Any] | None, +) -> dict[str, Any]: + """Build the media content dict for a request body.""" + content: dict[str, Any] = {"schema": body_schema} + if openapi_examples: + content["examples"] = openapi_examples + return content + + +def _build_custom_response( + *, + response: OpenAPIResponse, + dependant: Dependant, + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], +) -> OpenAPIResponse: + """Build a single custom response, resolving model references in content.""" + if "content" not in response: + response["content"] = { + DEFAULT_CONTENT_TYPE: _build_return_schema( + param=dependant.return_param, + model_name_map=model_name_map, + field_mapping=field_mapping, + ), + } + return response + + for content_type, payload in response["content"].items(): + response["content"][content_type] = _resolve_response_payload( + payload=payload, + dependant=dependant, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + return response + + +def _resolve_response_payload( + *, + payload: OpenAPIResponseContentSchema | OpenAPIResponseContentModel, + dependant: Dependant, + model_name_map: dict[TypeModelOrEnum, str], + field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], +) -> OpenAPIResponseContentSchema: + """Resolve a single response content payload, replacing model refs with schemas.""" + if "model" not in payload: + return cast(OpenAPIResponseContentSchema, payload) + + model_payload_typed = cast(OpenAPIResponseContentModel, payload) + return_field = next( + filter( + lambda model: model.type_ is model_payload_typed["model"], + dependant.response_extra_models, + ), + ) + if not return_field: + raise AssertionError("Model declared in custom responses was not found") + + model_payload = _build_return_schema( + param=return_field, + model_name_map=model_name_map, + field_mapping=field_mapping, + ) + + new_payload: OpenAPIResponseContentSchema = {} + for key, value in payload.items(): + if key != "model": + new_payload[key] = value # type: ignore[literal-required] + new_payload.update(model_payload) + return new_payload From 5374efb37483ef0e4dc16ab16fff63b8f660ab2f Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 6 Apr 2026 23:50:43 +0800 Subject: [PATCH 31/84] docs: add openapi docs (#7939) * docs: add openapi docs * Addressing Ran's feedback --------- Co-authored-by: Claude Opus 4.6 --- .../event_handler/openapi/merge.py | 383 ++++++++------- docs/core/event_handler/api_gateway.md | 149 +----- docs/core/event_handler/openapi.md | 452 ++++++++++++++++++ .../src/openapi_merge_conflict.py | 9 + .../src/openapi_merge_full_config.py | 18 + .../src/openapi_merge_multiple_patterns.py | 9 + .../src/openapi_merge_resolver.py | 18 + .../src/openapi_merge_shared_discovery.py | 13 + .../src/openapi_merge_shared_orders_routes.py | 7 + .../src/openapi_merge_shared_resolver.py | 4 + .../src/openapi_merge_shared_users_routes.py | 12 + .../src/openapi_merge_standalone.py | 23 + .../src/openapi_merge_with_exclusions.py | 10 + mkdocs.yml | 1 + .../merge_handlers/shared/__init__.py | 0 .../shared/categories_routes.py | 11 + .../merge_handlers/shared/products_routes.py | 17 + .../merge_handlers/shared/resolver.py | 5 + .../_pydantic/test_openapi_merge.py | 33 ++ .../openapi/test_openapi_merge.py | 8 +- 20 files changed, 841 insertions(+), 341 deletions(-) create mode 100644 docs/core/event_handler/openapi.md create mode 100644 examples/event_handler_rest/src/openapi_merge_conflict.py create mode 100644 examples/event_handler_rest/src/openapi_merge_full_config.py create mode 100644 examples/event_handler_rest/src/openapi_merge_multiple_patterns.py create mode 100644 examples/event_handler_rest/src/openapi_merge_resolver.py create mode 100644 examples/event_handler_rest/src/openapi_merge_shared_discovery.py create mode 100644 examples/event_handler_rest/src/openapi_merge_shared_orders_routes.py create mode 100644 examples/event_handler_rest/src/openapi_merge_shared_resolver.py create mode 100644 examples/event_handler_rest/src/openapi_merge_shared_users_routes.py create mode 100644 examples/event_handler_rest/src/openapi_merge_standalone.py create mode 100644 examples/event_handler_rest/src/openapi_merge_with_exclusions.py create mode 100644 tests/functional/event_handler/_pydantic/merge_handlers/shared/__init__.py create mode 100644 tests/functional/event_handler/_pydantic/merge_handlers/shared/categories_routes.py create mode 100644 tests/functional/event_handler/_pydantic/merge_handlers/shared/products_routes.py create mode 100644 tests/functional/event_handler/_pydantic/merge_handlers/shared/resolver.py diff --git a/aws_lambda_powertools/event_handler/openapi/merge.py b/aws_lambda_powertools/event_handler/openapi/merge.py index 9db9c0daa5c..4b7f51cab1c 100644 --- a/aws_lambda_powertools/event_handler/openapi/merge.py +++ b/aws_lambda_powertools/event_handler/openapi/merge.py @@ -7,6 +7,7 @@ import importlib.util import logging import sys +import warnings from pathlib import Path from typing import TYPE_CHECKING, Any, Literal @@ -53,9 +54,9 @@ def _is_resolver_call(node: ast.expr) -> bool: func = node.func if isinstance(func, ast.Name) and func.id in RESOLVER_CLASSES: return True - if isinstance(func, ast.Attribute) and func.attr in RESOLVER_CLASSES: # pragma: no cover + if isinstance(func, ast.Attribute) and func.attr in RESOLVER_CLASSES: return True - return False # pragma: no cover + return False def _file_has_resolver(file_path: Path, resolver_name: str) -> bool: @@ -82,6 +83,65 @@ def _file_has_resolver(file_path: Path, resolver_name: str) -> bool: return False +def _file_imports_resolver(file_path: Path, resolver_file: Path, resolver_name: str, root: Path) -> bool: + """Check if a Python file imports the resolver from the resolver file.""" + try: + source = file_path.read_text(encoding="utf-8") + tree = ast.parse(source, filename=str(file_path)) + except (SyntaxError, UnicodeDecodeError): + return False + + # Get the module path of the resolver file relative to root + # e.g., "service/handlers/utils/rest_api_resolver.py" -> "service.handlers.utils.rest_api_resolver" + resolver_relative = resolver_file.relative_to(root).with_suffix("") + resolver_module = ".".join(resolver_relative.parts) + + for node in ast.walk(tree): + # Check "from X import app" or "from X import app as something" + if isinstance(node, ast.ImportFrom) and node.module: + for alias in node.names: + if alias.name == resolver_name: + # Check if the import module matches the resolver module + if node.module == resolver_module: + return True + return False + + +def _find_dependent_files( + search_path: Path, + resolver_file: Path, + resolver_name: str, + exclude: list[str], + project_root: Path, +) -> list[Path]: + """Find all Python files that import the resolver. + + Parameters + ---------- + search_path : Path + Directory to search for dependent files. + resolver_file : Path + The resolver file that dependents import from. + resolver_name : str + Variable name of the resolver. + exclude : list[str] + Patterns to exclude. + project_root : Path + Root directory for resolving Python imports. + """ + dependent_files: list[Path] = [] + + for file_path in search_path.rglob("*.py"): + if file_path == resolver_file: + continue + if _is_excluded(file_path, search_path, exclude): + continue + if _file_imports_resolver(file_path, resolver_file, resolver_name, project_root): + dependent_files.append(file_path) + + return sorted(dependent_files) + + def _is_excluded(file_path: Path, root: Path, exclude_patterns: list[str]) -> bool: """Check if a file matches any exclusion pattern.""" relative_str = str(file_path.relative_to(root)) @@ -91,12 +151,11 @@ def _is_excluded(file_path: Path, root: Path, exclude_patterns: list[str]) -> bo sub_pattern = pattern[3:] if fnmatch.fnmatch(relative_str, pattern) or fnmatch.fnmatch(file_path.name, sub_pattern): return True - # Check directory parts - remove trailing glob patterns clean_pattern = sub_pattern.replace("/**", "").replace("/*", "") for part in file_path.relative_to(root).parts: - if fnmatch.fnmatch(part, clean_pattern): # pragma: no cover + if fnmatch.fnmatch(part, clean_pattern): return True - elif fnmatch.fnmatch(relative_str, pattern) or fnmatch.fnmatch(file_path.name, pattern): # pragma: no cover + elif fnmatch.fnmatch(relative_str, pattern) or fnmatch.fnmatch(file_path.name, pattern): return True return False @@ -106,7 +165,7 @@ def _get_glob_pattern(pat: str, recursive: bool) -> str: if recursive and not pat.startswith("**/"): return f"**/{pat}" if not recursive and pat.startswith("**/"): - return pat[3:] # Strip **/ prefix + return pat[3:] return pat @@ -138,133 +197,87 @@ def _discover_resolver_files( return sorted(found_files) -def _load_resolver(file_path: Path, resolver_name: str) -> Any: - """Load a resolver instance from a Python file.""" - file_path = Path(file_path).resolve() - module_name = f"_powertools_openapi_merge_{file_path.stem}_{id(file_path)}" - +def _load_module(file_path: Path, module_name: str) -> Any: + """Load a Python module from file.""" spec = importlib.util.spec_from_file_location(module_name, file_path) - if spec is None or spec.loader is None: # pragma: no cover + if spec is None or spec.loader is None: raise ImportError(f"Cannot load module from {file_path}") module = importlib.util.module_from_spec(spec) - module_dir = str(file_path.parent) + sys.modules[module_name] = module + spec.loader.exec_module(module) + return module + + +def _load_resolver_with_dependencies( + file_path: Path, + resolver_name: str, + dependent_files: list[Path], + root: Path, +) -> Any: + """Load a resolver instance, first loading all dependent files that register routes.""" + file_path = Path(file_path).resolve() + + # Add root to sys.path if not already there + root_str = str(root) original_path = sys.path.copy() try: - if module_dir not in sys.path: - sys.path.insert(0, module_dir) - sys.modules[module_name] = module - spec.loader.exec_module(module) + if root_str not in sys.path: + sys.path.insert(0, root_str) + + # First, load all dependent files (they will import the resolver and register routes) + for dep_file in dependent_files: + dep_module_name = f"_powertools_dep_{dep_file.stem}_{id(dep_file)}" + try: + _load_module(dep_file, dep_module_name) + logger.debug(f"Loaded dependent file: {dep_file}") + except Exception as e: + warnings.warn( + f"Failed to load dependent file {dep_file}: {e}. " + "If your handler module has side effects at import time " + "(e.g. environment variable validation, database connections), " + "consider deferring them to runtime.", + stacklevel=2, + ) + + # Now get the resolver - it should already be loaded by the dependent files + # Try to get it from the module that was loaded by dependents + resolver_relative = file_path.relative_to(root).with_suffix("") + resolver_module_name = ".".join(resolver_relative.parts) + + if resolver_module_name in sys.modules: + module = sys.modules[resolver_module_name] + else: + # Fallback: load the resolver file directly + module_name = f"_powertools_openapi_merge_{file_path.stem}_{id(file_path)}" + module = _load_module(file_path, module_name) if not hasattr(module, resolver_name): raise AttributeError(f"Resolver '{resolver_name}' not found in {file_path}.") return getattr(module, resolver_name) finally: sys.path = original_path - sys.modules.pop(module_name, None) def _model_to_dict(obj: Any) -> Any: """Convert Pydantic model to dict if needed.""" if hasattr(obj, "model_dump"): return obj.model_dump(by_alias=True, exclude_none=True) - return obj # pragma: no cover + return obj class OpenAPIMerge: """ Discover and merge OpenAPI schemas from multiple Lambda handlers. - This class is designed for micro-functions architectures where you have multiple - Lambda functions, each with its own resolver, and need to generate a unified - OpenAPI specification. It's particularly useful for: + This class supports two patterns: + 1. Standard pattern: Each handler file defines its own resolver with routes + 2. Shared resolver pattern: A central resolver file is imported by multiple handler files + that register routes on it - - CI/CD pipelines to generate and publish unified API documentation - - Build-time schema generation for API Gateway imports - - Creating a dedicated Lambda that serves the consolidated OpenAPI spec - - The class uses AST analysis to detect resolver instances without importing modules, - making discovery fast and safe. - - Parameters - ---------- - title : str - The title of the unified API. - version : str - The version of the API (e.g., "1.0.0"). - openapi_version : str, default "3.1.0" - The OpenAPI specification version. - summary : str, optional - A short summary of the API. - description : str, optional - A detailed description of the API. - tags : list[Tag | str], optional - Tags for API documentation organization. - servers : list[Server], optional - Server objects for API connectivity information. - terms_of_service : str, optional - URL to the Terms of Service. - contact : Contact, optional - Contact information for the API. - license_info : License, optional - License information for the API. - security_schemes : dict[str, SecurityScheme], optional - Security scheme definitions. - security : list[dict[str, list[str]]], optional - Global security requirements. - external_documentation : ExternalDocumentation, optional - Link to external documentation. - openapi_extensions : dict[str, Any], optional - OpenAPI specification extensions (x-* fields). - on_conflict : Literal["warn", "error", "first", "last"], default "warn" - Strategy when the same path+method is defined in multiple handlers: - - "warn": Log warning and keep first definition - - "error": Raise OpenAPIMergeError - - "first": Silently keep first definition - - "last": Use last definition (override) - - Example - ------- - **CI/CD Pipeline - Generate unified schema at build time:** - - >>> from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge - >>> - >>> merge = OpenAPIMerge( - ... title="My Unified API", - ... version="1.0.0", - ... description="Consolidated API from multiple Lambda functions", - ... ) - >>> merge.discover( - ... path="./src/functions", - ... pattern="**/handler.py", - ... exclude=["**/tests/**"], - ... ) - >>> schema_json = merge.get_openapi_json_schema() - >>> - >>> # Write to file for API Gateway import or documentation - >>> with open("openapi.json", "w") as f: - ... f.write(schema_json) - - **Dedicated OpenAPI Lambda - Serve unified spec at runtime:** - - >>> from aws_lambda_powertools.event_handler import APIGatewayRestResolver - >>> - >>> app = APIGatewayRestResolver() - >>> app.configure_openapi_merge( - ... path="./functions", - ... pattern="**/handler.py", - ... title="My API", - ... version="1.0.0", - ... ) - >>> app.enable_swagger(path="/docs") # Swagger UI with merged schema - >>> - >>> def handler(event, context): - ... return app.resolve(event, context) - - See Also - -------- - OpenAPIMergeError : Exception raised on merge conflicts when on_conflict="error" + For the shared resolver pattern, this class automatically discovers files that import + the resolver and loads them before extracting the schema, ensuring all routes are registered. """ def __init__( @@ -304,9 +317,12 @@ def __init__( ) self._schemas: list[dict[str, Any]] = [] self._discovered_files: list[Path] = [] + self._dependent_files: dict[Path, list[Path]] = {} self._resolver_name: str = "app" self._on_conflict = on_conflict self._cached_schema: dict[str, Any] | None = None + self._root: Path | None = None + self._exclude: list[str] = [] def discover( self, @@ -315,45 +331,41 @@ def discover( exclude: list[str] | None = None, resolver_name: str = "app", recursive: bool = False, + project_root: str | Path | None = None, ) -> list[Path]: - """ - Discover resolver files in the specified path using glob patterns. - - This method scans the directory tree for Python files matching the pattern, - then uses AST analysis to identify files containing resolver instances. + """Discover resolver files and their dependent handler files. Parameters ---------- path : str | Path - Root directory to search for handler files. - pattern : str | list[str], default "handler.py" + Directory to search for resolver files. + pattern : str | list[str] Glob pattern(s) to match handler files. - exclude : list[str], optional - Patterns to exclude. Defaults to ["**/tests/**", "**/__pycache__/**", "**/.venv/**"]. - resolver_name : str, default "app" - Variable name of the resolver instance in handler files. - recursive : bool, default False - Whether to search recursively in subdirectories. - - Returns - ------- - list[Path] - List of discovered files containing resolver instances. - - Example - ------- - >>> merge = OpenAPIMerge(title="API", version="1.0.0") - >>> files = merge.discover( - ... path="./src", - ... pattern=["handler.py", "api.py"], - ... exclude=["**/tests/**", "**/legacy/**"], - ... recursive=True, - ... ) - >>> print(f"Found {len(files)} handlers") + exclude : list[str] | None + Patterns to exclude. + resolver_name : str + Variable name of the resolver instance. + recursive : bool + Whether to search recursively. + project_root : str | Path | None + Root directory for resolving Python imports. If None, uses current working directory. + This is needed when handlers import the resolver using absolute imports like + 'from service.handlers.utils.resolver import app'. """ exclude = exclude or ["**/tests/**", "**/__pycache__/**", "**/.venv/**"] + self._exclude = exclude self._resolver_name = resolver_name + self._search_path = Path(path).resolve() + self._root = Path(project_root).resolve() if project_root else self._search_path + self._discovered_files = _discover_resolver_files(path, pattern, exclude, resolver_name, recursive) + + # For each resolver file, find files that import it (search within path, resolve imports with project_root) + for resolver_file in self._discovered_files: + dependent = _find_dependent_files(self._search_path, resolver_file, resolver_name, exclude, self._root) + self._dependent_files[resolver_file] = dependent + logger.debug(f"Found {len(dependent)} dependent files for {resolver_file}") + return self._discovered_files def add_file(self, file_path: str | Path, resolver_name: str | None = None) -> None: @@ -376,87 +388,75 @@ def add_schema(self, schema: dict[str, Any]) -> None: """ self._schemas.append(_model_to_dict(schema)) - def get_openapi_schema(self) -> dict[str, Any]: - """ - Generate the merged OpenAPI schema as a dictionary. - - Loads all discovered resolver files, extracts their OpenAPI schemas, - and merges them into a single unified specification. - - The schema is cached after the first generation for performance. + @property + def discovered_files(self) -> list[Path]: + """Get the list of discovered resolver files.""" + return self._discovered_files.copy() - Returns - ------- - dict[str, Any] - The merged OpenAPI schema. + @property + def dependent_files(self) -> dict[Path, list[Path]]: + """Get the mapping of resolver files to their dependent handler files.""" + return {k: v.copy() for k, v in self._dependent_files.items()} - Raises - ------ - OpenAPIMergeError - If on_conflict="error" and duplicate path+method combinations are found. - """ + def get_openapi_schema(self) -> dict[str, Any]: + """Generate the merged OpenAPI schema.""" if self._cached_schema is not None: return self._cached_schema - # Load schemas from discovered files for file_path in self._discovered_files: try: - resolver = _load_resolver(file_path, self._resolver_name) + dependent = self._dependent_files.get(file_path, []) + root = self._root or file_path.parent + resolver = _load_resolver_with_dependencies( + file_path, + self._resolver_name, + dependent, + root, + ) if hasattr(resolver, "get_openapi_schema"): self._schemas.append(_model_to_dict(resolver.get_openapi_schema())) - except (ImportError, AttributeError, FileNotFoundError) as e: # pragma: no cover - logger.warning(f"Failed to load resolver from {file_path}: {e}") + except (ImportError, AttributeError, FileNotFoundError) as e: + warnings.warn( + f"Failed to load resolver from {file_path}: {e}. " + "If your handler module has side effects at import time " + "(e.g. environment variable validation, database connections), " + "consider deferring them to runtime.", + stacklevel=1, + ) self._cached_schema = self._merge_schemas() + + if self._discovered_files and not self._cached_schema.get("paths"): + warnings.warn( + f"OpenAPIMerge discovered {len(self._discovered_files)} handler file(s) " + "but the final schema has no paths. " + "Check if your handler modules have side effects at import time " + "that prevent route registration.", + stacklevel=1, + ) + return self._cached_schema def get_openapi_json_schema(self) -> str: - """ - Generate the merged OpenAPI schema as a JSON string. - - This is the recommended method for CI/CD pipelines and build-time - schema generation, as the output can be directly written to a file - or used for API Gateway imports. - - Returns - ------- - str - The merged OpenAPI schema as formatted JSON. - - Example - ------- - >>> merge = OpenAPIMerge(title="API", version="1.0.0") - >>> merge.discover(path="./functions", pattern="**/handler.py") - >>> json_schema = merge.get_openapi_json_schema() - >>> with open("openapi.json", "w") as f: - ... f.write(json_schema) - """ + """Generate the merged OpenAPI schema as JSON string.""" from aws_lambda_powertools.event_handler.openapi.compat import model_json from aws_lambda_powertools.event_handler.openapi.models import OpenAPI schema = self.get_openapi_schema() return model_json(OpenAPI(**schema), by_alias=True, exclude_none=True, indent=2) - @property - def discovered_files(self) -> list[Path]: - """Get the list of discovered resolver files.""" - return self._discovered_files.copy() - def _merge_schemas(self) -> dict[str, Any]: """Merge all schemas into a single OpenAPI schema.""" cfg = self._config - # Build base schema merged: dict[str, Any] = { "openapi": cfg.openapi_version, "info": {"title": cfg.title, "version": cfg.version}, "servers": [_model_to_dict(s) for s in cfg.servers] if cfg.servers else [{"url": "/"}], } - # Add optional info fields self._add_optional_info_fields(merged, cfg) - # Merge paths and components merged_paths: dict[str, Any] = {} merged_components: dict[str, dict[str, Any]] = {} @@ -464,7 +464,6 @@ def _merge_schemas(self) -> dict[str, Any]: self._merge_paths(schema.get("paths", {}), merged_paths) self._merge_components(schema.get("components", {}), merged_components) - # Add security schemes from config if cfg.security_schemes: merged_components.setdefault("securitySchemes", {}).update(cfg.security_schemes) @@ -473,7 +472,6 @@ def _merge_schemas(self) -> dict[str, Any]: if merged_components: merged["components"] = merged_components - # Merge tags if merged_tags := self._merge_tags(): merged["tags"] = merged_tags @@ -521,12 +519,7 @@ def _handle_conflict(self, method: str, path: str, target: dict, operation: Any) target[path][method] = operation def _merge_components(self, source: dict[str, Any], target: dict[str, dict[str, Any]]) -> None: - """Merge components from source into target. - - Note: Components with the same name are silently overwritten (last wins). - This is intentional as component conflicts are typically user errors - (e.g., two handlers defining different 'User' schemas). - """ + """Merge components from source into target.""" for component_type, components in source.items(): target.setdefault(component_type, {}).update(components) @@ -534,7 +527,6 @@ def _merge_tags(self) -> list[dict[str, Any]]: """Merge tags from config and schemas.""" tags_map: dict[str, dict[str, Any]] = {} - # Config tags first for tag in self._config.tags or []: if isinstance(tag, str): tags_map[tag] = {"name": tag} @@ -542,11 +534,10 @@ def _merge_tags(self) -> list[dict[str, Any]]: tag_dict = _model_to_dict(tag) tags_map[tag_dict["name"]] = tag_dict - # Schema tags (don't override config) for schema in self._schemas: for tag in schema.get("tags", []): name = tag["name"] if isinstance(tag, dict) else tag if name not in tags_map: - tags_map[name] = tag if isinstance(tag, dict) else {"name": tag} # pragma: no cover + tags_map[name] = tag if isinstance(tag, dict) else {"name": tag} return list(tags_map.values()) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index b5b312e7a26..b9666457dc8 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -485,7 +485,7 @@ This value will override the value of the failed response validation http code s We use the `Annotated` type to tell the Event Handler that a particular parameter is not only an optional string, but also a query string with constraints. -In the following example, we use a new `Query` OpenAPI type to add [one out of many possible constraints](#customizing-openapi-parameters), which should read as: +In the following example, we use a new `Query` OpenAPI type to add [one out of many possible constraints](openapi.md#customizing-parameters), which should read as: * `completed` is a query string with a `None` as its default value * `completed`, when set, should have at minimum 4 characters @@ -539,7 +539,7 @@ In the following example, we use a new `Query` OpenAPI type to add [one out of m #### Validating path parameters -Just like we learned in [query string validation](#validating-query-strings), we can use a new `Path` OpenAPI type to [add constraints](#customizing-openapi-parameters). +Just like we learned in [query string validation](#validating-query-strings), we can use a new `Path` OpenAPI type to [add constraints](openapi.md#customizing-parameters). For example, we could validate that `` dynamic path should be no greater than three digits. @@ -555,7 +555,7 @@ For example, we could validate that `` dynamic path should be no greate We use the `Annotated` type to tell the Event Handler that a particular parameter is a header that needs to be validated. Also, we adhere to [HTTP RFC standards](https://www.rfc-editor.org/rfc/rfc7540#section-8.1.2){target="_blank" rel="nofollow"}, which means we treat HTTP headers as case-insensitive. -In the following example, we use a new `Header` OpenAPI type to add [one out of many possible constraints](#customizing-openapi-parameters), which should read as: +In the following example, we use a new `Header` OpenAPI type to add [one out of many possible constraints](openapi.md#customizing-parameters), which should read as: * `correlation_id` is a header that must be present in the request * `correlation_id` should have 16 characters @@ -767,28 +767,15 @@ We provide pre-defined errors for the most popular ones based on [AWS Lambda API ### Enabling SwaggerUI -!!! note "This feature requires [data validation](#data-validation) feature to be enabled." +???+ tip "OpenAPI documentation has moved" + For complete OpenAPI documentation including Swagger UI customization, security schemes, and OpenAPI Merge for micro-functions, see the dedicated [OpenAPI documentation](openapi.md). -Behind the scenes, the [data validation](#data-validation) feature auto-generates an OpenAPI specification from your routes and type annotations. You can use [Swagger UI](https://swagger.io/tools/swagger-ui/){target="_blank" rel="nofollow"} to visualize and interact with your newly auto-documented API. - -There are some important **caveats** that you should know before enabling it: - -| Caveat | Description | -| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Swagger UI is **publicly accessible by default** | When using `enable_swagger` method, you can [protect sensitive API endpoints by implementing a custom middleware](#customizing-swagger-ui) using your preferred authorization mechanism. | -| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. | -| You need to expose a **new route** | You'll need to expose the following path to Lambda: `/swagger`; ignore if you're routing this path already. | -| JS and CSS files are **embedded within Swagger HTML** | If you are not using an external CDN to serve Swagger UI assets, we embed JS and CSS directly into the HTML. To enhance performance, please consider enabling the `compress` option to minimize the size of HTTP requests. | -| Authorization data is **lost** on browser close/refresh | Use `enable_swagger(persist_authorization=True)` to persist authorization data, like OAuath 2.0 access tokens. | +Use `enable_swagger()` to serve interactive API documentation: ```python hl_lines="12-13" title="enabling_swagger.py" --8<-- "examples/event_handler_rest/src/enabling_swagger.py" ``` -1. `enable_swagger` creates a route to serve Swagger UI and allows quick customizations.

You can also include middlewares to protect or enhance the overall experience. - -Here's an example of what it looks like by default: - ![Swagger UI picture](../../media/swagger.png) ### Custom Domain API Mappings @@ -1274,128 +1261,8 @@ This will enable full tracebacks errors in the response, print request and respo ### OpenAPI -When you enable [Data Validation](#data-validation), we use a combination of Pydantic Models and [OpenAPI](https://www.openapis.org/){target="_blank" rel="nofollow"} type annotations to add constraints to your API's parameters. - -???+ warning "OpenAPI schema version depends on the installed version of Pydantic" - Pydantic v1 generates [valid OpenAPI 3.0.3 schemas](https://docs.pydantic.dev/1.10/usage/schema/){target="_blank" rel="nofollow"}, and Pydantic v2 generates [valid OpenAPI 3.1.0 schemas](https://docs.pydantic.dev/latest/why/#json-schema){target="_blank" rel="nofollow"}. - -In OpenAPI documentation tools like [SwaggerUI](#enabling-swaggerui), these annotations become readable descriptions, offering a self-explanatory API interface. This reduces boilerplate code while improving functionality and enabling auto-documentation. - -???+ note - We don't have support for files, form data, and header parameters at the moment. If you're interested in this, please [open an issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&projects=&template=feature_request.yml&title=Feature+request%3A+TITLE). - -#### Customizing OpenAPI parameters - ---8<-- "docs/core/event_handler/_openapi_customization_parameters.md" - -#### Customizing API operations - ---8<-- "docs/core/event_handler/_openapi_customization_operations.md" - -To implement these customizations, include extra parameters when defining your routes: - -```python hl_lines="11-20" title="customizing_api_operations.py" ---8<-- "examples/event_handler_rest/src/customizing_api_operations.py" -``` - -#### Customizing OpenAPI metadata - ---8<-- "docs/core/event_handler/_openapi_customization_metadata.md" - -Include extra parameters when exporting your OpenAPI specification to apply these customizations: - -=== "customizing_api_metadata.py" - - ```python hl_lines="8-16" - --8<-- "examples/event_handler_rest/src/customizing_api_metadata.py" - ``` - -#### Customizing Swagger UI - -???+note "Customizing the Swagger metadata" - The `enable_swagger` method accepts the same metadata as described at [Customizing OpenAPI metadata](#customizing-openapi-metadata). - -The Swagger UI appears by default at the `/swagger` path, but you can customize this to serve the documentation from another path and specify the source for Swagger UI assets. - -Below is an example configuration for serving Swagger UI from a custom path or CDN, with assets like CSS and JavaScript loading from a chosen CDN base URL. - -=== "customizing_swagger.py" - - ```python hl_lines="10" - --8<-- "examples/event_handler_rest/src/customizing_swagger.py" - ``` - -=== "customizing_swagger_middlewares.py" - - A Middleware can handle tasks such as adding security headers, user authentication, or other request processing for serving the Swagger UI. - - ```python hl_lines="7 13-18 21" - --8<-- "examples/event_handler_rest/src/customizing_swagger_middlewares.py" - ``` - -#### Security schemes - -???-info "Does Powertools implement any of the security schemes?" - No. Powertools adds support for generating OpenAPI documentation with [security schemes](https://swagger.io/docs/specification/authentication/), but it doesn't implement any of the security schemes itself, so you must implement the security mechanisms separately. - -Security schemes are declared at the top-level first. You can reference them globally or on a per path _(operation)_ level. **However**, if you reference security schemes that are not defined at the top-level it will lead to a `SchemaValidationError` _(invalid OpenAPI spec)_. - -=== "Global OpenAPI security schemes" - - ```python title="security_schemes_global.py" hl_lines="17-27" - --8<-- "examples/event_handler_rest/src/security_schemes_global.py" - ``` - - 1. Using the oauth security scheme defined earlier, scoped to the "admin" role. - -=== "Per Operation security" - - ```python title="security_schemes_per_operation.py" hl_lines="17-26 30" - --8<-- "examples/event_handler_rest/src/security_schemes_per_operation.py" - ``` - - 1. Using the oauth security scheme defined bellow, scoped to the "admin" role. - -=== "Global security schemes and optional security per route" - - ```python title="security_schemes_global_and_optional.py" hl_lines="17-26 35" - --8<-- "examples/event_handler_rest/src/security_schemes_global_and_optional.py" - ``` - - 1. To make security optional in a specific route, an empty security requirement ({}) can be included in the array. - -OpenAPI 3 lets you describe APIs protected using the following security schemes: - -| Security Scheme | Type | Description | -| --------------------------------------------------------------------------------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [HTTP auth](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml){target="_blank"} | `HTTPBase` | HTTP authentication schemes using the Authorization header (e.g: [Basic auth](https://swagger.io/docs/specification/authentication/basic-authentication/){target="_blank"}, [Bearer](https://swagger.io/docs/specification/authentication/bearer-authentication/){target="_blank"}) | -| [API keys](https://swagger.io/docs/specification/authentication/api-keys/){target="_blank"} (e.g: query strings, cookies) | `APIKey` | API keys in headers, query strings or [cookies](https://swagger.io/docs/specification/authentication/cookie-authentication/){target="_blank"}. | -| [OAuth 2](https://swagger.io/docs/specification/authentication/oauth2/){target="_blank"} | `OAuth2` | Authorization protocol that gives an API client limited access to user data on a web server. | -| [OpenID Connect Discovery](https://swagger.io/docs/specification/authentication/openid-connect-discovery/){target="_blank"} | `OpenIdConnect` | Identity layer built [on top of the OAuth 2.0 protocol](https://openid.net/developers/how-connect-works/){target="_blank"} and supported by some OAuth 2.0. | -| [Mutual TLS](https://swagger.io/specification/#security-scheme-object){target="_blank"}. | `MutualTLS` | Client/server certificate mutual authentication scheme. | - -???-note "Using OAuth2 with the Swagger UI?" - You can use the `OAuth2Config` option to configure a default OAuth2 app on the generated Swagger UI. - - ```python hl_lines="10 15-18 22" - --8<-- "examples/event_handler_rest/src/swagger_with_oauth2.py" - ``` - -#### OpenAPI extensions - -For a better experience when working with Lambda and Amazon API Gateway, customers can define extensions using the `openapi_extensions` parameter. We support defining OpenAPI extensions at the following levels of the OpenAPI JSON Schema: Root, Servers, Operation, and Security Schemes. - -???+ warning - We do not support the `x-amazon-apigateway-any-method` and `x-amazon-apigateway-integrations` extensions. - -```python hl_lines="9 15 25 28" title="Adding OpenAPI extensions" ---8<-- "examples/event_handler_rest/src/working_with_openapi_extensions.py" -``` - -1. Server level -2. Operation level -3. Security scheme level -4. Root level +???+ tip "OpenAPI documentation has moved" + For complete OpenAPI documentation including customization, security schemes, extensions, and OpenAPI Merge for micro-functions, see the dedicated [OpenAPI documentation](openapi.md). ### Custom serializer diff --git a/docs/core/event_handler/openapi.md b/docs/core/event_handler/openapi.md new file mode 100644 index 00000000000..5a4980fafec --- /dev/null +++ b/docs/core/event_handler/openapi.md @@ -0,0 +1,452 @@ +--- +title: OpenAPI +description: Core utility - OpenAPI documentation and schema generation +--- + + + +Powertools for AWS Lambda supports automatic OpenAPI schema generation from your route definitions and type annotations. This includes Swagger UI integration, schema customization, and OpenAPI Merge for micro-functions architectures. + +## Key features + +* **Automatic schema generation** from Pydantic models and type annotations +* **Swagger UI** for interactive API documentation +* **OpenAPI Merge** for generating unified schemas from multiple Lambda handlers +* **Security schemes** support (OAuth2, API Key, HTTP auth, etc.) +* **Customizable** metadata, operations, and parameters + +## Swagger UI + +Behind the scenes, the [data validation](api_gateway.md#data-validation) feature auto-generates an OpenAPI specification from your routes and type annotations. You can use [Swagger UI](https://swagger.io/tools/swagger-ui/){target="_blank" rel="nofollow"} to visualize and interact with your API. + +!!! note "This feature requires [data validation](api_gateway.md#data-validation) to be enabled." + +???+ warning "Important caveats" + | Caveat | Description | + | ------ | ----------- | + | Swagger UI is **publicly accessible by default** | Implement a [custom middleware](#customizing-swagger-ui) for authorization | + | You need to expose a **new route** | Expose `/swagger` path to Lambda | + | JS and CSS files are **embedded within Swagger HTML** | Consider enabling `compress` option for better performance | + | Authorization data is **lost** on browser close/refresh | Use `enable_swagger(persist_authorization=True)` to persist | + +=== "enabling_swagger.py" + + ```python hl_lines="12-13" + --8<-- "examples/event_handler_rest/src/enabling_swagger.py" + ``` + + 1. `enable_swagger` creates a route to serve Swagger UI and allows quick customizations. + +Here's an example of what it looks like by default: + +![Swagger UI picture](../../media/swagger.png) + +### Customizing Swagger UI + +The Swagger UI appears by default at the `/swagger` path, but you can customize this to serve the documentation from another path and specify the source for Swagger UI assets. + +=== "customizing_swagger.py" + + ```python hl_lines="10" + --8<-- "examples/event_handler_rest/src/customizing_swagger.py" + ``` + +=== "customizing_swagger_middlewares.py" + + Use middleware for security headers, authentication, or other request processing. + + ```python hl_lines="7 13-18 21" + --8<-- "examples/event_handler_rest/src/customizing_swagger_middlewares.py" + ``` + +## Customization + +### Customizing parameters + +--8<-- "docs/core/event_handler/_openapi_customization_parameters.md" + +### Customizing operations + +--8<-- "docs/core/event_handler/_openapi_customization_operations.md" + +To implement these customizations, include extra parameters when defining your routes: + +=== "customizing_api_operations.py" + + ```python hl_lines="11-20" + --8<-- "examples/event_handler_rest/src/customizing_api_operations.py" + ``` + +### Customizing metadata + +--8<-- "docs/core/event_handler/_openapi_customization_metadata.md" + +Include extra parameters when exporting your OpenAPI specification: + +=== "customizing_api_metadata.py" + + ```python hl_lines="8-16" + --8<-- "examples/event_handler_rest/src/customizing_api_metadata.py" + ``` + +### Security schemes + +???- info "Does Powertools implement any of the security schemes?" + No. Powertools adds support for generating OpenAPI documentation with [security schemes](https://swagger.io/docs/specification/authentication/), but you must implement the security mechanisms separately. + +Security schemes are declared at the top-level first, then referenced globally or per operation. + +=== "Global security schemes" + + ```python hl_lines="17-27" + --8<-- "examples/event_handler_rest/src/security_schemes_global.py" + ``` + + 1. Using the oauth security scheme defined earlier, scoped to the "admin" role. + +=== "Per operation security" + + ```python hl_lines="17-26 30" + --8<-- "examples/event_handler_rest/src/security_schemes_per_operation.py" + ``` + + 1. Using the oauth security scheme scoped to the "admin" role. + +=== "Optional security per route" + + ```python hl_lines="17-26 35" + --8<-- "examples/event_handler_rest/src/security_schemes_global_and_optional.py" + ``` + + 1. An empty security requirement ({}) makes security optional for this route. + +OpenAPI 3 supports these security schemes: + +| Security Scheme | Type | Description | +| --------------- | ---- | ----------- | +| [HTTP auth](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml){target="_blank"} | `HTTPBase` | HTTP authentication (Basic, Bearer) | +| [API keys](https://swagger.io/docs/specification/authentication/api-keys/){target="_blank"} | `APIKey` | API keys in headers, query strings or cookies | +| [OAuth 2](https://swagger.io/docs/specification/authentication/oauth2/){target="_blank"} | `OAuth2` | OAuth 2.0 authorization | +| [OpenID Connect](https://swagger.io/docs/specification/authentication/openid-connect-discovery/){target="_blank"} | `OpenIdConnect` | OpenID Connect Discovery | +| [Mutual TLS](https://swagger.io/specification/#security-scheme-object){target="_blank"} | `MutualTLS` | Client/server certificate authentication | + +???- note "Using OAuth2 with Swagger UI?" + Use `OAuth2Config` to configure a default OAuth2 app: + + ```python hl_lines="10 15-18 22" + --8<-- "examples/event_handler_rest/src/swagger_with_oauth2.py" + ``` + +### OpenAPI extensions + +Define extensions using `openapi_extensions` parameter at Root, Servers, Operation, and Security Schemes levels. + +???+ warning + We do not support `x-amazon-apigateway-any-method` and `x-amazon-apigateway-integrations` extensions. + +=== "working_with_openapi_extensions.py" + + ```python hl_lines="9 15 25 28" + --8<-- "examples/event_handler_rest/src/working_with_openapi_extensions.py" + ``` + + 1. Server level + 2. Operation level + 3. Security scheme level + 4. Root level + +## OpenAPI Merge + +OpenAPI Merge generates a unified OpenAPI schema from multiple Lambda handlers. This is designed for micro-functions architectures where each Lambda has its own resolver. + +### Why OpenAPI Merge? + +In a micro-functions architecture, each Lambda function handles a specific domain (users, orders, payments). Each has its own resolver with routes, but you need a single OpenAPI specification for documentation and API Gateway imports. + +```mermaid +graph LR + A[Users Lambda] --> D[OpenAPI Merge] + B[Orders Lambda] --> D + C[Payments Lambda] --> D + D --> E[Unified OpenAPI Schema] + E --> F[Swagger UI] + E --> G[API Gateway Import] +``` + +### How it works + +OpenAPI Merge uses AST (Abstract Syntax Tree) analysis to detect resolver instances in your handler files. **No code is executed during discovery** - it's pure static analysis. This means: + +* No side effects from importing handler code +* No Lambda cold starts +* No security concerns from arbitrary code execution +* Fast discovery across many files + +???+ warning "Handler modules must be side-effect-free at import time" + While discovery uses static analysis (AST), **schema generation requires importing your handler modules** to extract route definitions. If a handler module runs code at import time - such as validating environment variables, opening database connections, or calling external services — the import will fail silently and its routes will be missing from the final schema. + + If your schema is unexpectedly empty, check whether your handler files have decorators or top-level code that depends on runtime state. Move these to the handler function body or guard them with `if __name__ == "__main__"`. + +### Discovery parameters + +The `discover()` method accepts the following parameters: + +| Parameter | Type | Default | Description | +| --------- | ---- | ------- | ----------- | +| `path` | `str` or `Path` | required | Root directory to search for handler files | +| `pattern` | `str` or `list[str]` | `"handler.py"` | Glob pattern(s) to match handler files | +| `exclude` | `list[str]` | `["**/tests/**", "**/__pycache__/**", "**/.venv/**"]` | Patterns to exclude from discovery | +| `resolver_name` | `str` | `"app"` | Variable name of the resolver instance in handler files | +| `recursive` | `bool` | `False` | Whether to search recursively in subdirectories | +| `project_root` | `str` or `Path` | Same as `path` | Root directory for resolving Python imports | + +#### Pattern examples + +Patterns use glob syntax: + +| Pattern | Matches | +| ------- | ------- | +| `handler.py` | Files named exactly `handler.py` in the root directory | +| `*_handler.py` | Files ending with `_handler.py` (e.g., `users_handler.py`) | +| `**/*.py` | All Python files recursively (requires `recursive=True`) | +| `["handler.py", "api.py"]` | Multiple patterns | + +#### Recursive search + +By default, `recursive=False` searches only in the specified `path` directory. Set `recursive=True` to search subdirectories: + +```python +# Only searches in ./src (not subdirectories) +merge.discover(path="./src", pattern="handler.py") + +# Searches ./src and all subdirectories +merge.discover(path="./src", pattern="handler.py", recursive=True) + +# Pattern with **/ also searches recursively +merge.discover(path="./src", pattern="**/handler.py") +``` + +#### Project root for imports + +When handler files use absolute imports (e.g., `from myapp.utils.resolver import app`), set `project_root` to the directory that serves as the Python package root: + +```python +merge.discover( + path="./src/myapp/handlers", + pattern="*.py", + project_root="./src", # Allows resolving "from myapp.x import y" +) +``` + +### Getting started example + +Here's a typical micro-functions project structure and how to configure OpenAPI Merge: + +```text +my-api/ +├── functions/ +│ ├── users/ +│ │ └── handler.py # app = APIGatewayRestResolver() with /users routes +│ ├── orders/ +│ │ └── handler.py # app = APIGatewayRestResolver() with /orders routes +│ ├── payments/ +│ │ └── handler.py # app = APIGatewayRestResolver() with /payments routes +│ └── docs/ +│ └── handler.py # Dedicated Lambda to serve unified OpenAPI docs +├── scripts/ +│ └── generate_openapi.py # CI/CD script to generate openapi.json +└── template.yaml # SAM/CloudFormation template +``` + +Each handler file defines its own resolver with domain-specific routes: + +=== "functions/users/handler.py" + + ```python + from aws_lambda_powertools.event_handler import APIGatewayRestResolver + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/users") + def list_users(): + return {"users": []} + + @app.get("/users/") + def get_user(user_id: str): + return {"id": user_id, "name": "John"} + + def handler(event, context): + return app.resolve(event, context) + ``` + +=== "functions/orders/handler.py" + + ```python + from aws_lambda_powertools.event_handler import APIGatewayRestResolver + + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/orders") + def list_orders(): + return {"orders": []} + + @app.post("/orders") + def create_order(): + return {"id": "order-123"} + + def handler(event, context): + return app.resolve(event, context) + ``` + +To generate a unified OpenAPI schema, you have two options: + +=== "Option 1: CI/CD script" + + Generate `openapi.json` at build time: + + ```python + # scripts/generate_openapi.py + from pathlib import Path + from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge + + merge = OpenAPIMerge( + title="My API", + version="1.0.0", + description="Unified API documentation", + ) + + merge.discover( + path="./functions", + pattern="handler.py", + exclude=["**/docs/**"], # Exclude the docs Lambda + recursive=True, + ) + + output = Path("openapi.json") + output.write_text(merge.get_openapi_json_schema()) + print(f"Generated {output}") + ``` + +=== "Option 2: Dedicated docs Lambda" + + Serve Swagger UI from a dedicated Lambda: + + ```python + # functions/docs/handler.py + from aws_lambda_powertools.event_handler import APIGatewayRestResolver + + app = APIGatewayRestResolver() + + app.configure_openapi_merge( + path="../", # Parent directory containing other handlers + pattern="handler.py", + exclude=["**/docs/**"], + recursive=True, + title="My API", + version="1.0.0", + ) + + app.enable_swagger(path="/") + + def handler(event, context): + return app.resolve(event, context) + ``` + +### Standalone class + +Use `OpenAPIMerge` class to generate schemas. This is pure Python code where you control the paths and output. + +=== "openapi_merge_standalone.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_standalone.py" + ``` + +=== "openapi_merge_with_exclusions.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_with_exclusions.py" + ``` + +=== "openapi_merge_multiple_patterns.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_multiple_patterns.py" + ``` + +### Resolver integration + +Use `configure_openapi_merge()` on any resolver to serve merged schemas via Swagger UI. This is useful when you want a dedicated Lambda to serve the unified documentation. + +=== "openapi_merge_resolver.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_resolver.py" + ``` + +???+ warning "Routes from other Lambdas are documentation only" + The merged schema includes routes from all discovered handlers for documentation purposes. However, only routes defined in the current Lambda are actually executable. Other routes exist only in the OpenAPI spec - unless you configure API Gateway to route them to their respective Lambdas. + +### Shared resolver pattern + +In some architectures, instead of each handler file defining its own resolver, you have a central resolver file that is imported by multiple route files. Each route file registers its routes on the shared resolver instance. + +```text +src/ +├── myapp/ +│ ├── resolver.py # Defines: app = APIGatewayRestResolver() +│ ├── users_routes.py # Imports app, registers /users routes +│ ├── orders_routes.py # Imports app, registers /orders routes +│ └── payments_routes.py # Imports app, registers /payments routes +``` + +OpenAPI Merge automatically detects this pattern. When you point `discover()` to the resolver file, it finds all files that import from it and loads them to ensure all routes are registered before extracting the schema. + +=== "shared_resolver.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_shared_resolver.py" + ``` + +=== "shared_users_routes.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_shared_users_routes.py" + ``` + +=== "shared_orders_routes.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_shared_orders_routes.py" + ``` + +=== "Discovery" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_shared_discovery.py" + ``` + +### Conflict handling + +When the same path+method is defined in multiple handlers, use `on_conflict` to control behavior: + +| Strategy | Behavior | +| -------- | -------- | +| `warn` (default) | Log warning, keep first definition | +| `error` | Raise `OpenAPIMergeError` | +| `first` | Silently keep first definition | +| `last` | Use last definition (override) | + +=== "openapi_merge_conflict.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_conflict.py" + ``` + +### Full configuration + +=== "openapi_merge_full_config.py" + + ```python + --8<-- "examples/event_handler_rest/src/openapi_merge_full_config.py" + ``` diff --git a/examples/event_handler_rest/src/openapi_merge_conflict.py b/examples/event_handler_rest/src/openapi_merge_conflict.py new file mode 100644 index 00000000000..f7b90c7a946 --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_conflict.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge + +merge = OpenAPIMerge( + title="API", + version="1.0.0", + on_conflict="error", # Raise OpenAPIMergeError on conflicts +) + +merge.discover(path="./src", pattern="**/handler.py") diff --git a/examples/event_handler_rest/src/openapi_merge_full_config.py b/examples/event_handler_rest/src/openapi_merge_full_config.py new file mode 100644 index 00000000000..a52549c6aab --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_full_config.py @@ -0,0 +1,18 @@ +from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge +from aws_lambda_powertools.event_handler.openapi.models import Contact, License, Server, Tag + +merge = OpenAPIMerge( + title="My API", + version="1.0.0", + summary="API summary", + description="Full API description", + terms_of_service="https://example.com/tos", + contact=Contact(name="Support", email="support@example.com"), + license_info=License(name="MIT"), + servers=[Server(url="https://api.example.com")], + tags=[Tag(name="users", description="User operations")], + on_conflict="warn", +) + +merge.discover(path="./src", pattern="**/handler.py", recursive=True) +schema = merge.get_openapi_json_schema() diff --git a/examples/event_handler_rest/src/openapi_merge_multiple_patterns.py b/examples/event_handler_rest/src/openapi_merge_multiple_patterns.py new file mode 100644 index 00000000000..9cf2a46fc8e --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_multiple_patterns.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge + +merge = OpenAPIMerge(title="API", version="1.0.0") + +merge.discover( + path="./src", + pattern=["handler.py", "api.py", "*_routes.py"], + recursive=True, +) diff --git a/examples/event_handler_rest/src/openapi_merge_resolver.py b/examples/event_handler_rest/src/openapi_merge_resolver.py new file mode 100644 index 00000000000..cc8cccbf2a5 --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_resolver.py @@ -0,0 +1,18 @@ +from aws_lambda_powertools.event_handler import APIGatewayRestResolver + +app = APIGatewayRestResolver() + +# Configure merge - discovers handlers but doesn't execute them +app.configure_openapi_merge( + path="./functions", + pattern="**/handler.py", + title="My API", + version="1.0.0", +) + +# Swagger UI will show the merged schema +app.enable_swagger(path="/docs") + + +def handler(event, context): + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/openapi_merge_shared_discovery.py b/examples/event_handler_rest/src/openapi_merge_shared_discovery.py new file mode 100644 index 00000000000..13cdfc3cef8 --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_shared_discovery.py @@ -0,0 +1,13 @@ +from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge + +merge = OpenAPIMerge(title="API", version="1.0.0") + +# Use project_root to resolve absolute imports like "from myapp.shared_resolver import app" +merge.discover( + path="./src/myapp", + pattern="shared_resolver.py", + project_root="./src", # Root for import resolution +) + +# Automatically finds users_routes.py and orders_routes.py +# that import from shared_resolver.py diff --git a/examples/event_handler_rest/src/openapi_merge_shared_orders_routes.py b/examples/event_handler_rest/src/openapi_merge_shared_orders_routes.py new file mode 100644 index 00000000000..2682a9c6ab1 --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_shared_orders_routes.py @@ -0,0 +1,7 @@ +# Imports and registers routes on shared resolver - orders_routes.py +from myapp.shared_resolver import app # type: ignore[import-not-found] + + +@app.get("/orders") +def get_orders(): + return [] diff --git a/examples/event_handler_rest/src/openapi_merge_shared_resolver.py b/examples/event_handler_rest/src/openapi_merge_shared_resolver.py new file mode 100644 index 00000000000..decaaa3c829 --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_shared_resolver.py @@ -0,0 +1,4 @@ +# Central resolver definition - shared_resolver.py +from aws_lambda_powertools.event_handler import APIGatewayRestResolver + +app = APIGatewayRestResolver() diff --git a/examples/event_handler_rest/src/openapi_merge_shared_users_routes.py b/examples/event_handler_rest/src/openapi_merge_shared_users_routes.py new file mode 100644 index 00000000000..de4c87069de --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_shared_users_routes.py @@ -0,0 +1,12 @@ +# Imports and registers routes on shared resolver - users_routes.py +from myapp.shared_resolver import app # type: ignore[import-not-found] + + +@app.get("/users") +def get_users(): + return [] + + +@app.get("/users/") +def get_user(user_id: str): + return {"id": user_id} diff --git a/examples/event_handler_rest/src/openapi_merge_standalone.py b/examples/event_handler_rest/src/openapi_merge_standalone.py new file mode 100644 index 00000000000..ef056974901 --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_standalone.py @@ -0,0 +1,23 @@ +from pathlib import Path + +from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge + +merge = OpenAPIMerge( + title="My Unified API", + version="1.0.0", + description="Consolidated API from multiple Lambda functions", +) + +# Discover handlers +merge.discover( + path="./src/functions", + pattern="*_handler.py", + recursive=True, +) + +# Generate schema +schema_json = merge.get_openapi_json_schema() + +# Write to file +output = Path("openapi.json") +output.write_text(schema_json) diff --git a/examples/event_handler_rest/src/openapi_merge_with_exclusions.py b/examples/event_handler_rest/src/openapi_merge_with_exclusions.py new file mode 100644 index 00000000000..b781857ddc5 --- /dev/null +++ b/examples/event_handler_rest/src/openapi_merge_with_exclusions.py @@ -0,0 +1,10 @@ +from aws_lambda_powertools.event_handler.openapi import OpenAPIMerge + +merge = OpenAPIMerge(title="API", version="1.0.0") + +merge.discover( + path="./src", + pattern="**/*_handler.py", + exclude=["**/tests/**", "**/legacy/**"], + recursive=True, +) diff --git a/mkdocs.yml b/mkdocs.yml index cc51089fab0..72921ac161d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -21,6 +21,7 @@ nav: - Datadog: core/metrics/datadog.md - Event Handler: - core/event_handler/api_gateway.md + - core/event_handler/openapi.md - core/event_handler/appsync.md - core/event_handler/appsync_events.md - core/event_handler/bedrock_agents.md diff --git a/tests/functional/event_handler/_pydantic/merge_handlers/shared/__init__.py b/tests/functional/event_handler/_pydantic/merge_handlers/shared/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/functional/event_handler/_pydantic/merge_handlers/shared/categories_routes.py b/tests/functional/event_handler/_pydantic/merge_handlers/shared/categories_routes.py new file mode 100644 index 00000000000..7029ad332c7 --- /dev/null +++ b/tests/functional/event_handler/_pydantic/merge_handlers/shared/categories_routes.py @@ -0,0 +1,11 @@ +"""Categories routes - imports shared resolver and registers routes.""" + +from __future__ import annotations + +from tests.functional.event_handler._pydantic.merge_handlers.shared.resolver import app + + +@app.get("/categories") +def get_categories() -> list[dict]: + """Get all categories.""" + return [] diff --git a/tests/functional/event_handler/_pydantic/merge_handlers/shared/products_routes.py b/tests/functional/event_handler/_pydantic/merge_handlers/shared/products_routes.py new file mode 100644 index 00000000000..84d9d4bbde5 --- /dev/null +++ b/tests/functional/event_handler/_pydantic/merge_handlers/shared/products_routes.py @@ -0,0 +1,17 @@ +"""Products routes - imports shared resolver and registers routes.""" + +from __future__ import annotations + +from tests.functional.event_handler._pydantic.merge_handlers.shared.resolver import app + + +@app.get("/products") +def get_products() -> list[dict]: + """Get all products.""" + return [] + + +@app.get("/products/") +def get_product(product_id: str) -> dict: + """Get a product by ID.""" + return {"id": product_id} diff --git a/tests/functional/event_handler/_pydantic/merge_handlers/shared/resolver.py b/tests/functional/event_handler/_pydantic/merge_handlers/shared/resolver.py new file mode 100644 index 00000000000..8a7a472b216 --- /dev/null +++ b/tests/functional/event_handler/_pydantic/merge_handlers/shared/resolver.py @@ -0,0 +1,5 @@ +"""Shared resolver - routes are registered by other files that import this.""" + +from aws_lambda_powertools.event_handler import APIGatewayRestResolver + +app = APIGatewayRestResolver() diff --git a/tests/functional/event_handler/_pydantic/test_openapi_merge.py b/tests/functional/event_handler/_pydantic/test_openapi_merge.py index 12d41566e32..88834667727 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_merge.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_merge.py @@ -369,6 +369,39 @@ def test_openapi_merge_schema_is_cached(): assert len([p for p in schema1["paths"] if p == "/users"]) == 1 +def test_openapi_merge_shared_resolver_pattern(): + # GIVEN a shared resolver pattern where: + # - resolver.py defines the resolver + # - products_routes.py and categories_routes.py import it and register routes + merge = OpenAPIMerge(title="Shared Resolver API", version="1.0.0") + + # WHEN discovering with project_root set to allow absolute imports + shared_path = MERGE_HANDLERS_PATH / "shared" + project_root = Path(__file__).parent.parent.parent.parent.parent # repo root + + files = merge.discover( + path=shared_path, + pattern="resolver.py", + project_root=project_root, + ) + + # THEN it should find the resolver file + assert len(files) == 1 + assert files[0].name == "resolver.py" + + # AND it should find dependent files that import the resolver + dependent = merge.dependent_files.get(files[0], []) + dependent_names = [f.name for f in dependent] + assert "products_routes.py" in dependent_names + assert "categories_routes.py" in dependent_names + + # AND the merged schema should include routes from all dependent files + schema = merge.get_openapi_schema() + assert "/products" in schema["paths"] + assert "/products/{product_id}" in schema["paths"] + assert "/categories" in schema["paths"] + + def test_openapi_merge_discover_type_annotated_resolver(): # GIVEN an OpenAPIMerge instance merge = OpenAPIMerge(title="Typed API", version="1.0.0") diff --git a/tests/unit/event_handler/openapi/test_openapi_merge.py b/tests/unit/event_handler/openapi/test_openapi_merge.py index 21500145b35..bce18b62dea 100644 --- a/tests/unit/event_handler/openapi/test_openapi_merge.py +++ b/tests/unit/event_handler/openapi/test_openapi_merge.py @@ -10,7 +10,7 @@ _discover_resolver_files, _file_has_resolver, _is_excluded, - _load_resolver, + _load_resolver_with_dependencies, ) MERGE_HANDLERS_PATH = Path(__file__).parents[3] / "functional/event_handler/_pydantic/merge_handlers" @@ -71,7 +71,7 @@ def test_is_excluded_with_file_pattern(): def test_load_resolver_file_not_found(): with pytest.raises(FileNotFoundError): - _load_resolver(Path("/non/existent/file.py"), "app") + _load_resolver_with_dependencies(Path("/non/existent/file.py"), "app", [], Path("/")) def test_load_resolver_not_found_in_module(tmp_path: Path): @@ -79,7 +79,7 @@ def test_load_resolver_not_found_in_module(tmp_path: Path): handler_file.write_text("x = 1") with pytest.raises(AttributeError, match="Resolver 'app' not found"): - _load_resolver(handler_file, "app") + _load_resolver_with_dependencies(handler_file, "app", [], tmp_path) def test_load_resolver_success(tmp_path: Path): @@ -93,6 +93,6 @@ def test_endpoint(): return {"test": True} """) - resolver = _load_resolver(handler_file, "app") + resolver = _load_resolver_with_dependencies(handler_file, "app", [], tmp_path) assert resolver is not None assert hasattr(resolver, "get_openapi_schema") From 403c760fd2b2273a707b3ec1d3178547312647a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:08:26 +0800 Subject: [PATCH 32/84] chore(deps-dev): bump types-protobuf from 6.32.1.20260221 to 7.34.1.20260403 (#8117) chore(deps-dev): bump types-protobuf Bumps [types-protobuf](https://github.com/python/typeshed) from 6.32.1.20260221 to 7.34.1.20260403. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-protobuf dependency-version: 7.34.1.20260403 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 27 +++++++++++++++------------ pyproject.toml | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/poetry.lock b/poetry.lock index 37583604a7e..2e25a277323 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.2.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" @@ -325,7 +325,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"}, @@ -1830,7 +1830,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"}, @@ -1912,6 +1912,7 @@ 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] @@ -1930,6 +1931,7 @@ 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] @@ -1945,6 +1947,7 @@ python-versions = ">=3.10" groups = ["dev"] files = [ {file = "griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f"}, + {file = "griffelib-2.0.0.tar.gz", hash = "sha256:e504d637a089f5cab9b5daf18f7645970509bf4f53eda8d79ed71cce8bd97934"}, ] [package.extras] @@ -3405,7 +3408,7 @@ files = [ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3547,7 +3550,7 @@ files = [ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -4685,14 +4688,14 @@ types-setuptools = "*" [[package]] name = "types-protobuf" -version = "6.32.1.20260221" +version = "7.34.1.20260403" description = "Typing stubs for protobuf" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_protobuf-6.32.1.20260221-py3-none-any.whl", hash = "sha256:da7cdd947975964a93c30bfbcc2c6841ee646b318d3816b033adc2c4eb6448e4"}, - {file = "types_protobuf-6.32.1.20260221.tar.gz", hash = "sha256:6d5fb060a616bfb076cbb61b4b3c3969f5fc8bec5810f9a2f7e648ee5cbcbf6e"}, + {file = "types_protobuf-7.34.1.20260403-py3-none-any.whl", hash = "sha256:16d9bbca52ab0f306279958878567df2520f3f5579059419b0ce149a0ad1e332"}, + {file = "types_protobuf-7.34.1.20260403.tar.gz", hash = "sha256:8d7881867888e667eb9563c08a916fccdc12bdb5f9f34c31d217cce876e36765"}, ] [[package]] @@ -4801,7 +4804,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" @@ -5119,7 +5122,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" @@ -5175,4 +5178,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "f89f84ee54e29c9efaca37b5102e899b8a15a84b862f78196aa6b26f3c21f180" +content-hash = "ebcd1323432f7c0dff5d7408a9274675a491b06cc47c9488d041a33f3d39c82d" diff --git a/pyproject.toml b/pyproject.toml index 5c4c2433566..d736d2c5f37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -128,7 +128,7 @@ mkdocstrings-python = "^1.13.0" mkdocs-llmstxt = ">=0.2,<0.5" avro = "^1.12.0" protobuf = ">=6.30.2,<8.0.0" -types-protobuf = "^6.30.2.20250516" +types-protobuf = ">=6.30.2.20250516,<8.0.0.0" ty = ">=0.0.23,<0.0.28" [tool.coverage.run] From db2f13f9ef09d4febe124dd4cebdc58deb9fe633 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:11:57 +0800 Subject: [PATCH 33/84] chore(deps-dev): bump boto3-stubs from 1.42.74 to 1.42.84 (#8115) Bumps [boto3-stubs](https://github.com/youtype/mypy_boto3_builder) from 1.42.74 to 1.42.84. - [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.42.84 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> --- poetry.lock | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2e25a277323..414b736b7a0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -453,14 +453,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "boto3-stubs" -version = "1.42.74" -description = "Type annotations for boto3 1.42.74 generated with mypy-boto3-builder 8.12.0" +version = "1.42.84" +description = "Type annotations for boto3 1.42.84 generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "boto3_stubs-1.42.74-py3-none-any.whl", hash = "sha256:63b7ba180b3fe361dcae0a50dd57e1ac676149cf0c90be420fa067189bafa7c6"}, - {file = "boto3_stubs-1.42.74.tar.gz", hash = "sha256:781078235e61c78000035ece0a92befaaf846762b6a91becf6b2887331fd010d"}, + {file = "boto3_stubs-1.42.84-py3-none-any.whl", hash = "sha256:73c3f47fc18e27dfe6f17c1c4d3ee48ab6f926d1b7029d15e6771c8255a6f278"}, + {file = "boto3_stubs-1.42.84.tar.gz", hash = "sha256:c517c254e1d8f00af24f7df55c8b1061d1142405c5ac07e426ee2b5b709f3362"}, ] [package.dependencies] @@ -485,7 +485,7 @@ account = ["mypy-boto3-account (>=1.42.0,<1.43.0)"] acm = ["mypy-boto3-acm (>=1.42.0,<1.43.0)"] acm-pca = ["mypy-boto3-acm-pca (>=1.42.0,<1.43.0)"] aiops = ["mypy-boto3-aiops (>=1.42.0,<1.43.0)"] -all = ["mypy-boto3-accessanalyzer (>=1.42.0,<1.43.0)", "mypy-boto3-account (>=1.42.0,<1.43.0)", "mypy-boto3-acm (>=1.42.0,<1.43.0)", "mypy-boto3-acm-pca (>=1.42.0,<1.43.0)", "mypy-boto3-aiops (>=1.42.0,<1.43.0)", "mypy-boto3-amp (>=1.42.0,<1.43.0)", "mypy-boto3-amplify (>=1.42.0,<1.43.0)", "mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)", "mypy-boto3-amplifyuibuilder (>=1.42.0,<1.43.0)", "mypy-boto3-apigateway (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewaymanagementapi (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewayv2 (>=1.42.0,<1.43.0)", "mypy-boto3-appconfig (>=1.42.0,<1.43.0)", "mypy-boto3-appconfigdata (>=1.42.0,<1.43.0)", "mypy-boto3-appfabric (>=1.42.0,<1.43.0)", "mypy-boto3-appflow (>=1.42.0,<1.43.0)", "mypy-boto3-appintegrations (>=1.42.0,<1.43.0)", "mypy-boto3-application-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-application-insights (>=1.42.0,<1.43.0)", "mypy-boto3-application-signals (>=1.42.0,<1.43.0)", "mypy-boto3-applicationcostprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-appmesh (>=1.42.0,<1.43.0)", "mypy-boto3-apprunner (>=1.42.0,<1.43.0)", "mypy-boto3-appstream (>=1.42.0,<1.43.0)", "mypy-boto3-appsync (>=1.42.0,<1.43.0)", "mypy-boto3-arc-region-switch (>=1.42.0,<1.43.0)", "mypy-boto3-arc-zonal-shift (>=1.42.0,<1.43.0)", "mypy-boto3-artifact (>=1.42.0,<1.43.0)", "mypy-boto3-athena (>=1.42.0,<1.43.0)", "mypy-boto3-auditmanager (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling-plans (>=1.42.0,<1.43.0)", "mypy-boto3-b2bi (>=1.42.0,<1.43.0)", "mypy-boto3-backup (>=1.42.0,<1.43.0)", "mypy-boto3-backup-gateway (>=1.42.0,<1.43.0)", "mypy-boto3-backupsearch (>=1.42.0,<1.43.0)", "mypy-boto3-batch (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-dashboards (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-data-exports (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-pricing-calculator (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-recommended-actions (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore-control (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-billing (>=1.42.0,<1.43.0)", "mypy-boto3-billingconductor (>=1.42.0,<1.43.0)", "mypy-boto3-braket (>=1.42.0,<1.43.0)", "mypy-boto3-budgets (>=1.42.0,<1.43.0)", "mypy-boto3-ce (>=1.42.0,<1.43.0)", "mypy-boto3-chatbot (>=1.42.0,<1.43.0)", "mypy-boto3-chime (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-identity (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-meetings (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-messaging (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-voice (>=1.42.0,<1.43.0)", "mypy-boto3-cleanrooms (>=1.42.0,<1.43.0)", "mypy-boto3-cleanroomsml (>=1.42.0,<1.43.0)", "mypy-boto3-cloud9 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudcontrol (>=1.42.0,<1.43.0)", "mypy-boto3-clouddirectory (>=1.42.0,<1.43.0)", "mypy-boto3-cloudformation (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsm (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsmv2 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearch (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearchdomain (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail-data (>=1.42.0,<1.43.0)", "mypy-boto3-cloudwatch (>=1.42.0,<1.43.0)", "mypy-boto3-codeartifact (>=1.42.0,<1.43.0)", "mypy-boto3-codebuild (>=1.42.0,<1.43.0)", "mypy-boto3-codecatalyst (>=1.42.0,<1.43.0)", "mypy-boto3-codecommit (>=1.42.0,<1.43.0)", "mypy-boto3-codeconnections (>=1.42.0,<1.43.0)", "mypy-boto3-codedeploy (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-reviewer (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-security (>=1.42.0,<1.43.0)", "mypy-boto3-codeguruprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-codepipeline (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-connections (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-identity (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-idp (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-sync (>=1.42.0,<1.43.0)", "mypy-boto3-comprehend (>=1.42.0,<1.43.0)", "mypy-boto3-comprehendmedical (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer-automation (>=1.42.0,<1.43.0)", "mypy-boto3-config (>=1.42.0,<1.43.0)", "mypy-boto3-connect (>=1.42.0,<1.43.0)", "mypy-boto3-connect-contact-lens (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaigns (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaignsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-connectcases (>=1.42.0,<1.43.0)", "mypy-boto3-connecthealth (>=1.42.0,<1.43.0)", "mypy-boto3-connectparticipant (>=1.42.0,<1.43.0)", "mypy-boto3-controlcatalog (>=1.42.0,<1.43.0)", "mypy-boto3-controltower (>=1.42.0,<1.43.0)", "mypy-boto3-cost-optimization-hub (>=1.42.0,<1.43.0)", "mypy-boto3-cur (>=1.42.0,<1.43.0)", "mypy-boto3-customer-profiles (>=1.42.0,<1.43.0)", "mypy-boto3-databrew (>=1.42.0,<1.43.0)", "mypy-boto3-dataexchange (>=1.42.0,<1.43.0)", "mypy-boto3-datapipeline (>=1.42.0,<1.43.0)", "mypy-boto3-datasync (>=1.42.0,<1.43.0)", "mypy-boto3-datazone (>=1.42.0,<1.43.0)", "mypy-boto3-dax (>=1.42.0,<1.43.0)", "mypy-boto3-deadline (>=1.42.0,<1.43.0)", "mypy-boto3-detective (>=1.42.0,<1.43.0)", "mypy-boto3-devicefarm (>=1.42.0,<1.43.0)", "mypy-boto3-devops-guru (>=1.42.0,<1.43.0)", "mypy-boto3-directconnect (>=1.42.0,<1.43.0)", "mypy-boto3-discovery (>=1.42.0,<1.43.0)", "mypy-boto3-dlm (>=1.42.0,<1.43.0)", "mypy-boto3-dms (>=1.42.0,<1.43.0)", "mypy-boto3-docdb (>=1.42.0,<1.43.0)", "mypy-boto3-docdb-elastic (>=1.42.0,<1.43.0)", "mypy-boto3-drs (>=1.42.0,<1.43.0)", "mypy-boto3-ds (>=1.42.0,<1.43.0)", "mypy-boto3-ds-data (>=1.42.0,<1.43.0)", "mypy-boto3-dsql (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodb (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodbstreams (>=1.42.0,<1.43.0)", "mypy-boto3-ebs (>=1.42.0,<1.43.0)", "mypy-boto3-ec2 (>=1.42.0,<1.43.0)", "mypy-boto3-ec2-instance-connect (>=1.42.0,<1.43.0)", "mypy-boto3-ecr (>=1.42.0,<1.43.0)", "mypy-boto3-ecr-public (>=1.42.0,<1.43.0)", "mypy-boto3-ecs (>=1.42.0,<1.43.0)", "mypy-boto3-efs (>=1.42.0,<1.43.0)", "mypy-boto3-eks (>=1.42.0,<1.43.0)", "mypy-boto3-eks-auth (>=1.42.0,<1.43.0)", "mypy-boto3-elasticache (>=1.42.0,<1.43.0)", "mypy-boto3-elasticbeanstalk (>=1.42.0,<1.43.0)", "mypy-boto3-elb (>=1.42.0,<1.43.0)", "mypy-boto3-elbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-elementalinference (>=1.42.0,<1.43.0)", "mypy-boto3-emr (>=1.42.0,<1.43.0)", "mypy-boto3-emr-containers (>=1.42.0,<1.43.0)", "mypy-boto3-emr-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-entityresolution (>=1.42.0,<1.43.0)", "mypy-boto3-es (>=1.42.0,<1.43.0)", "mypy-boto3-events (>=1.42.0,<1.43.0)", "mypy-boto3-evs (>=1.42.0,<1.43.0)", "mypy-boto3-finspace (>=1.42.0,<1.43.0)", "mypy-boto3-finspace-data (>=1.42.0,<1.43.0)", "mypy-boto3-firehose (>=1.42.0,<1.43.0)", "mypy-boto3-fis (>=1.42.0,<1.43.0)", "mypy-boto3-fms (>=1.42.0,<1.43.0)", "mypy-boto3-forecast (>=1.42.0,<1.43.0)", "mypy-boto3-forecastquery (>=1.42.0,<1.43.0)", "mypy-boto3-frauddetector (>=1.42.0,<1.43.0)", "mypy-boto3-freetier (>=1.42.0,<1.43.0)", "mypy-boto3-fsx (>=1.42.0,<1.43.0)", "mypy-boto3-gamelift (>=1.42.0,<1.43.0)", "mypy-boto3-gameliftstreams (>=1.42.0,<1.43.0)", "mypy-boto3-geo-maps (>=1.42.0,<1.43.0)", "mypy-boto3-geo-places (>=1.42.0,<1.43.0)", "mypy-boto3-geo-routes (>=1.42.0,<1.43.0)", "mypy-boto3-glacier (>=1.42.0,<1.43.0)", "mypy-boto3-globalaccelerator (>=1.42.0,<1.43.0)", "mypy-boto3-glue (>=1.42.0,<1.43.0)", "mypy-boto3-grafana (>=1.42.0,<1.43.0)", "mypy-boto3-greengrass (>=1.42.0,<1.43.0)", "mypy-boto3-greengrassv2 (>=1.42.0,<1.43.0)", "mypy-boto3-groundstation (>=1.42.0,<1.43.0)", "mypy-boto3-guardduty (>=1.42.0,<1.43.0)", "mypy-boto3-health (>=1.42.0,<1.43.0)", "mypy-boto3-healthlake (>=1.42.0,<1.43.0)", "mypy-boto3-iam (>=1.42.0,<1.43.0)", "mypy-boto3-identitystore (>=1.42.0,<1.43.0)", "mypy-boto3-imagebuilder (>=1.42.0,<1.43.0)", "mypy-boto3-importexport (>=1.42.0,<1.43.0)", "mypy-boto3-inspector (>=1.42.0,<1.43.0)", "mypy-boto3-inspector-scan (>=1.42.0,<1.43.0)", "mypy-boto3-inspector2 (>=1.42.0,<1.43.0)", "mypy-boto3-internetmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-invoicing (>=1.42.0,<1.43.0)", "mypy-boto3-iot (>=1.42.0,<1.43.0)", "mypy-boto3-iot-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-jobs-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-managed-integrations (>=1.42.0,<1.43.0)", "mypy-boto3-iotdeviceadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents-data (>=1.42.0,<1.43.0)", "mypy-boto3-iotfleetwise (>=1.42.0,<1.43.0)", "mypy-boto3-iotsecuretunneling (>=1.42.0,<1.43.0)", "mypy-boto3-iotsitewise (>=1.42.0,<1.43.0)", "mypy-boto3-iotthingsgraph (>=1.42.0,<1.43.0)", "mypy-boto3-iottwinmaker (>=1.42.0,<1.43.0)", "mypy-boto3-iotwireless (>=1.42.0,<1.43.0)", "mypy-boto3-ivs (>=1.42.0,<1.43.0)", "mypy-boto3-ivs-realtime (>=1.42.0,<1.43.0)", "mypy-boto3-ivschat (>=1.42.0,<1.43.0)", "mypy-boto3-kafka (>=1.42.0,<1.43.0)", "mypy-boto3-kafkaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-kendra (>=1.42.0,<1.43.0)", "mypy-boto3-kendra-ranking (>=1.42.0,<1.43.0)", "mypy-boto3-keyspaces (>=1.42.0,<1.43.0)", "mypy-boto3-keyspacesstreams (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-archived-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-signaling (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisvideo (>=1.42.0,<1.43.0)", "mypy-boto3-kms (>=1.42.0,<1.43.0)", "mypy-boto3-lakeformation (>=1.42.0,<1.43.0)", "mypy-boto3-lambda (>=1.42.0,<1.43.0)", "mypy-boto3-launch-wizard (>=1.42.0,<1.43.0)", "mypy-boto3-lex-models (>=1.42.0,<1.43.0)", "mypy-boto3-lex-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-models (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-lightsail (>=1.42.0,<1.43.0)", "mypy-boto3-location (>=1.42.0,<1.43.0)", "mypy-boto3-logs (>=1.42.0,<1.43.0)", "mypy-boto3-lookoutequipment (>=1.42.0,<1.43.0)", "mypy-boto3-m2 (>=1.42.0,<1.43.0)", "mypy-boto3-machinelearning (>=1.42.0,<1.43.0)", "mypy-boto3-macie2 (>=1.42.0,<1.43.0)", "mypy-boto3-mailmanager (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain-query (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-agreement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-catalog (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-deployment (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-entitlement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-reporting (>=1.42.0,<1.43.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconvert (>=1.42.0,<1.43.0)", "mypy-boto3-medialive (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage-vod (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackagev2 (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore-data (>=1.42.0,<1.43.0)", "mypy-boto3-mediatailor (>=1.42.0,<1.43.0)", "mypy-boto3-medical-imaging (>=1.42.0,<1.43.0)", "mypy-boto3-memorydb (>=1.42.0,<1.43.0)", "mypy-boto3-meteringmarketplace (>=1.42.0,<1.43.0)", "mypy-boto3-mgh (>=1.42.0,<1.43.0)", "mypy-boto3-mgn (>=1.42.0,<1.43.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhub-config (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhuborchestrator (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhubstrategy (>=1.42.0,<1.43.0)", "mypy-boto3-mpa (>=1.42.0,<1.43.0)", "mypy-boto3-mq (>=1.42.0,<1.43.0)", "mypy-boto3-mturk (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-neptune (>=1.42.0,<1.43.0)", "mypy-boto3-neptune-graph (>=1.42.0,<1.43.0)", "mypy-boto3-neptunedata (>=1.42.0,<1.43.0)", "mypy-boto3-network-firewall (>=1.42.0,<1.43.0)", "mypy-boto3-networkflowmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-networkmanager (>=1.42.0,<1.43.0)", "mypy-boto3-networkmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-notificationscontacts (>=1.42.0,<1.43.0)", "mypy-boto3-nova-act (>=1.42.0,<1.43.0)", "mypy-boto3-oam (>=1.42.0,<1.43.0)", "mypy-boto3-observabilityadmin (>=1.42.0,<1.43.0)", "mypy-boto3-odb (>=1.42.0,<1.43.0)", "mypy-boto3-omics (>=1.42.0,<1.43.0)", "mypy-boto3-opensearch (>=1.42.0,<1.43.0)", "mypy-boto3-opensearchserverless (>=1.42.0,<1.43.0)", "mypy-boto3-organizations (>=1.42.0,<1.43.0)", "mypy-boto3-osis (>=1.42.0,<1.43.0)", "mypy-boto3-outposts (>=1.42.0,<1.43.0)", "mypy-boto3-panorama (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-account (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-benefits (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-channel (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-selling (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography-data (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-ad (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-scep (>=1.42.0,<1.43.0)", "mypy-boto3-pcs (>=1.42.0,<1.43.0)", "mypy-boto3-personalize (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-events (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-pi (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-email (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.42.0,<1.43.0)", "mypy-boto3-pipes (>=1.42.0,<1.43.0)", "mypy-boto3-polly (>=1.42.0,<1.43.0)", "mypy-boto3-pricing (>=1.42.0,<1.43.0)", "mypy-boto3-proton (>=1.42.0,<1.43.0)", "mypy-boto3-qapps (>=1.42.0,<1.43.0)", "mypy-boto3-qbusiness (>=1.42.0,<1.43.0)", "mypy-boto3-qconnect (>=1.42.0,<1.43.0)", "mypy-boto3-quicksight (>=1.42.0,<1.43.0)", "mypy-boto3-ram (>=1.42.0,<1.43.0)", "mypy-boto3-rbin (>=1.42.0,<1.43.0)", "mypy-boto3-rds (>=1.42.0,<1.43.0)", "mypy-boto3-rds-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-rekognition (>=1.42.0,<1.43.0)", "mypy-boto3-repostspace (>=1.42.0,<1.43.0)", "mypy-boto3-resiliencehub (>=1.42.0,<1.43.0)", "mypy-boto3-resource-explorer-2 (>=1.42.0,<1.43.0)", "mypy-boto3-resource-groups (>=1.42.0,<1.43.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.42.0,<1.43.0)", "mypy-boto3-rolesanywhere (>=1.42.0,<1.43.0)", "mypy-boto3-route53 (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-cluster (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-control-config (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-readiness (>=1.42.0,<1.43.0)", "mypy-boto3-route53domains (>=1.42.0,<1.43.0)", "mypy-boto3-route53globalresolver (>=1.42.0,<1.43.0)", "mypy-boto3-route53profiles (>=1.42.0,<1.43.0)", "mypy-boto3-route53resolver (>=1.42.0,<1.43.0)", "mypy-boto3-rtbfabric (>=1.42.0,<1.43.0)", "mypy-boto3-rum (>=1.42.0,<1.43.0)", "mypy-boto3-s3 (>=1.42.0,<1.43.0)", "mypy-boto3-s3control (>=1.42.0,<1.43.0)", "mypy-boto3-s3outposts (>=1.42.0,<1.43.0)", "mypy-boto3-s3tables (>=1.42.0,<1.43.0)", "mypy-boto3-s3vectors (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-edge (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-geospatial (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-metrics (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-savingsplans (>=1.42.0,<1.43.0)", "mypy-boto3-scheduler (>=1.42.0,<1.43.0)", "mypy-boto3-schemas (>=1.42.0,<1.43.0)", "mypy-boto3-sdb (>=1.42.0,<1.43.0)", "mypy-boto3-secretsmanager (>=1.42.0,<1.43.0)", "mypy-boto3-security-ir (>=1.42.0,<1.43.0)", "mypy-boto3-securityhub (>=1.42.0,<1.43.0)", "mypy-boto3-securitylake (>=1.42.0,<1.43.0)", "mypy-boto3-serverlessrepo (>=1.42.0,<1.43.0)", "mypy-boto3-service-quotas (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog-appregistry (>=1.42.0,<1.43.0)", "mypy-boto3-servicediscovery (>=1.42.0,<1.43.0)", "mypy-boto3-ses (>=1.42.0,<1.43.0)", "mypy-boto3-sesv2 (>=1.42.0,<1.43.0)", "mypy-boto3-shield (>=1.42.0,<1.43.0)", "mypy-boto3-signer (>=1.42.0,<1.43.0)", "mypy-boto3-signer-data (>=1.42.0,<1.43.0)", "mypy-boto3-signin (>=1.42.0,<1.43.0)", "mypy-boto3-simpledbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-simspaceweaver (>=1.42.0,<1.43.0)", "mypy-boto3-snow-device-management (>=1.42.0,<1.43.0)", "mypy-boto3-snowball (>=1.42.0,<1.43.0)", "mypy-boto3-sns (>=1.42.0,<1.43.0)", "mypy-boto3-socialmessaging (>=1.42.0,<1.43.0)", "mypy-boto3-sqs (>=1.42.0,<1.43.0)", "mypy-boto3-ssm (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-contacts (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-guiconnect (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-incidents (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-quicksetup (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-sap (>=1.42.0,<1.43.0)", "mypy-boto3-sso (>=1.42.0,<1.43.0)", "mypy-boto3-sso-admin (>=1.42.0,<1.43.0)", "mypy-boto3-sso-oidc (>=1.42.0,<1.43.0)", "mypy-boto3-stepfunctions (>=1.42.0,<1.43.0)", "mypy-boto3-storagegateway (>=1.42.0,<1.43.0)", "mypy-boto3-sts (>=1.42.0,<1.43.0)", "mypy-boto3-supplychain (>=1.42.0,<1.43.0)", "mypy-boto3-support (>=1.42.0,<1.43.0)", "mypy-boto3-support-app (>=1.42.0,<1.43.0)", "mypy-boto3-swf (>=1.42.0,<1.43.0)", "mypy-boto3-synthetics (>=1.42.0,<1.43.0)", "mypy-boto3-taxsettings (>=1.42.0,<1.43.0)", "mypy-boto3-textract (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-influxdb (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-query (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-write (>=1.42.0,<1.43.0)", "mypy-boto3-tnb (>=1.42.0,<1.43.0)", "mypy-boto3-transcribe (>=1.42.0,<1.43.0)", "mypy-boto3-transfer (>=1.42.0,<1.43.0)", "mypy-boto3-translate (>=1.42.0,<1.43.0)", "mypy-boto3-trustedadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-verifiedpermissions (>=1.42.0,<1.43.0)", "mypy-boto3-voice-id (>=1.42.0,<1.43.0)", "mypy-boto3-vpc-lattice (>=1.42.0,<1.43.0)", "mypy-boto3-waf (>=1.42.0,<1.43.0)", "mypy-boto3-waf-regional (>=1.42.0,<1.43.0)", "mypy-boto3-wafv2 (>=1.42.0,<1.43.0)", "mypy-boto3-wellarchitected (>=1.42.0,<1.43.0)", "mypy-boto3-wickr (>=1.42.0,<1.43.0)", "mypy-boto3-wisdom (>=1.42.0,<1.43.0)", "mypy-boto3-workdocs (>=1.42.0,<1.43.0)", "mypy-boto3-workmail (>=1.42.0,<1.43.0)", "mypy-boto3-workmailmessageflow (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-instances (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-thin-client (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-web (>=1.42.0,<1.43.0)", "mypy-boto3-xray (>=1.42.0,<1.43.0)"] +all = ["mypy-boto3-accessanalyzer (>=1.42.0,<1.43.0)", "mypy-boto3-account (>=1.42.0,<1.43.0)", "mypy-boto3-acm (>=1.42.0,<1.43.0)", "mypy-boto3-acm-pca (>=1.42.0,<1.43.0)", "mypy-boto3-aiops (>=1.42.0,<1.43.0)", "mypy-boto3-amp (>=1.42.0,<1.43.0)", "mypy-boto3-amplify (>=1.42.0,<1.43.0)", "mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)", "mypy-boto3-amplifyuibuilder (>=1.42.0,<1.43.0)", "mypy-boto3-apigateway (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewaymanagementapi (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewayv2 (>=1.42.0,<1.43.0)", "mypy-boto3-appconfig (>=1.42.0,<1.43.0)", "mypy-boto3-appconfigdata (>=1.42.0,<1.43.0)", "mypy-boto3-appfabric (>=1.42.0,<1.43.0)", "mypy-boto3-appflow (>=1.42.0,<1.43.0)", "mypy-boto3-appintegrations (>=1.42.0,<1.43.0)", "mypy-boto3-application-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-application-insights (>=1.42.0,<1.43.0)", "mypy-boto3-application-signals (>=1.42.0,<1.43.0)", "mypy-boto3-applicationcostprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-appmesh (>=1.42.0,<1.43.0)", "mypy-boto3-apprunner (>=1.42.0,<1.43.0)", "mypy-boto3-appstream (>=1.42.0,<1.43.0)", "mypy-boto3-appsync (>=1.42.0,<1.43.0)", "mypy-boto3-arc-region-switch (>=1.42.0,<1.43.0)", "mypy-boto3-arc-zonal-shift (>=1.42.0,<1.43.0)", "mypy-boto3-artifact (>=1.42.0,<1.43.0)", "mypy-boto3-athena (>=1.42.0,<1.43.0)", "mypy-boto3-auditmanager (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling-plans (>=1.42.0,<1.43.0)", "mypy-boto3-b2bi (>=1.42.0,<1.43.0)", "mypy-boto3-backup (>=1.42.0,<1.43.0)", "mypy-boto3-backup-gateway (>=1.42.0,<1.43.0)", "mypy-boto3-backupsearch (>=1.42.0,<1.43.0)", "mypy-boto3-batch (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-dashboards (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-data-exports (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-pricing-calculator (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-recommended-actions (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore-control (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-billing (>=1.42.0,<1.43.0)", "mypy-boto3-billingconductor (>=1.42.0,<1.43.0)", "mypy-boto3-braket (>=1.42.0,<1.43.0)", "mypy-boto3-budgets (>=1.42.0,<1.43.0)", "mypy-boto3-ce (>=1.42.0,<1.43.0)", "mypy-boto3-chatbot (>=1.42.0,<1.43.0)", "mypy-boto3-chime (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-identity (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-meetings (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-messaging (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-voice (>=1.42.0,<1.43.0)", "mypy-boto3-cleanrooms (>=1.42.0,<1.43.0)", "mypy-boto3-cleanroomsml (>=1.42.0,<1.43.0)", "mypy-boto3-cloud9 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudcontrol (>=1.42.0,<1.43.0)", "mypy-boto3-clouddirectory (>=1.42.0,<1.43.0)", "mypy-boto3-cloudformation (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsm (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsmv2 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearch (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearchdomain (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail-data (>=1.42.0,<1.43.0)", "mypy-boto3-cloudwatch (>=1.42.0,<1.43.0)", "mypy-boto3-codeartifact (>=1.42.0,<1.43.0)", "mypy-boto3-codebuild (>=1.42.0,<1.43.0)", "mypy-boto3-codecatalyst (>=1.42.0,<1.43.0)", "mypy-boto3-codecommit (>=1.42.0,<1.43.0)", "mypy-boto3-codeconnections (>=1.42.0,<1.43.0)", "mypy-boto3-codedeploy (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-reviewer (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-security (>=1.42.0,<1.43.0)", "mypy-boto3-codeguruprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-codepipeline (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-connections (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-identity (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-idp (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-sync (>=1.42.0,<1.43.0)", "mypy-boto3-comprehend (>=1.42.0,<1.43.0)", "mypy-boto3-comprehendmedical (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer-automation (>=1.42.0,<1.43.0)", "mypy-boto3-config (>=1.42.0,<1.43.0)", "mypy-boto3-connect (>=1.42.0,<1.43.0)", "mypy-boto3-connect-contact-lens (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaigns (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaignsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-connectcases (>=1.42.0,<1.43.0)", "mypy-boto3-connecthealth (>=1.42.0,<1.43.0)", "mypy-boto3-connectparticipant (>=1.42.0,<1.43.0)", "mypy-boto3-controlcatalog (>=1.42.0,<1.43.0)", "mypy-boto3-controltower (>=1.42.0,<1.43.0)", "mypy-boto3-cost-optimization-hub (>=1.42.0,<1.43.0)", "mypy-boto3-cur (>=1.42.0,<1.43.0)", "mypy-boto3-customer-profiles (>=1.42.0,<1.43.0)", "mypy-boto3-databrew (>=1.42.0,<1.43.0)", "mypy-boto3-dataexchange (>=1.42.0,<1.43.0)", "mypy-boto3-datapipeline (>=1.42.0,<1.43.0)", "mypy-boto3-datasync (>=1.42.0,<1.43.0)", "mypy-boto3-datazone (>=1.42.0,<1.43.0)", "mypy-boto3-dax (>=1.42.0,<1.43.0)", "mypy-boto3-deadline (>=1.42.0,<1.43.0)", "mypy-boto3-detective (>=1.42.0,<1.43.0)", "mypy-boto3-devicefarm (>=1.42.0,<1.43.0)", "mypy-boto3-devops-agent (>=1.42.0,<1.43.0)", "mypy-boto3-devops-guru (>=1.42.0,<1.43.0)", "mypy-boto3-directconnect (>=1.42.0,<1.43.0)", "mypy-boto3-discovery (>=1.42.0,<1.43.0)", "mypy-boto3-dlm (>=1.42.0,<1.43.0)", "mypy-boto3-dms (>=1.42.0,<1.43.0)", "mypy-boto3-docdb (>=1.42.0,<1.43.0)", "mypy-boto3-docdb-elastic (>=1.42.0,<1.43.0)", "mypy-boto3-drs (>=1.42.0,<1.43.0)", "mypy-boto3-ds (>=1.42.0,<1.43.0)", "mypy-boto3-ds-data (>=1.42.0,<1.43.0)", "mypy-boto3-dsql (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodb (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodbstreams (>=1.42.0,<1.43.0)", "mypy-boto3-ebs (>=1.42.0,<1.43.0)", "mypy-boto3-ec2 (>=1.42.0,<1.43.0)", "mypy-boto3-ec2-instance-connect (>=1.42.0,<1.43.0)", "mypy-boto3-ecr (>=1.42.0,<1.43.0)", "mypy-boto3-ecr-public (>=1.42.0,<1.43.0)", "mypy-boto3-ecs (>=1.42.0,<1.43.0)", "mypy-boto3-efs (>=1.42.0,<1.43.0)", "mypy-boto3-eks (>=1.42.0,<1.43.0)", "mypy-boto3-eks-auth (>=1.42.0,<1.43.0)", "mypy-boto3-elasticache (>=1.42.0,<1.43.0)", "mypy-boto3-elasticbeanstalk (>=1.42.0,<1.43.0)", "mypy-boto3-elb (>=1.42.0,<1.43.0)", "mypy-boto3-elbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-elementalinference (>=1.42.0,<1.43.0)", "mypy-boto3-emr (>=1.42.0,<1.43.0)", "mypy-boto3-emr-containers (>=1.42.0,<1.43.0)", "mypy-boto3-emr-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-entityresolution (>=1.42.0,<1.43.0)", "mypy-boto3-es (>=1.42.0,<1.43.0)", "mypy-boto3-events (>=1.42.0,<1.43.0)", "mypy-boto3-evs (>=1.42.0,<1.43.0)", "mypy-boto3-finspace (>=1.42.0,<1.43.0)", "mypy-boto3-finspace-data (>=1.42.0,<1.43.0)", "mypy-boto3-firehose (>=1.42.0,<1.43.0)", "mypy-boto3-fis (>=1.42.0,<1.43.0)", "mypy-boto3-fms (>=1.42.0,<1.43.0)", "mypy-boto3-forecast (>=1.42.0,<1.43.0)", "mypy-boto3-forecastquery (>=1.42.0,<1.43.0)", "mypy-boto3-frauddetector (>=1.42.0,<1.43.0)", "mypy-boto3-freetier (>=1.42.0,<1.43.0)", "mypy-boto3-fsx (>=1.42.0,<1.43.0)", "mypy-boto3-gamelift (>=1.42.0,<1.43.0)", "mypy-boto3-gameliftstreams (>=1.42.0,<1.43.0)", "mypy-boto3-geo-maps (>=1.42.0,<1.43.0)", "mypy-boto3-geo-places (>=1.42.0,<1.43.0)", "mypy-boto3-geo-routes (>=1.42.0,<1.43.0)", "mypy-boto3-glacier (>=1.42.0,<1.43.0)", "mypy-boto3-globalaccelerator (>=1.42.0,<1.43.0)", "mypy-boto3-glue (>=1.42.0,<1.43.0)", "mypy-boto3-grafana (>=1.42.0,<1.43.0)", "mypy-boto3-greengrass (>=1.42.0,<1.43.0)", "mypy-boto3-greengrassv2 (>=1.42.0,<1.43.0)", "mypy-boto3-groundstation (>=1.42.0,<1.43.0)", "mypy-boto3-guardduty (>=1.42.0,<1.43.0)", "mypy-boto3-health (>=1.42.0,<1.43.0)", "mypy-boto3-healthlake (>=1.42.0,<1.43.0)", "mypy-boto3-iam (>=1.42.0,<1.43.0)", "mypy-boto3-identitystore (>=1.42.0,<1.43.0)", "mypy-boto3-imagebuilder (>=1.42.0,<1.43.0)", "mypy-boto3-importexport (>=1.42.0,<1.43.0)", "mypy-boto3-inspector (>=1.42.0,<1.43.0)", "mypy-boto3-inspector-scan (>=1.42.0,<1.43.0)", "mypy-boto3-inspector2 (>=1.42.0,<1.43.0)", "mypy-boto3-internetmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-invoicing (>=1.42.0,<1.43.0)", "mypy-boto3-iot (>=1.42.0,<1.43.0)", "mypy-boto3-iot-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-jobs-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-managed-integrations (>=1.42.0,<1.43.0)", "mypy-boto3-iotdeviceadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents-data (>=1.42.0,<1.43.0)", "mypy-boto3-iotfleetwise (>=1.42.0,<1.43.0)", "mypy-boto3-iotsecuretunneling (>=1.42.0,<1.43.0)", "mypy-boto3-iotsitewise (>=1.42.0,<1.43.0)", "mypy-boto3-iotthingsgraph (>=1.42.0,<1.43.0)", "mypy-boto3-iottwinmaker (>=1.42.0,<1.43.0)", "mypy-boto3-iotwireless (>=1.42.0,<1.43.0)", "mypy-boto3-ivs (>=1.42.0,<1.43.0)", "mypy-boto3-ivs-realtime (>=1.42.0,<1.43.0)", "mypy-boto3-ivschat (>=1.42.0,<1.43.0)", "mypy-boto3-kafka (>=1.42.0,<1.43.0)", "mypy-boto3-kafkaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-kendra (>=1.42.0,<1.43.0)", "mypy-boto3-kendra-ranking (>=1.42.0,<1.43.0)", "mypy-boto3-keyspaces (>=1.42.0,<1.43.0)", "mypy-boto3-keyspacesstreams (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-archived-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-signaling (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisvideo (>=1.42.0,<1.43.0)", "mypy-boto3-kms (>=1.42.0,<1.43.0)", "mypy-boto3-lakeformation (>=1.42.0,<1.43.0)", "mypy-boto3-lambda (>=1.42.0,<1.43.0)", "mypy-boto3-launch-wizard (>=1.42.0,<1.43.0)", "mypy-boto3-lex-models (>=1.42.0,<1.43.0)", "mypy-boto3-lex-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-models (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-lightsail (>=1.42.0,<1.43.0)", "mypy-boto3-location (>=1.42.0,<1.43.0)", "mypy-boto3-logs (>=1.42.0,<1.43.0)", "mypy-boto3-lookoutequipment (>=1.42.0,<1.43.0)", "mypy-boto3-m2 (>=1.42.0,<1.43.0)", "mypy-boto3-machinelearning (>=1.42.0,<1.43.0)", "mypy-boto3-macie2 (>=1.42.0,<1.43.0)", "mypy-boto3-mailmanager (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain-query (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-agreement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-catalog (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-deployment (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-entitlement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-reporting (>=1.42.0,<1.43.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconvert (>=1.42.0,<1.43.0)", "mypy-boto3-medialive (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage-vod (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackagev2 (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore-data (>=1.42.0,<1.43.0)", "mypy-boto3-mediatailor (>=1.42.0,<1.43.0)", "mypy-boto3-medical-imaging (>=1.42.0,<1.43.0)", "mypy-boto3-memorydb (>=1.42.0,<1.43.0)", "mypy-boto3-meteringmarketplace (>=1.42.0,<1.43.0)", "mypy-boto3-mgh (>=1.42.0,<1.43.0)", "mypy-boto3-mgn (>=1.42.0,<1.43.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhub-config (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhuborchestrator (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhubstrategy (>=1.42.0,<1.43.0)", "mypy-boto3-mpa (>=1.42.0,<1.43.0)", "mypy-boto3-mq (>=1.42.0,<1.43.0)", "mypy-boto3-mturk (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-neptune (>=1.42.0,<1.43.0)", "mypy-boto3-neptune-graph (>=1.42.0,<1.43.0)", "mypy-boto3-neptunedata (>=1.42.0,<1.43.0)", "mypy-boto3-network-firewall (>=1.42.0,<1.43.0)", "mypy-boto3-networkflowmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-networkmanager (>=1.42.0,<1.43.0)", "mypy-boto3-networkmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-notificationscontacts (>=1.42.0,<1.43.0)", "mypy-boto3-nova-act (>=1.42.0,<1.43.0)", "mypy-boto3-oam (>=1.42.0,<1.43.0)", "mypy-boto3-observabilityadmin (>=1.42.0,<1.43.0)", "mypy-boto3-odb (>=1.42.0,<1.43.0)", "mypy-boto3-omics (>=1.42.0,<1.43.0)", "mypy-boto3-opensearch (>=1.42.0,<1.43.0)", "mypy-boto3-opensearchserverless (>=1.42.0,<1.43.0)", "mypy-boto3-organizations (>=1.42.0,<1.43.0)", "mypy-boto3-osis (>=1.42.0,<1.43.0)", "mypy-boto3-outposts (>=1.42.0,<1.43.0)", "mypy-boto3-panorama (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-account (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-benefits (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-channel (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-selling (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography-data (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-ad (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-scep (>=1.42.0,<1.43.0)", "mypy-boto3-pcs (>=1.42.0,<1.43.0)", "mypy-boto3-personalize (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-events (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-pi (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-email (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.42.0,<1.43.0)", "mypy-boto3-pipes (>=1.42.0,<1.43.0)", "mypy-boto3-polly (>=1.42.0,<1.43.0)", "mypy-boto3-pricing (>=1.42.0,<1.43.0)", "mypy-boto3-proton (>=1.42.0,<1.43.0)", "mypy-boto3-qapps (>=1.42.0,<1.43.0)", "mypy-boto3-qbusiness (>=1.42.0,<1.43.0)", "mypy-boto3-qconnect (>=1.42.0,<1.43.0)", "mypy-boto3-quicksight (>=1.42.0,<1.43.0)", "mypy-boto3-ram (>=1.42.0,<1.43.0)", "mypy-boto3-rbin (>=1.42.0,<1.43.0)", "mypy-boto3-rds (>=1.42.0,<1.43.0)", "mypy-boto3-rds-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-rekognition (>=1.42.0,<1.43.0)", "mypy-boto3-repostspace (>=1.42.0,<1.43.0)", "mypy-boto3-resiliencehub (>=1.42.0,<1.43.0)", "mypy-boto3-resource-explorer-2 (>=1.42.0,<1.43.0)", "mypy-boto3-resource-groups (>=1.42.0,<1.43.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.42.0,<1.43.0)", "mypy-boto3-rolesanywhere (>=1.42.0,<1.43.0)", "mypy-boto3-route53 (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-cluster (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-control-config (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-readiness (>=1.42.0,<1.43.0)", "mypy-boto3-route53domains (>=1.42.0,<1.43.0)", "mypy-boto3-route53globalresolver (>=1.42.0,<1.43.0)", "mypy-boto3-route53profiles (>=1.42.0,<1.43.0)", "mypy-boto3-route53resolver (>=1.42.0,<1.43.0)", "mypy-boto3-rtbfabric (>=1.42.0,<1.43.0)", "mypy-boto3-rum (>=1.42.0,<1.43.0)", "mypy-boto3-s3 (>=1.42.0,<1.43.0)", "mypy-boto3-s3control (>=1.42.0,<1.43.0)", "mypy-boto3-s3outposts (>=1.42.0,<1.43.0)", "mypy-boto3-s3tables (>=1.42.0,<1.43.0)", "mypy-boto3-s3vectors (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-edge (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-geospatial (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-metrics (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-savingsplans (>=1.42.0,<1.43.0)", "mypy-boto3-scheduler (>=1.42.0,<1.43.0)", "mypy-boto3-schemas (>=1.42.0,<1.43.0)", "mypy-boto3-sdb (>=1.42.0,<1.43.0)", "mypy-boto3-secretsmanager (>=1.42.0,<1.43.0)", "mypy-boto3-security-ir (>=1.42.0,<1.43.0)", "mypy-boto3-securityagent (>=1.42.0,<1.43.0)", "mypy-boto3-securityhub (>=1.42.0,<1.43.0)", "mypy-boto3-securitylake (>=1.42.0,<1.43.0)", "mypy-boto3-serverlessrepo (>=1.42.0,<1.43.0)", "mypy-boto3-service-quotas (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog-appregistry (>=1.42.0,<1.43.0)", "mypy-boto3-servicediscovery (>=1.42.0,<1.43.0)", "mypy-boto3-ses (>=1.42.0,<1.43.0)", "mypy-boto3-sesv2 (>=1.42.0,<1.43.0)", "mypy-boto3-shield (>=1.42.0,<1.43.0)", "mypy-boto3-signer (>=1.42.0,<1.43.0)", "mypy-boto3-signer-data (>=1.42.0,<1.43.0)", "mypy-boto3-signin (>=1.42.0,<1.43.0)", "mypy-boto3-simpledbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-simspaceweaver (>=1.42.0,<1.43.0)", "mypy-boto3-snow-device-management (>=1.42.0,<1.43.0)", "mypy-boto3-snowball (>=1.42.0,<1.43.0)", "mypy-boto3-sns (>=1.42.0,<1.43.0)", "mypy-boto3-socialmessaging (>=1.42.0,<1.43.0)", "mypy-boto3-sqs (>=1.42.0,<1.43.0)", "mypy-boto3-ssm (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-contacts (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-guiconnect (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-incidents (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-quicksetup (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-sap (>=1.42.0,<1.43.0)", "mypy-boto3-sso (>=1.42.0,<1.43.0)", "mypy-boto3-sso-admin (>=1.42.0,<1.43.0)", "mypy-boto3-sso-oidc (>=1.42.0,<1.43.0)", "mypy-boto3-stepfunctions (>=1.42.0,<1.43.0)", "mypy-boto3-storagegateway (>=1.42.0,<1.43.0)", "mypy-boto3-sts (>=1.42.0,<1.43.0)", "mypy-boto3-supplychain (>=1.42.0,<1.43.0)", "mypy-boto3-support (>=1.42.0,<1.43.0)", "mypy-boto3-support-app (>=1.42.0,<1.43.0)", "mypy-boto3-sustainability (>=1.42.0,<1.43.0)", "mypy-boto3-swf (>=1.42.0,<1.43.0)", "mypy-boto3-synthetics (>=1.42.0,<1.43.0)", "mypy-boto3-taxsettings (>=1.42.0,<1.43.0)", "mypy-boto3-textract (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-influxdb (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-query (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-write (>=1.42.0,<1.43.0)", "mypy-boto3-tnb (>=1.42.0,<1.43.0)", "mypy-boto3-transcribe (>=1.42.0,<1.43.0)", "mypy-boto3-transfer (>=1.42.0,<1.43.0)", "mypy-boto3-translate (>=1.42.0,<1.43.0)", "mypy-boto3-trustedadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-uxc (>=1.42.0,<1.43.0)", "mypy-boto3-verifiedpermissions (>=1.42.0,<1.43.0)", "mypy-boto3-voice-id (>=1.42.0,<1.43.0)", "mypy-boto3-vpc-lattice (>=1.42.0,<1.43.0)", "mypy-boto3-waf (>=1.42.0,<1.43.0)", "mypy-boto3-waf-regional (>=1.42.0,<1.43.0)", "mypy-boto3-wafv2 (>=1.42.0,<1.43.0)", "mypy-boto3-wellarchitected (>=1.42.0,<1.43.0)", "mypy-boto3-wickr (>=1.42.0,<1.43.0)", "mypy-boto3-wisdom (>=1.42.0,<1.43.0)", "mypy-boto3-workdocs (>=1.42.0,<1.43.0)", "mypy-boto3-workmail (>=1.42.0,<1.43.0)", "mypy-boto3-workmailmessageflow (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-instances (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-thin-client (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-web (>=1.42.0,<1.43.0)", "mypy-boto3-xray (>=1.42.0,<1.43.0)"] amp = ["mypy-boto3-amp (>=1.42.0,<1.43.0)"] amplify = ["mypy-boto3-amplify (>=1.42.0,<1.43.0)"] amplifybackend = ["mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)"] @@ -532,7 +532,7 @@ bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime ( bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)"] billing = ["mypy-boto3-billing (>=1.42.0,<1.43.0)"] billingconductor = ["mypy-boto3-billingconductor (>=1.42.0,<1.43.0)"] -boto3 = ["boto3 (==1.42.74)"] +boto3 = ["boto3 (==1.42.84)"] braket = ["mypy-boto3-braket (>=1.42.0,<1.43.0)"] budgets = ["mypy-boto3-budgets (>=1.42.0,<1.43.0)"] ce = ["mypy-boto3-ce (>=1.42.0,<1.43.0)"] @@ -599,6 +599,7 @@ dax = ["mypy-boto3-dax (>=1.42.0,<1.43.0)"] deadline = ["mypy-boto3-deadline (>=1.42.0,<1.43.0)"] detective = ["mypy-boto3-detective (>=1.42.0,<1.43.0)"] devicefarm = ["mypy-boto3-devicefarm (>=1.42.0,<1.43.0)"] +devops-agent = ["mypy-boto3-devops-agent (>=1.42.0,<1.43.0)"] devops-guru = ["mypy-boto3-devops-guru (>=1.42.0,<1.43.0)"] directconnect = ["mypy-boto3-directconnect (>=1.42.0,<1.43.0)"] discovery = ["mypy-boto3-discovery (>=1.42.0,<1.43.0)"] @@ -836,6 +837,7 @@ schemas = ["mypy-boto3-schemas (>=1.42.0,<1.43.0)"] sdb = ["mypy-boto3-sdb (>=1.42.0,<1.43.0)"] secretsmanager = ["mypy-boto3-secretsmanager (>=1.42.0,<1.43.0)"] security-ir = ["mypy-boto3-security-ir (>=1.42.0,<1.43.0)"] +securityagent = ["mypy-boto3-securityagent (>=1.42.0,<1.43.0)"] securityhub = ["mypy-boto3-securityhub (>=1.42.0,<1.43.0)"] securitylake = ["mypy-boto3-securitylake (>=1.42.0,<1.43.0)"] serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.42.0,<1.43.0)"] @@ -871,6 +873,7 @@ sts = ["mypy-boto3-sts (>=1.42.0,<1.43.0)"] supplychain = ["mypy-boto3-supplychain (>=1.42.0,<1.43.0)"] support = ["mypy-boto3-support (>=1.42.0,<1.43.0)"] support-app = ["mypy-boto3-support-app (>=1.42.0,<1.43.0)"] +sustainability = ["mypy-boto3-sustainability (>=1.42.0,<1.43.0)"] swf = ["mypy-boto3-swf (>=1.42.0,<1.43.0)"] synthetics = ["mypy-boto3-synthetics (>=1.42.0,<1.43.0)"] taxsettings = ["mypy-boto3-taxsettings (>=1.42.0,<1.43.0)"] @@ -883,6 +886,7 @@ transcribe = ["mypy-boto3-transcribe (>=1.42.0,<1.43.0)"] transfer = ["mypy-boto3-transfer (>=1.42.0,<1.43.0)"] translate = ["mypy-boto3-translate (>=1.42.0,<1.43.0)"] trustedadvisor = ["mypy-boto3-trustedadvisor (>=1.42.0,<1.43.0)"] +uxc = ["mypy-boto3-uxc (>=1.42.0,<1.43.0)"] verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.42.0,<1.43.0)"] voice-id = ["mypy-boto3-voice-id (>=1.42.0,<1.43.0)"] vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.42.0,<1.43.0)"] From e8b0468d05cec938cfd2707554feb3c69ed1968d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:21:50 +0800 Subject: [PATCH 34/84] chore(deps-dev): bump aws-cdk from 2.1115.0 to 2.1117.0 in the aws-cdk group (#8111) 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.1115.0 to 2.1117.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1117.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1117.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 c35a27a65c9..28f81e58656 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.1115.0" + "aws-cdk": "^2.1117.0" } }, "node_modules/aws-cdk": { - "version": "2.1115.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1115.0.tgz", - "integrity": "sha512-PpNNflDt1L2TxpMh2h7cPHnFkDVeY1hwIxuGuvswS08mA0syOT4OmZx8hZYdcLru6NceCsn0x/7uTHpb6Hzo5A==", + "version": "2.1117.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1117.0.tgz", + "integrity": "sha512-2NbSDDw8LTkGv0uhEDffttmNvgyTAWV5EkLkyPUGAGECzBdwCmbgmRxSoUhbzxZ0XEd1eaqbdVTFRWgtsbj31g==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 6cf64a2b8e6..2c97f75843e 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.1115.0" + "aws-cdk": "^2.1117.0" } } From 6728e2d7335f91aa75448a61ce8bcf5505ab0711 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:00:36 +0800 Subject: [PATCH 35/84] chore(deps-dev): bump types-python-dateutil from 2.9.0.20260305 to 2.9.0.20260402 (#8114) chore(deps-dev): bump types-python-dateutil Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.9.0.20260305 to 2.9.0.20260402. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-python-dateutil dependency-version: 2.9.0.20260402 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 414b736b7a0..de4801123c7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4720,14 +4720,14 @@ types-cffi = "*" [[package]] name = "types-python-dateutil" -version = "2.9.0.20260305" +version = "2.9.0.20260402" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_python_dateutil-2.9.0.20260305-py3-none-any.whl", hash = "sha256:a3be9ca444d38cadabd756cfbb29780d8b338ae2a3020e73c266a83cc3025dd7"}, - {file = "types_python_dateutil-2.9.0.20260305.tar.gz", hash = "sha256:389717c9f64d8f769f36d55a01873915b37e97e52ce21928198d210fbd393c8b"}, + {file = "types_python_dateutil-2.9.0.20260402-py3-none-any.whl", hash = "sha256:7827e6a9c93587cc18e766944254d1351a2396262e4abe1510cbbd7601c5e01f"}, + {file = "types_python_dateutil-2.9.0.20260402.tar.gz", hash = "sha256:a980142b9966713acb382c467e35c5cc4208a2f91b10b8d785a0ae6765df6c0b"}, ] [[package]] From b8979e6bc0b63aa8935a968ea318b1a1ebf0feac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:15:59 +0800 Subject: [PATCH 36/84] chore(deps-dev): bump cfn-lint from 1.46.0 to 1.48.1 (#8113) Bumps [cfn-lint](https://github.com/aws-cloudformation/cfn-lint) from 1.46.0 to 1.48.1. - [Release notes](https://github.com/aws-cloudformation/cfn-lint/releases) - [Changelog](https://github.com/aws-cloudformation/cfn-lint/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-cloudformation/cfn-lint/compare/v1.46.0...v1.48.1) --- updated-dependencies: - dependency-name: cfn-lint dependency-version: 1.48.1 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 | 20 ++++++++++---------- pyproject.toml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/poetry.lock b/poetry.lock index de4801123c7..f731300c650 100644 --- a/poetry.lock +++ b/poetry.lock @@ -299,14 +299,14 @@ requests = ">=0.14.0" [[package]] name = "aws-sam-translator" -version = "1.107.0" +version = "1.108.0" description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates" optional = false python-versions = "!=4.0,<=4.0,>=3.8" groups = ["dev"] files = [ - {file = "aws_sam_translator-1.107.0-py3-none-any.whl", hash = "sha256:95b2a03a87fb61d9a9e9e431a18e6221c4780b32792eed4b239e72ef7366d63b"}, - {file = "aws_sam_translator-1.107.0.tar.gz", hash = "sha256:e6462c85309a4cabcc9559edf12f164c67a74a1208feb6350ab8aa1b620c9365"}, + {file = "aws_sam_translator-1.108.0-py3-none-any.whl", hash = "sha256:03130421e641bb57ba7978e7db9e49acb32ecb09a87777dca3c28e44b3ea49db"}, + {file = "aws_sam_translator-1.108.0.tar.gz", hash = "sha256:8a21be119caaa64cf85e01b5e0fde804abe117b36fcce934bc1b74f3ccdc2488"}, ] [package.dependencies] @@ -316,7 +316,7 @@ pydantic = {version = ">=2.12.5,<2.13.0", markers = "python_version >= \"3.9\""} typing_extensions = ">=4.4" [package.extras] -dev = ["black (==24.3.0)", "boto3 (>=1.34.0,<2.0.0)", "boto3-stubs[appconfig,serverlessrepo] (>=1.34.0,<2.0.0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "mypy (>=1.10.1,<1.11.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (>=0.4.5,<0.5.0)", "tenacity (>=9.0,<10.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)"] +dev = ["black (==24.3.0)", "boto3 (>=1.34.0,<2.0.0)", "boto3-stubs[appconfig,serverlessrepo] (>=1.34.0,<2.0.0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "mypy (>=1.10.1,<1.11.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (>=0.4.5,<0.5.0)", "tenacity (>=9.0,<10.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)", "types-requests (>=2.28,<3.0)"] [[package]] name = "aws-xray-sdk" @@ -1134,18 +1134,18 @@ pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} [[package]] name = "cfn-lint" -version = "1.46.0" +version = "1.48.1" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "cfn_lint-1.46.0-py3-none-any.whl", hash = "sha256:1dfca1993af3159411e4a4f79466617ccdca48eddaf424e216297167c500aa3b"}, - {file = "cfn_lint-1.46.0.tar.gz", hash = "sha256:fa7cb76db683109133241baf1e1734b1d61b46d3900ba2a309db8f3d0e5d3994"}, + {file = "cfn_lint-1.48.1-py3-none-any.whl", hash = "sha256:73785acd4fcb71ed68183589f7dcf9e46fd0ad9fb01f704243cb07993490a40e"}, + {file = "cfn_lint-1.48.1.tar.gz", hash = "sha256:1855dce6b97528ff532e3f5a3aa5b659f40e51c338192a0ba82c1af88882b6f7"}, ] [package.dependencies] -aws-sam-translator = ">=1.97.0" +aws-sam-translator = ">=1.108.0" jsonpatch = "*" networkx = ">=2.4,<4" pyyaml = ">5.4" @@ -5182,4 +5182,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "ebcd1323432f7c0dff5d7408a9274675a491b06cc47c9488d041a33f3d39c82d" +content-hash = "b25255bc28d8bd32a551f513c491e2b4aa72491f57c80689fb1be294f583adfa" diff --git a/pyproject.toml b/pyproject.toml index d736d2c5f37..6b512b6001f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -110,7 +110,7 @@ hvac = "^2.3.0" aws-requests-auth = "^0.4.3" urllib3 = ">=1.25.4,!=2.2.0,<3" requests = ">=2.32.0" -cfn-lint = "1.46.0" +cfn-lint = "1.48.1" mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" aws-cdk-aws-appsync-alpha = "^2.59.0a0" From 7af52e460d650357dd8b727b6b45e30c8d17c8e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:46:41 +0800 Subject: [PATCH 37/84] chore(deps-dev): bump testcontainers from 4.14.1 to 4.14.2 (#8116) Bumps [testcontainers](https://github.com/testcontainers/testcontainers-python) from 4.14.1 to 4.14.2. - [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.1...testcontainers-v4.14.2) --- updated-dependencies: - dependency-name: testcontainers dependency-version: 4.14.2 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 | 63 +++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/poetry.lock b/poetry.lock index f731300c650..f5445bb54a2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4509,58 +4509,59 @@ dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] [[package]] name = "testcontainers" -version = "4.14.1" +version = "4.14.2" 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.1-py3-none-any.whl", hash = "sha256:03dfef4797b31c82e7b762a454b6afec61a2a512ad54af47ab41e4fa5415f891"}, - {file = "testcontainers-4.14.1.tar.gz", hash = "sha256:316f1bb178d829c003acd650233e3ff3c59a833a08d8661c074f58a4fbd42a64"}, + {file = "testcontainers-4.14.2-py3-none-any.whl", hash = "sha256:0d0522c3cd8f8d9627cda41f7a6b51b639fa57bdc492923c045117933c668d68"}, + {file = "testcontainers-4.14.2.tar.gz", hash = "sha256:1340ccf16fe3acd9389a6c9e1d9ab21d9fe99a8afdf8165f89c3e69c1967d239"}, ] [package.dependencies] docker = "*" python-dotenv = "*" -redis = {version = ">=7,<8", optional = true, markers = "extra == \"generic\" or extra == \"redis\""} +redis = {version = ">=7", optional = true, markers = "extra == \"redis\""} typing-extensions = "*" urllib3 = "*" wrapt = "*" [package.extras] -arangodb = ["python-arango (>=8,<9)"] -aws = ["boto3 (>=1,<2)", "httpx"] -azurite = ["azure-storage-blob (>=12,<13)"] -chroma = ["chromadb-client (>=1,<2)"] -cosmosdb = ["azure-cosmos (>=4,<5)"] -db2 = ["ibm_db_sa ; platform_machine != \"aarch64\" and platform_machine != \"arm64\"", "sqlalchemy (>=2,<3)"] -generic = ["httpx", "redis (>=7,<8)"] -google = ["google-cloud-datastore (>=2,<3)", "google-cloud-pubsub (>=2,<3)"] -influxdb = ["influxdb (>=5,<6)", "influxdb-client (>=1,<2)"] +arangodb = ["python-arango (>=8)"] +aws = ["boto3 (>=1)", "httpx"] +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)"] +google = ["google-cloud-datastore (>=2)", "google-cloud-pubsub (>=2)"] +influxdb = ["influxdb (>=5)", "influxdb-client (>=1)"] k3s = ["kubernetes", "pyyaml (>=6.0.3)"] -keycloak = ["python-keycloak (>=6,<7) ; python_version < \"4.0\""] -localstack = ["boto3 (>=1,<2)"] +keycloak = ["python-keycloak (>=6) ; python_version < \"4.0\""] +localstack = ["boto3 (>=1)"] mailpit = ["cryptography"] -minio = ["minio (>=7,<8)"] -mongodb = ["pymongo (>=4,<5)"] -mssql = ["pymssql (>=2,<3)", "sqlalchemy (>=2,<3)"] -mysql = ["pymysql[rsa] (>=1,<2)", "sqlalchemy (>=2,<3)"] -nats = ["nats-py (>=2,<3)"] -neo4j = ["neo4j (>=6,<7)"] +minio = ["minio (>=7)"] +mongodb = ["pymongo (>=4)"] +mssql = ["pymssql (>=2)", "sqlalchemy (>=2)"] +mysql = ["pymysql[rsa] (>=1)", "sqlalchemy (>=2)"] +nats = ["nats-py (>=2)"] +neo4j = ["neo4j (>=6)"] openfga = ["openfga-sdk"] -opensearch = ["opensearch-py (>=3,<4) ; python_version < \"4.0\""] -oracle = ["oracledb (>=3,<4)", "sqlalchemy (>=2,<3)"] -oracle-free = ["oracledb (>=3,<4)", "sqlalchemy (>=2,<3)"] -qdrant = ["qdrant-client (>=1,<2)"] -rabbitmq = ["pika (>=1,<2)"] -redis = ["redis (>=7,<8)"] -registry = ["bcrypt (>=5,<6)"] -scylla = ["cassandra-driver (>=3,<4)"] -selenium = ["selenium (>=4,<5)"] +opensearch = ["opensearch-py (>=3) ; python_version < \"4.0\""] +oracle = ["oracledb (>=3)", "sqlalchemy (>=2)"] +oracle-free = ["oracledb (>=3)", "sqlalchemy (>=2)"] +qdrant = ["qdrant-client (>=1)"] +rabbitmq = ["pika (>=1)"] +redis = ["redis (>=7)"] +registry = ["bcrypt (>=5)"] +scylla = ["cassandra-driver (>=3)"] +selenium = ["selenium (>=4)"] sftp = ["cryptography"] test-module-import = ["httpx"] trino = ["trino"] -weaviate = ["weaviate-client (>=4,<5)"] +weaviate = ["weaviate-client (>=4)"] [[package]] name = "tomli" From c47ab63b7544ffee31944a2f6b84e576263ac9ee Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 7 Apr 2026 20:45:54 +0800 Subject: [PATCH 38/84] refactor(event_handler): refactoring params to reduce code (#8124) chore: refactoring params --- .../event_handler/openapi/params.py | 242 ------------------ 1 file changed, 242 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/params.py b/aws_lambda_powertools/event_handler/openapi/params.py index 3da928ca236..0f13e1e1990 100644 --- a/aws_lambda_powertools/event_handler/openapi/params.py +++ b/aws_lambda_powertools/event_handler/openapi/params.py @@ -286,64 +286,6 @@ def __init__( json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): - """ - Constructs a new Path param. - - Parameters - ---------- - default: Any - The default value of the parameter - default_factory: Callable[[], Any], optional - Callable that will be called when a default value is needed for this field - annotation: Any, optional - The type annotation of the parameter - alias: str, optional - The public name of the field - alias_priority: int, optional - Priority of the alias. This affects whether an alias generator is used - validation_alias: str | AliasPath | AliasChoices | None, optional - Alias to be used for validation only - serialization_alias: str | AliasPath | AliasChoices | None, optional - Alias to be used for serialization only - title: str, optional - The title of the parameter - description: str, optional - The description of the parameter - gt: float, optional - Only applies to numbers, required the field to be "greater than" - ge: float, optional - Only applies to numbers, required the field to be "greater than or equal" - lt: float, optional - Only applies to numbers, required the field to be "less than" - le: float, optional - Only applies to numbers, required the field to be "less than or equal" - min_length: int, optional - Only applies to strings, required the field to have a minimum length - max_length: int, optional - Only applies to strings, required the field to have a maximum length - pattern: str, optional - Only applies to strings, requires the field match against a regular expression pattern string - discriminator: str, optional - Parameter field name for discriminating the type in a tagged union - strict: bool, optional - Enables Pydantic's strict mode for the field - multiple_of: float, optional - Only applies to numbers, requires the field to be a multiple of the given value - allow_inf_nan: bool, optional - Only applies to numbers, requires the field to allow infinity and NaN values - max_digits: int, optional - Only applies to Decimals, requires the field to have a maxmium number of digits within the decimal. - decimal_places: int, optional - Only applies to Decimals, requires the field to have at most a number of decimal places - examples: list[Any], optional - A list of examples for the parameter - deprecated: bool, optional - If `True`, the parameter will be marked as deprecated - include_in_schema: bool, optional - If `False`, the parameter will be excluded from the generated OpenAPI schema - json_schema_extra: dict[str, Any], optional - Extra values to include in the generated OpenAPI schema - """ if default is not ...: raise AssertionError("Path parameters cannot have a default value") @@ -418,64 +360,6 @@ def __init__( json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): - """ - Constructs a new Query param. - - Parameters - ---------- - default: Any - The default value of the parameter - default_factory: Callable[[], Any], optional - Callable that will be called when a default value is needed for this field - annotation: Any, optional - The type annotation of the parameter - alias: str, optional - The public name of the field - alias_priority: int, optional - Priority of the alias. This affects whether an alias generator is used - validation_alias: str | AliasPath | AliasChoices | None, optional - Alias to be used for validation only - serialization_alias: str | AliasPath | AliasChoices | None, optional - Alias to be used for serialization only - title: str, optional - The title of the parameter - description: str, optional - The description of the parameter - gt: float, optional - Only applies to numbers, required the field to be "greater than" - ge: float, optional - Only applies to numbers, required the field to be "greater than or equal" - lt: float, optional - Only applies to numbers, required the field to be "less than" - le: float, optional - Only applies to numbers, required the field to be "less than or equal" - min_length: int, optional - Only applies to strings, required the field to have a minimum length - max_length: int, optional - Only applies to strings, required the field to have a maximum length - pattern: str, optional - Only applies to strings, requires the field match against a regular expression pattern string - discriminator: str, optional - Parameter field name for discriminating the type in a tagged union - strict: bool, optional - Enables Pydantic's strict mode for the field - multiple_of: float, optional - Only applies to numbers, requires the field to be a multiple of the given value - allow_inf_nan: bool, optional - Only applies to numbers, requires the field to allow infinity and NaN values - max_digits: int, optional - Only applies to Decimals, requires the field to have a maxmium number of digits within the decimal. - decimal_places: int, optional - Only applies to Decimals, requires the field to have at most a number of decimal places - examples: list[Any], optional - A list of examples for the parameter - deprecated: bool, optional - If `True`, the parameter will be marked as deprecated - include_in_schema: bool, optional - If `False`, the parameter will be excluded from the generated OpenAPI schema - json_schema_extra: dict[str, Any], optional - Extra values to include in the generated OpenAPI schema - """ super().__init__( default=default, default_factory=default_factory, @@ -550,67 +434,6 @@ def __init__( json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): - """ - Constructs a new Query param. - - Parameters - ---------- - default: Any - The default value of the parameter - default_factory: Callable[[], Any], optional - Callable that will be called when a default value is needed for this field - annotation: Any, optional - The type annotation of the parameter - alias: str, optional - The public name of the field - alias_priority: int, optional - Priority of the alias. This affects whether an alias generator is used - validation_alias: str | AliasPath | AliasChoices | None, optional - Alias to be used for validation only - serialization_alias: str | AliasPath | AliasChoices | None, optional - Alias to be used for serialization only - convert_underscores: bool - If true convert "_" to "-" - See RFC: https://www.rfc-editor.org/rfc/rfc9110.html#name-field-name-registry - title: str, optional - The title of the parameter - description: str, optional - The description of the parameter - gt: float, optional - Only applies to numbers, required the field to be "greater than" - ge: float, optional - Only applies to numbers, required the field to be "greater than or equal" - lt: float, optional - Only applies to numbers, required the field to be "less than" - le: float, optional - Only applies to numbers, required the field to be "less than or equal" - min_length: int, optional - Only applies to strings, required the field to have a minimum length - max_length: int, optional - Only applies to strings, required the field to have a maximum length - pattern: str, optional - Only applies to strings, requires the field match against a regular expression pattern string - discriminator: str, optional - Parameter field name for discriminating the type in a tagged union - strict: bool, optional - Enables Pydantic's strict mode for the field - multiple_of: float, optional - Only applies to numbers, requires the field to be a multiple of the given value - allow_inf_nan: bool, optional - Only applies to numbers, requires the field to allow infinity and NaN values - max_digits: int, optional - Only applies to Decimals, requires the field to have a maxmium number of digits within the decimal. - decimal_places: int, optional - Only applies to Decimals, requires the field to have at most a number of decimal places - examples: list[Any], optional - A list of examples for the parameter - deprecated: bool, optional - If `True`, the parameter will be marked as deprecated - include_in_schema: bool, optional - If `False`, the parameter will be excluded from the generated OpenAPI schema - json_schema_extra: dict[str, Any], optional - Extra values to include in the generated OpenAPI schema - """ self.convert_underscores = convert_underscores self._alias = alias @@ -665,71 +488,6 @@ class Cookie(Param): # type: ignore[misc] in_ = ParamTypes.cookie - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - alias: str | None = None, - alias_priority: int | None = _Unset, - # MAINTENANCE: update when deprecating Pydantic v1, import these types - # str | AliasPath | AliasChoices | None - validation_alias: str | None = _Unset, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - openapi_examples: dict[str, Example] | None = None, - deprecated: bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - super().__init__( - default=default, - default_factory=default_factory, - annotation=annotation, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - deprecated=deprecated, - examples=examples, - openapi_examples=openapi_examples, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - class Body(FieldInfo): # type: ignore[misc] """ From baec69b8cebb9634018813c76cd98e306cab1466 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 7 Apr 2026 21:07:02 +0800 Subject: [PATCH 39/84] refactor(event_handler): refactoring proxy events (#8125) * chore: refactoring proxy events * chore: refactoring proxy events --- .../event_handler/api_gateway.py | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index ad1e14d3122..db341240132 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -113,6 +113,17 @@ class ProxyEventType(Enum): LambdaFunctionUrlEvent = "LambdaFunctionUrlEvent" +_PROXY_EVENT_MAP: dict[Enum, tuple[type[BaseProxyEvent], str]] = { + ProxyEventType.APIGatewayProxyEvent: (APIGatewayProxyEvent, "API Gateway REST API"), + ProxyEventType.APIGatewayProxyEventV2: (APIGatewayProxyEventV2, "API Gateway HTTP API"), + ProxyEventType.BedrockAgentEvent: (BedrockAgentEvent, "Bedrock Agent"), + ProxyEventType.LambdaFunctionUrlEvent: (LambdaFunctionUrlEvent, "Lambda Function URL"), + ProxyEventType.VPCLatticeEvent: (VPCLatticeEvent, "VPC Lattice"), + ProxyEventType.VPCLatticeEventV2: (VPCLatticeEventV2, "VPC LatticeV2"), + ProxyEventType.ALBEvent: (ALBEvent, "ALB"), +} + + class CORSConfig: """CORS Config @@ -2498,28 +2509,11 @@ def _compile_regex(rule: str, base_regex: str = _ROUTE_REGEX): rule_regex: str = re.sub(_DYNAMIC_ROUTE_PATTERN, _NAMED_GROUP_BOUNDARY_PATTERN, rule) return re.compile(base_regex.format(rule_regex)) - def _to_proxy_event(self, event: dict) -> BaseProxyEvent: # noqa: PLR0911 # ignore many returns + def _to_proxy_event(self, event: dict) -> BaseProxyEvent: """Convert the event dict to the corresponding data class""" - if self._proxy_type == ProxyEventType.APIGatewayProxyEvent: - logger.debug("Converting event to API Gateway REST API contract") - return APIGatewayProxyEvent(event, self._json_body_deserializer) - if self._proxy_type == ProxyEventType.APIGatewayProxyEventV2: - logger.debug("Converting event to API Gateway HTTP API contract") - return APIGatewayProxyEventV2(event, self._json_body_deserializer) - if self._proxy_type == ProxyEventType.BedrockAgentEvent: - logger.debug("Converting event to Bedrock Agent contract") - return BedrockAgentEvent(event, self._json_body_deserializer) - if self._proxy_type == ProxyEventType.LambdaFunctionUrlEvent: - logger.debug("Converting event to Lambda Function URL contract") - return LambdaFunctionUrlEvent(event, self._json_body_deserializer) - if self._proxy_type == ProxyEventType.VPCLatticeEvent: - logger.debug("Converting event to VPC Lattice contract") - return VPCLatticeEvent(event, self._json_body_deserializer) - if self._proxy_type == ProxyEventType.VPCLatticeEventV2: - logger.debug("Converting event to VPC LatticeV2 contract") - return VPCLatticeEventV2(event, self._json_body_deserializer) - logger.debug("Converting event to ALB contract") - return ALBEvent(event, self._json_body_deserializer) + event_class, label = _PROXY_EVENT_MAP.get(self._proxy_type, (ALBEvent, "ALB")) + logger.debug("Converting event to %s contract", label) + return event_class(event, self._json_body_deserializer) def _resolve(self) -> ResponseBuilder: """Resolves the response or return the not found response""" From 8b42829d1bef3c9799bd8d71f19ecbbd13b94612 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 7 Apr 2026 21:54:32 +0800 Subject: [PATCH 40/84] refactor(event_handler): refactoring encoder file (#8126) chore: refactoring encoder file --- .../event_handler/openapi/encoders.py | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/encoders.py b/aws_lambda_powertools/event_handler/openapi/encoders.py index 59ce47ebc1d..d1b8861bdde 100644 --- a/aws_lambda_powertools/event_handler/openapi/encoders.py +++ b/aws_lambda_powertools/event_handler/openapi/encoders.py @@ -5,7 +5,7 @@ from collections import defaultdict, deque from decimal import Decimal from enum import Enum -from pathlib import Path, PurePath +from pathlib import PurePath from re import Pattern from types import GeneratorType from typing import TYPE_CHECKING, Any @@ -103,17 +103,14 @@ def jsonable_encoder( # noqa: PLR0911 custom_serializer=custom_serializer, ) - # Enums - if isinstance(obj, Enum): - return obj.value + # Simple type dispatch (exact type match, then isinstance for subclasses) + encoder = ENCODERS_BY_TYPE.get(type(obj)) + if encoder is not None: + return encoder(obj) - # Paths - if isinstance(obj, PurePath): - return str(obj) - - # Scalars - if isinstance(obj, (str, int, float, type(None))): - return obj + for encoder_fn, classes_tuple in _encoders_by_class_tuples.items(): + if isinstance(obj, classes_tuple): + return encoder_fn(obj) # Dictionaries if isinstance(obj, dict): @@ -140,14 +137,6 @@ def jsonable_encoder( # noqa: PLR0911 custom_serializer=custom_serializer, ) - # Other types - if type(obj) in ENCODERS_BY_TYPE: - return ENCODERS_BY_TYPE[type(obj)](obj) - - for encoder, classes_tuple in encoders_by_class_tuples.items(): - if isinstance(obj, classes_tuple): - return encoder(obj) - # Use custom serializer if present if custom_serializer: return custom_serializer(obj) @@ -346,6 +335,11 @@ def decimal_encoder(dec_value: Decimal) -> int | float: # Encoders for types that are not JSON serializable ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = { + bool: lambda o: o, + int: lambda o: o, + float: lambda o: o, + str: lambda o: o, + type(None): lambda o: o, bytes: lambda o: o.decode(), datetime.date: iso_format, datetime.datetime: iso_format, @@ -353,14 +347,10 @@ def decimal_encoder(dec_value: Decimal) -> int | float: datetime.timedelta: lambda td: td.total_seconds(), Decimal: decimal_encoder, Enum: lambda o: o.value, - frozenset: list, - deque: list, - GeneratorType: list, - Path: str, + PurePath: str, Pattern: lambda o: o.pattern, SecretBytes: str, SecretStr: str, - set: list, UUID: str, } @@ -376,4 +366,4 @@ def generate_encoders_by_class_tuples( # Mapping of encoders to a tuple of classes that they can encode -encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE) +_encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE) From 12aeb50f7c8be00cb9272c58fd6d9256524a5f05 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 7 Apr 2026 22:27:27 +0800 Subject: [PATCH 41/84] refactor(event_handlers): remove unnecessary init methods (#8127) refactor: remove init methods --- .../event_handler/api_gateway.py | 66 ++++--------------- .../event_handler/lambda_function_url.py | 28 +------- .../event_handler/vpc_lattice.py | 52 +-------------- 3 files changed, 18 insertions(+), 128 deletions(-) diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index db341240132..27357b5ddab 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -1460,9 +1460,11 @@ def lambda_handler(event, context): ``` """ + _proxy_event_type: Enum = ProxyEventType.APIGatewayProxyEvent + def __init__( self, - proxy_type: Enum = ProxyEventType.APIGatewayProxyEvent, + proxy_type: Enum | None = None, cors: CORSConfig | None = None, debug: bool | None = None, serializer: Callable[[dict], str] | None = None, @@ -1495,7 +1497,7 @@ def __init__( function to deserialize `str`, `bytes`, `bytearray` containing a JSON document to a Python `dict`, by default json.loads when integrating with EventSource data class """ - self._proxy_type = proxy_type + self._proxy_type = proxy_type or self._proxy_event_type self._dynamic_routes: list[Route] = [] self._static_routes: list[Route] = [] self._route_keys: list[str] = [] @@ -2935,28 +2937,7 @@ class APIGatewayRestResolver(ApiGatewayResolver): """Amazon API Gateway REST and HTTP API v1 payload resolver""" current_event: APIGatewayProxyEvent - - def __init__( - self, - cors: CORSConfig | None = None, - debug: bool | None = None, - serializer: Callable[[dict], str] | None = None, - strip_prefixes: list[str | Pattern] | None = None, - enable_validation: bool = False, - response_validation_error_http_code: HTTPStatus | int | None = None, - json_body_deserializer: Callable[[str], dict] | None = None, - ): - """Amazon API Gateway REST and HTTP API v1 payload resolver""" - super().__init__( - ProxyEventType.APIGatewayProxyEvent, - cors, - debug, - serializer, - strip_prefixes, - enable_validation, - response_validation_error_http_code, - json_body_deserializer=json_body_deserializer, - ) + _proxy_event_type = ProxyEventType.APIGatewayProxyEvent def _get_base_path(self) -> str: # 3 different scenarios: @@ -3025,28 +3006,7 @@ class APIGatewayHttpResolver(ApiGatewayResolver): """Amazon API Gateway HTTP API v2 payload resolver""" current_event: APIGatewayProxyEventV2 - - def __init__( - self, - cors: CORSConfig | None = None, - debug: bool | None = None, - serializer: Callable[[dict], str] | None = None, - strip_prefixes: list[str | Pattern] | None = None, - enable_validation: bool = False, - response_validation_error_http_code: HTTPStatus | int | None = None, - json_body_deserializer: Callable[[str], dict] | None = None, - ): - """Amazon API Gateway HTTP API v2 payload resolver""" - super().__init__( - ProxyEventType.APIGatewayProxyEventV2, - cors, - debug, - serializer, - strip_prefixes, - enable_validation, - response_validation_error_http_code, - json_body_deserializer=json_body_deserializer, - ) + _proxy_event_type = ProxyEventType.APIGatewayProxyEventV2 def _get_base_path(self) -> str: # 3 different scenarios: @@ -3066,6 +3026,7 @@ class ALBResolver(ApiGatewayResolver): """Amazon Application Load Balancer (ALB) resolver""" current_event: ALBEvent + _proxy_event_type = ProxyEventType.ALBEvent def __init__( self, @@ -3105,13 +3066,12 @@ def __init__( Enables URL-decoding of query parameters (both keys and values), by default False. """ super().__init__( - ProxyEventType.ALBEvent, - cors, - debug, - serializer, - strip_prefixes, - enable_validation, - response_validation_error_http_code, + cors=cors, + debug=debug, + serializer=serializer, + strip_prefixes=strip_prefixes, + enable_validation=enable_validation, + response_validation_error_http_code=response_validation_error_http_code, json_body_deserializer=json_body_deserializer, ) self.decode_query_parameters = decode_query_parameters diff --git a/aws_lambda_powertools/event_handler/lambda_function_url.py b/aws_lambda_powertools/event_handler/lambda_function_url.py index 279899b645e..cbd92a00b6e 100644 --- a/aws_lambda_powertools/event_handler/lambda_function_url.py +++ b/aws_lambda_powertools/event_handler/lambda_function_url.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Pattern +from typing import TYPE_CHECKING from aws_lambda_powertools.event_handler.api_gateway import ( ApiGatewayResolver, @@ -8,10 +8,6 @@ ) if TYPE_CHECKING: - from collections.abc import Callable - from http import HTTPStatus - - from aws_lambda_powertools.event_handler import CORSConfig from aws_lambda_powertools.utilities.data_classes import LambdaFunctionUrlEvent @@ -52,27 +48,7 @@ def lambda_handler(event, context): """ current_event: LambdaFunctionUrlEvent - - def __init__( - self, - cors: CORSConfig | None = None, - debug: bool | None = None, - serializer: Callable[[dict], str] | None = None, - strip_prefixes: list[str | Pattern] | None = None, - enable_validation: bool = False, - response_validation_error_http_code: HTTPStatus | int | None = None, - json_body_deserializer: Callable[[str], dict] | None = None, - ): - super().__init__( - ProxyEventType.LambdaFunctionUrlEvent, - cors, - debug, - serializer, - strip_prefixes, - enable_validation, - response_validation_error_http_code, - json_body_deserializer=json_body_deserializer, - ) + _proxy_event_type = ProxyEventType.LambdaFunctionUrlEvent def _get_base_path(self) -> str: stage = self.current_event.request_context.stage diff --git a/aws_lambda_powertools/event_handler/vpc_lattice.py b/aws_lambda_powertools/event_handler/vpc_lattice.py index 40eafc01d01..9c3efc03792 100644 --- a/aws_lambda_powertools/event_handler/vpc_lattice.py +++ b/aws_lambda_powertools/event_handler/vpc_lattice.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Pattern +from typing import TYPE_CHECKING from aws_lambda_powertools.event_handler.api_gateway import ( ApiGatewayResolver, @@ -8,10 +8,6 @@ ) if TYPE_CHECKING: - from collections.abc import Callable - from http import HTTPStatus - - from aws_lambda_powertools.event_handler import CORSConfig from aws_lambda_powertools.utilities.data_classes import VPCLatticeEvent, VPCLatticeEventV2 @@ -48,28 +44,7 @@ def lambda_handler(event, context): """ current_event: VPCLatticeEvent - - def __init__( - self, - cors: CORSConfig | None = None, - debug: bool | None = None, - serializer: Callable[[dict], str] | None = None, - strip_prefixes: list[str | Pattern] | None = None, - enable_validation: bool = False, - response_validation_error_http_code: HTTPStatus | int | None = None, - json_body_deserializer: Callable[[str], dict] | None = None, - ): - """Amazon VPC Lattice resolver""" - super().__init__( - ProxyEventType.VPCLatticeEvent, - cors, - debug, - serializer, - strip_prefixes, - enable_validation, - response_validation_error_http_code, - json_body_deserializer=json_body_deserializer, - ) + _proxy_event_type = ProxyEventType.VPCLatticeEvent def _get_base_path(self) -> str: return "" @@ -108,28 +83,7 @@ def lambda_handler(event, context): """ current_event: VPCLatticeEventV2 - - def __init__( - self, - cors: CORSConfig | None = None, - debug: bool | None = None, - serializer: Callable[[dict], str] | None = None, - strip_prefixes: list[str | Pattern] | None = None, - enable_validation: bool = False, - response_validation_error_http_code: HTTPStatus | int | None = None, - json_body_deserializer: Callable[[str], dict] | None = None, - ): - """Amazon VPC Lattice resolver""" - super().__init__( - ProxyEventType.VPCLatticeEventV2, - cors, - debug, - serializer, - strip_prefixes, - enable_validation, - response_validation_error_http_code, - json_body_deserializer=json_body_deserializer, - ) + _proxy_event_type = ProxyEventType.VPCLatticeEventV2 def _get_base_path(self) -> str: return "" From f1d07ab224eb6032ebdd857aa90d37dabc4b85ea Mon Sep 17 00:00:00 2001 From: Justin <19935354+JustinBerger@users.noreply.github.com> Date: Wed, 8 Apr 2026 08:07:09 -0700 Subject: [PATCH 42/84] fix(event_handler): read swagger files with UTF-8 encoding (#8131) fix: read swagger files with UTF-8 encoding --- aws_lambda_powertools/event_handler/api_gateway.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 27357b5ddab..4a9fc142cf0 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -2224,8 +2224,12 @@ def swagger_handler(): # We now inject CSS and JS into the SwaggerUI file swagger_js = Path.open( Path(__file__).parent / "openapi" / "swagger_ui" / "swagger-ui-bundle.min.js", + encoding="utf-8", + ).read() + swagger_css = Path.open( + Path(__file__).parent / "openapi" / "swagger_ui" / "swagger-ui.min.css", + encoding="utf-8", ).read() - swagger_css = Path.open(Path(__file__).parent / "openapi" / "swagger_ui" / "swagger-ui.min.css").read() openapi_servers = servers or [Server(url=(base_path or "/"))] From 4cb9997e2c6615908d93cf5bc368997f3fba81e0 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 8 Apr 2026 23:16:26 +0800 Subject: [PATCH 43/84] feat(event_handler): add Dependency injection with Depends() (#8128) * feat: add Dependency injection feature * Merging from develop * feat: add Dependency injection feature * feat: add Dependency injection feature * feat: add Dependency injection feature * feat: add Dependency injection feature --- .../event_handler/__init__.py | 3 + .../event_handler/api_gateway.py | 24 + .../event_handler/depends.py | 222 ++++++++++ .../event_handler/openapi/dependant.py | 17 + .../event_handler/openapi/params.py | 17 +- docs/core/event_handler/api_gateway.md | 42 ++ .../src/dependency_injection.py | 32 ++ .../src/dependency_injection_nested.py | 38 ++ .../src/dependency_injection_testing.py | 26 ++ .../src/dependency_injection_with_request.py | 25 ++ .../event_handler/_pydantic/test_depends.py | 216 +++++++++ .../required_dependencies/test_depends.py | 416 ++++++++++++++++++ 12 files changed, 1077 insertions(+), 1 deletion(-) create mode 100644 aws_lambda_powertools/event_handler/depends.py create mode 100644 examples/event_handler_rest/src/dependency_injection.py create mode 100644 examples/event_handler_rest/src/dependency_injection_nested.py create mode 100644 examples/event_handler_rest/src/dependency_injection_testing.py create mode 100644 examples/event_handler_rest/src/dependency_injection_with_request.py create mode 100644 tests/functional/event_handler/_pydantic/test_depends.py create mode 100644 tests/functional/event_handler/required_dependencies/test_depends.py diff --git a/aws_lambda_powertools/event_handler/__init__.py b/aws_lambda_powertools/event_handler/__init__.py index 582abd017c0..98433b2e29b 100644 --- a/aws_lambda_powertools/event_handler/__init__.py +++ b/aws_lambda_powertools/event_handler/__init__.py @@ -16,6 +16,7 @@ BedrockAgentFunctionResolver, BedrockFunctionResponse, ) +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.lambda_function_url import ( @@ -36,6 +37,8 @@ "BedrockResponse", "BedrockFunctionResponse", "CORSConfig", + "Depends", + "DependencyResolutionError", "HttpResolverLocal", "LambdaFunctionUrlResolver", "Request", diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 4a9fc142cf0..7ffaa884761 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -472,6 +472,9 @@ def __init__( self.custom_response_validation_http_code = custom_response_validation_http_code + # Cache whether this route's handler declares Depends() parameters + self._has_dependencies: bool | None = None + # Caches the name of any Request-typed parameter in the handler. # Avoids re-scanning the signature on every invocation. self.request_param_name: str | None = None @@ -613,6 +616,15 @@ def dependant(self) -> Dependant: return self._dependant + @property + def has_dependencies(self) -> bool: + """Check if handler declares Depends() parameters without triggering full dependant computation.""" + if self._has_dependencies is None: + from aws_lambda_powertools.event_handler.depends import _has_depends + + self._has_dependencies = _has_depends(self.func) + return self._has_dependencies + @property def body_field(self) -> ModelField | None: if self._body_field is None: @@ -1428,6 +1440,17 @@ def _registered_api_adapter( if route.request_param_name: route_args = {**route_args, route.request_param_name: app.request} + # Resolve Depends() parameters + if route.has_dependencies: + from aws_lambda_powertools.event_handler.depends import build_dependency_tree, solve_dependencies + + dep_values = solve_dependencies( + dependant=build_dependency_tree(route.func), + request=app.request, + dependency_overrides=app.dependency_overrides or None, + ) + route_args.update(dep_values) + return app._to_response(next_middleware(**route_args)) @@ -1497,6 +1520,7 @@ def __init__( function to deserialize `str`, `bytes`, `bytearray` containing a JSON document to a Python `dict`, by default json.loads when integrating with EventSource data class """ + self.dependency_overrides: dict[Callable, Callable] = {} self._proxy_type = proxy_type or self._proxy_event_type self._dynamic_routes: list[Route] = [] self._static_routes: list[Route] = [] diff --git a/aws_lambda_powertools/event_handler/depends.py b/aws_lambda_powertools/event_handler/depends.py new file mode 100644 index 00000000000..f05167c63d9 --- /dev/null +++ b/aws_lambda_powertools/event_handler/depends.py @@ -0,0 +1,222 @@ +"""Lightweight dependency injection primitives — no pydantic import.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Annotated, Any, get_args, get_origin, get_type_hints + +if TYPE_CHECKING: + from collections.abc import Callable + + from aws_lambda_powertools.event_handler.openapi.params import Dependant + from aws_lambda_powertools.event_handler.request import Request + + +class DependencyResolutionError(Exception): + """Raised when a dependency cannot be resolved.""" + + +class Depends: + """ + Declares a dependency for a route handler parameter. + + Dependencies are resolved automatically before the handler is called. The return value + of the dependency callable is injected as the parameter value. + + Parameters + ---------- + dependency: Callable[..., Any] + A callable whose return value will be injected into the handler parameter. + The callable can itself declare ``Depends()`` parameters to form a dependency tree. + use_cache: bool + If ``True`` (default), the dependency result is cached per invocation so that + the same dependency used multiple times is only called once. + + Examples + -------- + + ```python + from typing import Annotated + + from aws_lambda_powertools.event_handler import APIGatewayHttpResolver, Depends + + app = APIGatewayHttpResolver() + + def get_tenant() -> str: + return "default-tenant" + + @app.get("/orders") + def list_orders(tenant_id: Annotated[str, Depends(get_tenant)]): + return {"tenant": tenant_id} + ``` + """ + + def __init__(self, dependency: Callable[..., Any], *, use_cache: bool = True) -> None: + if not callable(dependency): + raise DependencyResolutionError( + f"Depends() requires a callable, got {type(dependency).__name__}: {dependency!r}", + ) + self.dependency = dependency + self.use_cache = use_cache + + +class _DependencyNode: + """Lightweight node in a dependency tree — used by ``build_dependency_tree``.""" + + def __init__(self, *, param_name: str, depends: Depends, sub_tree: DependencyTree) -> None: + self.param_name = param_name + self.depends = depends + self.dependant = sub_tree + + +class DependencyTree: + """Lightweight dependency tree — no pydantic required. + + This mirrors the shape that ``solve_dependencies`` expects (a ``.dependencies`` + attribute containing nodes with ``.param_name``, ``.depends``, and ``.dependant``), + but can be built without importing pydantic. + """ + + def __init__(self, *, dependencies: list[_DependencyNode] | None = None) -> None: + self.dependencies: list[_DependencyNode] = dependencies or [] + + +class DependencyParam: + """Holds a dependency's parameter name and its resolved Dependant sub-tree (OpenAPI path).""" + + def __init__(self, *, param_name: str, depends: Depends, dependant: Dependant) -> None: + self.param_name = param_name + self.depends = depends + self.dependant = dependant + + +def _get_depends_from_annotation(annotation: Any) -> Depends | None: + """Extract a Depends instance from an Annotated[Type, Depends(...)] annotation.""" + if get_origin(annotation) is Annotated: + for arg in get_args(annotation)[1:]: + if isinstance(arg, Depends): + return arg + return None + + +def _has_depends(func: Callable[..., Any]) -> bool: + """Check if a callable has any Depends() parameters, without importing pydantic.""" + try: + hints = get_type_hints(func, include_extras=True) + except Exception: + return False + + for annotation in hints.values(): + if _get_depends_from_annotation(annotation) is not None: + return True + return False + + +def build_dependency_tree(func: Callable[..., Any]) -> DependencyTree: + """Build a lightweight dependency tree from a callable's signature. + + This inspects the function parameters for ``Annotated[Type, Depends(...)]`` + annotations and recursively builds the tree — all without importing pydantic. + """ + try: + hints = get_type_hints(func, include_extras=True) + except Exception: + return DependencyTree() + + dependencies: list[_DependencyNode] = [] + + for param_name, annotation in hints.items(): + if param_name == "return": + continue + + depends_instance = _get_depends_from_annotation(annotation) + if depends_instance is not None: + sub_tree = build_dependency_tree(depends_instance.dependency) + dependencies.append( + _DependencyNode( + param_name=param_name, + depends=depends_instance, + sub_tree=sub_tree, + ), + ) + + return DependencyTree(dependencies=dependencies) + + +def solve_dependencies( + *, + dependant: Dependant | DependencyTree, + request: Request | None = None, + dependency_overrides: dict[Callable[..., Any], Callable[..., Any]] | None = None, + dependency_cache: dict[Callable[..., Any], Any] | None = None, +) -> dict[str, Any]: + """ + Recursively resolve all ``Depends()`` parameters for a given dependant. + + Parameters + ---------- + dependant: Dependant + The dependant model containing dependency declarations + request: Request, optional + The current request object, injected into dependencies that declare a Request parameter + dependency_overrides: dict, optional + Mapping of original dependency callable to override callable (for testing) + dependency_cache: dict, optional + Per-invocation cache of resolved dependency values + + Returns + ------- + dict[str, Any] + Mapping of parameter name to resolved dependency value + """ + from aws_lambda_powertools.event_handler.request import Request as RequestClass + + if dependency_cache is None: + dependency_cache = {} + + values: dict[str, Any] = {} + + for dep in dependant.dependencies: + use_fn = dep.depends.dependency + + # Apply overrides (for testing) + if dependency_overrides and use_fn in dependency_overrides: + use_fn = dependency_overrides[use_fn] + + # Check cache + if dep.depends.use_cache and use_fn in dependency_cache: + values[dep.param_name] = dependency_cache[use_fn] + continue + + # Recursively resolve sub-dependencies + sub_values = solve_dependencies( + dependant=dep.dependant, + request=request, + dependency_overrides=dependency_overrides, + dependency_cache=dependency_cache, + ) + + # Inject Request if the dependency declares it + if request is not None: + try: + hints = get_type_hints(use_fn) + except Exception: # pragma: no cover - defensive for broken annotations + hints = {} + for param_name, annotation in hints.items(): + if annotation is RequestClass: + sub_values[param_name] = request + + try: + solved = use_fn(**sub_values) + except Exception as exc: + dep_name = getattr(use_fn, "__name__", repr(use_fn)) + raise DependencyResolutionError( + f"Failed to resolve dependency '{dep_name}' for parameter '{dep.param_name}': {exc}", + ) from exc + + # Cache result + if dep.depends.use_cache: + dependency_cache[use_fn] = solved + + values[dep.param_name] = solved + + return values diff --git a/aws_lambda_powertools/event_handler/openapi/dependant.py b/aws_lambda_powertools/event_handler/openapi/dependant.py index ec8414a7dd2..1e7f4327602 100644 --- a/aws_lambda_powertools/event_handler/openapi/dependant.py +++ b/aws_lambda_powertools/event_handler/openapi/dependant.py @@ -4,6 +4,7 @@ import re from typing import TYPE_CHECKING, Any, ForwardRef, cast +from aws_lambda_powertools.event_handler.depends import DependencyParam, _get_depends_from_annotation from aws_lambda_powertools.event_handler.openapi.compat import ( ModelField, create_body_model, @@ -193,6 +194,22 @@ def get_dependant( if param.annotation is Request: continue + # Depends() parameters (via Annotated[Type, Depends(fn)]) are resolved at call time. + depends_instance = _get_depends_from_annotation(param.annotation) + if depends_instance is not None: + sub_dependant = get_dependant( + path=path, + call=depends_instance.dependency, + ) + dependant.dependencies.append( + DependencyParam( + param_name=param_name, + depends=depends_instance, + dependant=sub_dependant, + ), + ) + continue + # If the parameter is a path parameter, we need to set the in_ field to "path". is_path_param = param_name in path_param_names diff --git a/aws_lambda_powertools/event_handler/openapi/params.py b/aws_lambda_powertools/event_handler/openapi/params.py index 0f13e1e1990..1ade081959f 100644 --- a/aws_lambda_powertools/event_handler/openapi/params.py +++ b/aws_lambda_powertools/event_handler/openapi/params.py @@ -23,6 +23,7 @@ if TYPE_CHECKING: from collections.abc import Callable + from aws_lambda_powertools.event_handler.depends import DependencyParam from aws_lambda_powertools.event_handler.openapi.models import Example from aws_lambda_powertools.event_handler.openapi.types import CacheKey @@ -64,6 +65,7 @@ def __init__( http_connection_param_name: str | None = None, response_param_name: str | None = None, background_tasks_param_name: str | None = None, + dependencies: list[DependencyParam] | None = None, path: str | None = None, ) -> None: self.path_params = path_params or [] @@ -78,6 +80,7 @@ def __init__( self.http_connection_param_name = http_connection_param_name self.response_param_name = response_param_name self.background_tasks_param_name = background_tasks_param_name + self.dependencies = dependencies or [] self.name = name self.call = call # Store the path to be able to re-generate a dependable from it in overrides @@ -816,7 +819,7 @@ def get_flat_dependant( visited = [] visited.append(dependant.cache_key) - return Dependant( + flat = Dependant( path_params=dependant.path_params.copy(), query_params=dependant.query_params.copy(), header_params=dependant.header_params.copy(), @@ -825,6 +828,18 @@ def get_flat_dependant( path=dependant.path, ) + # Flatten sub-dependencies that declare HTTP params (query, header, etc.) + for dep in dependant.dependencies: + if dep.dependant.cache_key not in visited: + sub_flat = get_flat_dependant(dep.dependant, visited=visited) + flat.path_params.extend(sub_flat.path_params) + flat.query_params.extend(sub_flat.query_params) + flat.header_params.extend(sub_flat.header_params) + flat.cookie_params.extend(sub_flat.cookie_params) + flat.body_params.extend(sub_flat.body_params) + + return flat + def analyze_param( *, diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index b9666457dc8..0ffd8cee15c 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -1365,6 +1365,48 @@ You can use `append_context` when you want to share data between your App and Ro --8<-- "examples/event_handler_rest/src/split_route_append_context_module.py" ``` +### Dependency injection + +You can use `Depends()` to declare dependencies that are automatically resolved and injected into your route handlers. This provides type-safe, composable, and testable dependency injection. + +#### Basic usage + +Use `Annotated[Type, Depends(fn)]` to declare a dependency. The return value of `fn` is injected into the parameter automatically. + +```python hl_lines="5 8 20 25" +--8<-- "examples/event_handler_rest/src/dependency_injection.py" +``` + +#### Nested dependencies + +Dependencies can depend on other dependencies, forming a composable tree. Shared sub-dependencies are resolved once per invocation and cached automatically. + +```python hl_lines="18 22 29-30" +--8<-- "examples/event_handler_rest/src/dependency_injection_nested.py" +``` + +#### Accessing the request + +Dependencies that need access to the current request can declare a parameter typed as `Request`. It will be injected automatically. + +```python hl_lines="5-6 12 20" +--8<-- "examples/event_handler_rest/src/dependency_injection_with_request.py" +``` + +#### Testing with dependency overrides + +Use `dependency_overrides` to replace any dependency with a mock or stub during testing - no monkeypatching needed. + +```python hl_lines="3 12 26" +--8<-- "examples/event_handler_rest/src/dependency_injection_testing.py" +``` + +???+ 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. + +???+ info "`append_context` vs `Depends()`" + `append_context` remains available for backward compatibility. `Depends()` is recommended for new code because it provides type safety, IDE autocomplete, composable dependency trees, and `dependency_overrides` for testing. + #### Sample layout This is a sample project layout for a monolithic function with routes split in different files (`/todos`, `/health`). diff --git a/examples/event_handler_rest/src/dependency_injection.py b/examples/event_handler_rest/src/dependency_injection.py new file mode 100644 index 00000000000..664bc56951d --- /dev/null +++ b/examples/event_handler_rest/src/dependency_injection.py @@ -0,0 +1,32 @@ +import os +from typing import Any + +import boto3 +from typing_extensions import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver +from aws_lambda_powertools.event_handler.depends import Depends +from aws_lambda_powertools.utilities.typing import LambdaContext + +app = APIGatewayHttpResolver() + + +def get_dynamodb_table(): + dynamodb = boto3.resource("dynamodb") + return dynamodb.Table(os.environ["TABLE_NAME"]) + + +@app.get("/orders") +def list_orders(table: Annotated[Any, Depends(get_dynamodb_table)]): + return table.scan()["Items"] + + +@app.post("/orders") +def create_order(table: Annotated[Any, Depends(get_dynamodb_table)]): + order = app.current_event.json_body + table.put_item(Item=order) + return {"message": "Order created"} + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/dependency_injection_nested.py b/examples/event_handler_rest/src/dependency_injection_nested.py new file mode 100644 index 00000000000..f8245439538 --- /dev/null +++ b/examples/event_handler_rest/src/dependency_injection_nested.py @@ -0,0 +1,38 @@ +import os +from typing import Any + +import boto3 +from typing_extensions import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver +from aws_lambda_powertools.event_handler.depends import Depends +from aws_lambda_powertools.utilities.typing import LambdaContext + +app = APIGatewayHttpResolver() + + +def get_dynamodb_resource(): + return boto3.resource("dynamodb") + + +def get_orders_table(dynamodb: Annotated[Any, Depends(get_dynamodb_resource)]): + return dynamodb.Table(os.environ["ORDERS_TABLE"]) + + +def get_users_table(dynamodb: Annotated[Any, Depends(get_dynamodb_resource)]): + return dynamodb.Table(os.environ["USERS_TABLE"]) + + +@app.get("/orders/") +def get_user_orders( + user_id: str, + orders_table: Annotated[Any, Depends(get_orders_table)], + users_table: Annotated[Any, Depends(get_users_table)], +): + user = users_table.get_item(Key={"pk": user_id})["Item"] + orders = orders_table.query(KeyConditionExpression="pk = :uid", ExpressionAttributeValues={":uid": user_id}) + return {"user": user["name"], "orders": orders["Items"]} + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/dependency_injection_testing.py b/examples/event_handler_rest/src/dependency_injection_testing.py new file mode 100644 index 00000000000..3b9f41c5330 --- /dev/null +++ b/examples/event_handler_rest/src/dependency_injection_testing.py @@ -0,0 +1,26 @@ +from unittest.mock import MagicMock + +from dependency_injection import app, get_dynamodb_table + + +def test_list_orders(): + # Create a mock table + mock_table = MagicMock() + mock_table.scan.return_value = {"Items": [{"id": "order-1"}]} + + # Override the dependency with a lambda that returns the mock + app.dependency_overrides[get_dynamodb_table] = lambda: mock_table + + result = app( + { + "requestContext": {"http": {"method": "GET", "path": "/orders"}, "stage": "$default"}, + "rawPath": "/orders", + "headers": {}, + }, + {}, + ) + + assert result["statusCode"] == 200 + + # Clean up overrides after testing + app.dependency_overrides.clear() diff --git a/examples/event_handler_rest/src/dependency_injection_with_request.py b/examples/event_handler_rest/src/dependency_injection_with_request.py new file mode 100644 index 00000000000..c918b646f46 --- /dev/null +++ b/examples/event_handler_rest/src/dependency_injection_with_request.py @@ -0,0 +1,25 @@ +from typing_extensions import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver +from aws_lambda_powertools.event_handler.depends import Depends +from aws_lambda_powertools.event_handler.exceptions import UnauthorizedError +from aws_lambda_powertools.event_handler.request import Request +from aws_lambda_powertools.utilities.typing import LambdaContext + +app = APIGatewayHttpResolver() + + +def get_authenticated_user(request: Request) -> str: + user_id = request.headers.get("x-user-id") + if not user_id: + raise UnauthorizedError("Missing authentication") + return user_id + + +@app.get("/profile") +def get_profile(user_id: Annotated[str, Depends(get_authenticated_user)]): + return {"user_id": user_id} + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/tests/functional/event_handler/_pydantic/test_depends.py b/tests/functional/event_handler/_pydantic/test_depends.py new file mode 100644 index 00000000000..0cbc05b83c7 --- /dev/null +++ b/tests/functional/event_handler/_pydantic/test_depends.py @@ -0,0 +1,216 @@ +"""Tests for Depends() with OpenAPI schema generation and validation.""" + +import json +from typing import Annotated + +from pydantic import BaseModel + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver, Depends +from aws_lambda_powertools.event_handler.request import Request +from tests.functional.utils import load_event + +API_GW_V2_EVENT = load_event("apiGatewayProxyV2Event.json") + + +# --- Fixtures --- + + +class AppConfig(BaseModel): + region: str = "us-east-1" + debug: bool = False + + +def get_config() -> AppConfig: + return AppConfig(region="eu-west-1", debug=True) + + +def get_tenant() -> str: + return "tenant-abc" + + +# --- OpenAPI schema tests --- + + +def test_depends_excluded_from_openapi_schema(): + """Depends() parameters must NOT appear in the OpenAPI schema.""" + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/orders") + def handler(tenant: Annotated[str, Depends(get_tenant)], status: str = "active"): + return {"tenant": tenant, "status": status} + + schema = app.get_openapi_schema() + get_op = schema.paths["/orders"].get + param_names = [p.name for p in (get_op.parameters or [])] + + assert "tenant" not in param_names + assert "status" in param_names + + +def test_depends_with_pydantic_model_excluded_from_schema(): + """Depends() returning a Pydantic model must NOT appear as a body param in the schema.""" + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/info") + def handler(config: Annotated[AppConfig, Depends(get_config)]): + return {"region": config.region} + + schema = app.get_openapi_schema() + get_op = schema.paths["/info"].get + param_names = [p.name for p in (get_op.parameters or [])] + + assert "config" not in param_names + # Should have no request body either + assert get_op.requestBody is None + + +def test_depends_nested_excluded_from_openapi_schema(): + """Nested Depends() parameters must NOT appear in the OpenAPI schema.""" + app = APIGatewayHttpResolver(enable_validation=True) + + def get_prefix() -> str: + return "Hello" + + def get_greeting(prefix: Annotated[str, Depends(get_prefix)]) -> str: + return f"{prefix}, world!" + + @app.get("/greet") + def handler(greeting: Annotated[str, Depends(get_greeting)]): + return {"greeting": greeting} + + schema = app.get_openapi_schema() + get_op = schema.paths["/greet"].get + param_names = [p.name for p in (get_op.parameters or [])] + + assert "greeting" not in param_names + assert "prefix" not in param_names + + +# --- Validation + Depends integration tests --- + + +def test_depends_with_validation_resolves_and_validates(): + """Depends() values are injected alongside validated query params.""" + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/orders") + def handler(tenant: Annotated[str, Depends(get_tenant)], limit: int = 10): + return {"tenant": tenant, "limit": limit} + + event = {**API_GW_V2_EVENT} + event["rawPath"] = "/orders" + event["requestContext"] = { + **event["requestContext"], + "http": {"method": "GET", "path": "/orders"}, + } + event["queryStringParameters"] = {"limit": "5"} + + result = app(event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["tenant"] == "tenant-abc" + assert body["limit"] == 5 + + +def test_depends_pydantic_model_with_validation(): + """Depends() returning a Pydantic model works with enable_validation.""" + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/config") + def handler(config: Annotated[AppConfig, Depends(get_config)]): + return {"region": config.region, "debug": config.debug} + + event = {**API_GW_V2_EVENT} + event["rawPath"] = "/config" + event["requestContext"] = { + **event["requestContext"], + "http": {"method": "GET", "path": "/config"}, + } + + result = app(event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["region"] == "eu-west-1" + assert body["debug"] is True + + +def test_depends_with_request_and_validation(): + """Depends() with Request injection works alongside validation.""" + app = APIGatewayHttpResolver(enable_validation=True) + + def get_method(request: Request) -> str: + return request.method + + @app.post("/my/path") + def handler(method: Annotated[str, Depends(get_method)], name: str = "world"): + return {"method": method, "name": name} + + event = {**API_GW_V2_EVENT, "queryStringParameters": {"name": "Lambda"}} + result = app(event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["method"] == "POST" + assert body["name"] == "Lambda" + + +def test_depends_override_with_validation(): + """dependency_overrides works with enable_validation.""" + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/orders") + def handler(tenant: Annotated[str, Depends(get_tenant)]): + return {"tenant": tenant} + + app.dependency_overrides[get_tenant] = lambda: "test-tenant" + + event = {**API_GW_V2_EVENT} + event["rawPath"] = "/orders" + event["requestContext"] = { + **event["requestContext"], + "http": {"method": "GET", "path": "/orders"}, + } + + result = app(event, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"tenant": "test-tenant"} + + app.dependency_overrides.clear() + + +def test_depends_with_path_params_and_validation(): + """Depends() works with path parameters and validation.""" + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/orders/") + def handler(order_id: str, tenant: Annotated[str, Depends(get_tenant)]): + return {"order_id": order_id, "tenant": tenant} + + event = {**API_GW_V2_EVENT} + event["rawPath"] = "/orders/abc-123" + event["requestContext"] = { + **event["requestContext"], + "http": {"method": "GET", "path": "/orders/abc-123"}, + } + + result = app(event, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["order_id"] == "abc-123" + assert body["tenant"] == "tenant-abc" + + +def test_depends_with_regular_params_and_validation(): + """Depends() works alongside regular handler parameters with validation.""" + app = APIGatewayHttpResolver(enable_validation=True) + + def get_greeting() -> str: + return "hello" + + @app.post("/my/path") + def handler(name: str = "world", greeting: Annotated[str, Depends(get_greeting)] = ""): + return {"message": f"{greeting}, {name}!"} + + event = {**API_GW_V2_EVENT, "queryStringParameters": {"name": "Lambda"}} + result = app(event, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"message": "hello, Lambda!"} diff --git a/tests/functional/event_handler/required_dependencies/test_depends.py b/tests/functional/event_handler/required_dependencies/test_depends.py new file mode 100644 index 00000000000..3131be2430e --- /dev/null +++ b/tests/functional/event_handler/required_dependencies/test_depends.py @@ -0,0 +1,416 @@ +"""Tests for the Depends() dependency injection feature using Annotated.""" + +import json + +import pytest +from typing_extensions import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver +from aws_lambda_powertools.event_handler.depends import DependencyResolutionError, Depends +from aws_lambda_powertools.event_handler.request import Request +from tests.functional.utils import load_event + +API_GW_V2_EVENT = load_event("apiGatewayProxyV2Event.json") + + +def test_depends_simple(): + """A simple dependency is resolved and injected into the handler.""" + app = APIGatewayHttpResolver() + + def get_greeting() -> str: + return "hello" + + @app.post("/my/path") + def handler(greeting: Annotated[str, Depends(get_greeting)]): + return {"greeting": greeting} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"greeting": "hello"} + + +def test_depends_nested(): + """Dependencies can depend on other dependencies.""" + app = APIGatewayHttpResolver() + + def get_prefix() -> str: + return "Hello" + + def get_greeting(prefix: Annotated[str, Depends(get_prefix)]) -> str: + return f"{prefix}, world!" + + @app.post("/my/path") + def handler(greeting: Annotated[str, Depends(get_greeting)]): + return {"greeting": greeting} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"greeting": "Hello, world!"} + + +def test_depends_cache_per_invocation(): + """Same dependency used twice in one invocation is only resolved once (use_cache=True).""" + app = APIGatewayHttpResolver() + call_count = 0 + + def get_config() -> dict: + nonlocal call_count + call_count += 1 + return {"key": "value"} + + def get_a(config: Annotated[dict, Depends(get_config)]) -> str: + return config["key"] + + def get_b(config: Annotated[dict, Depends(get_config)]) -> str: + return config["key"] + + @app.post("/my/path") + def handler(a: Annotated[str, Depends(get_a)], b: Annotated[str, Depends(get_b)]): + return {"a": a, "b": b} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert call_count == 1 # get_config called once despite being used by both get_a and get_b + + +def test_depends_no_cache(): + """use_cache=False resolves every time.""" + app = APIGatewayHttpResolver() + call_count = 0 + + def get_value() -> int: + nonlocal call_count + call_count += 1 + return call_count + + @app.post("/my/path") + def handler( + a: Annotated[int, Depends(get_value, use_cache=False)], + b: Annotated[int, Depends(get_value, use_cache=False)], + ): + return {"a": a, "b": b} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert call_count == 2 + + +def test_depends_with_request(): + """A dependency can receive the Request object.""" + app = APIGatewayHttpResolver() + + def get_method(request: Request) -> str: + return request.method + + @app.post("/my/path") + def handler(method: Annotated[str, Depends(get_method)]): + return {"method": method} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"method": "POST"} + + +def test_depends_override(): + """dependency_overrides replaces a dependency callable for testing.""" + app = APIGatewayHttpResolver() + + def get_tenant() -> str: + return "real-tenant" + + @app.post("/my/path") + def handler(tenant: Annotated[str, Depends(get_tenant)]): + return {"tenant": tenant} + + app.dependency_overrides[get_tenant] = lambda: "test-tenant" + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"tenant": "test-tenant"} + + app.dependency_overrides.clear() + + +def test_depends_override_nested(): + """dependency_overrides works for nested dependencies too.""" + app = APIGatewayHttpResolver() + + def get_db_client(): + return "real-db" + + def get_table(db: Annotated[str, Depends(get_db_client)]) -> str: + return f"table-from-{db}" + + @app.post("/my/path") + def handler(table: Annotated[str, Depends(get_table)]): + return {"table": table} + + app.dependency_overrides[get_db_client] = lambda: "mock-db" + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"table": "table-from-mock-db"} + + app.dependency_overrides.clear() + + +def test_depends_multiple_handlers(): + """Dependencies work across different route handlers.""" + app = APIGatewayHttpResolver() + + def get_user() -> str: + return "user-123" + + @app.get("/my/path") + def get_handler(user: Annotated[str, Depends(get_user)]): + return {"user": user, "action": "get"} + + @app.post("/my/path") + def post_handler(user: Annotated[str, Depends(get_user)]): + return {"user": user, "action": "post"} + + # Test POST (matches the event) + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"user": "user-123", "action": "post"} + + +def test_depends_reusable_type_alias(): + """Annotated type aliases can be reused across handlers.""" + app = APIGatewayHttpResolver() + + def get_tenant() -> str: + return "tenant-abc" + + TenantId = Annotated[str, Depends(get_tenant)] + + @app.post("/my/path") + def handler(tenant: TenantId): + return {"tenant": tenant} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"tenant": "tenant-abc"} + + +def test_handler_without_depends_works_normally(): + """A plain handler with no Depends() params is not affected by DI.""" + app = APIGatewayHttpResolver() + + @app.post("/my/path") + def handler(): + return {"ok": True} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"ok": True} + + +def test_depends_not_cached_across_invocations(): + """Each app() call resolves dependencies fresh — no cross-request leakage.""" + app = APIGatewayHttpResolver() + call_count = 0 + + def get_counter() -> int: + nonlocal call_count + call_count += 1 + return call_count + + @app.post("/my/path") + def handler(c: Annotated[int, Depends(get_counter)]): + return {"c": c} + + result1 = app(API_GW_V2_EVENT, {}) + result2 = app(API_GW_V2_EVENT, {}) + + assert json.loads(result1["body"]) == {"c": 1} + assert json.loads(result2["body"]) == {"c": 2} + assert call_count == 2 + + +def test_depends_deeply_nested(): + """Three-level dependency chain resolves correctly.""" + app = APIGatewayHttpResolver() + + def get_url() -> str: + return "postgres://localhost" + + def get_conn(url: Annotated[str, Depends(get_url)]) -> str: + return f"conn({url})" + + def get_session(conn: Annotated[str, Depends(get_conn)]) -> str: + return f"session({conn})" + + @app.post("/my/path") + def handler(session: Annotated[str, Depends(get_session)]): + return {"session": session} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"session": "session(conn(postgres://localhost))"} + + +def test_depends_with_request_reads_headers(): + """A dependency using Request can read actual request headers.""" + app = APIGatewayHttpResolver() + + def get_user_agent(request: Request) -> str: + return request.headers.get("user-agent", "unknown") + + @app.post("/my/path") + def handler(ua: Annotated[str, Depends(get_user_agent)]): + return {"ua": ua} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert isinstance(json.loads(result["body"])["ua"], str) + + +def test_depends_returning_none(): + """A dependency can return None without breaking.""" + app = APIGatewayHttpResolver() + + def get_nothing() -> None: + return None + + @app.post("/my/path") + def handler(val: Annotated[None, Depends(get_nothing)]): + return {"val": val} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"val": None} + + +def test_depends_exception_raises_dependency_resolution_error(): + """If a dependency raises, a DependencyResolutionError wraps the original exception.""" + app = APIGatewayHttpResolver() + + def broken() -> str: + raise ValueError("boom") + + @app.post("/my/path") + def handler(val: Annotated[str, Depends(broken)]): + return {"val": val} + + with pytest.raises(DependencyResolutionError, match="broken.*boom"): + app(API_GW_V2_EVENT, {}) + + +def test_depends_non_callable_raises_dependency_resolution_error(): + """Passing a non-callable to Depends() raises DependencyResolutionError immediately.""" + with pytest.raises(DependencyResolutionError, match="requires a callable"): + Depends("not_a_function") # type: ignore + + with pytest.raises(DependencyResolutionError, match="requires a callable"): + Depends(42) # type: ignore + + with pytest.raises(DependencyResolutionError, match="requires a callable"): + Depends(None) # type: ignore + + +def test_depends_accepts_lambda(): + """Depends() works with a lambda as the dependency.""" + app = APIGatewayHttpResolver() + + @app.post("/my/path") + def handler(val: Annotated[str, Depends(lambda: "from-lambda")]): + return {"val": val} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"val": "from-lambda"} + + +def test_depends_accepts_class_with_call(): + """Depends() works with a class that implements __call__.""" + app = APIGatewayHttpResolver() + + class TenantProvider: + def __call__(self) -> str: + return "tenant-from-class" + + @app.post("/my/path") + def handler(tenant: Annotated[str, Depends(TenantProvider())]): + return {"tenant": tenant} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"tenant": "tenant-from-class"} + + +def test_depends_accepts_class_as_factory(): + """Depends() works with a class itself (constructor as callable).""" + app = APIGatewayHttpResolver() + + class Config: + def __init__(self): + self.region = "us-east-1" + + @app.post("/my/path") + def handler(config: Annotated[Config, Depends(Config)]): + return {"region": config.region} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"region": "us-east-1"} + + +def test_depends_with_unresolvable_annotations_is_ignored(): + """A handler whose annotations cannot be resolved by get_type_hints is treated as having no deps.""" + app = APIGatewayHttpResolver() + + # Build a function with broken annotations that get_type_hints cannot resolve. + # The param has a default so the handler can still be called without it. + def make_handler(): + def handler(x: "CompletelyBogusType" = None): # noqa: F821 + return {"ok": True} + + return handler + + app.post("/my/path")(make_handler()) + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"ok": True} + + +def test_depends_without_request_does_not_inject(): + """A dependency that does NOT declare Request still works when request is available.""" + app = APIGatewayHttpResolver() + + def get_static() -> str: + return "no-request-needed" + + @app.post("/my/path") + def handler(val: Annotated[str, Depends(get_static)]): + return {"val": val} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"val": "no-request-needed"} + + +def test_depends_with_broken_type_hints_on_dependency(): + """A dependency callable with broken annotations still resolves (get_type_hints fails gracefully).""" + app = APIGatewayHttpResolver() + + # Create a callable whose annotations reference a nonexistent type + # so get_type_hints() will raise inside solve_dependencies + broken_dep = type( + "BrokenDep", + (), + { + "__call__": lambda self: "it-works", + "__annotations__": {"x": "NonExistentType"}, + "__module__": __name__, + }, + )() + + @app.post("/my/path") + def handler(val: Annotated[str, Depends(broken_dep)]): + return {"val": val} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"val": "it-works"} From d4885486d7d1bd2ef0591c3d63c9f52b7f570ae3 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 8 Apr 2026 23:42:11 +0800 Subject: [PATCH 44/84] docs: adding new Lambda features (#7917) * docs: adding new Lambda features * Addressing all feedback * Addressing Phillip's feedback * Addressing Steffano's feedback --- docs/lambda-features/durable-functions.md | 151 ++++++++++++++++++ docs/lambda-features/index.md | 28 ++++ docs/lambda-features/managed-instances.md | 102 ++++++++++++ examples/lambda_features/__init__.py | 0 .../durable_functions/__init__.py | 0 .../durable_functions/src/__init__.py | 0 .../src/best_practice_idempotency.py | 21 +++ .../src/best_practice_metrics.py | 23 +++ .../src/using_idempotency.py | 26 +++ .../durable_functions/src/using_logger.py | 25 +++ .../durable_functions/src/using_parameters.py | 20 +++ .../durable_functions/src/using_tracer.py | 27 ++++ .../managed_instances/__init__.py | 0 .../managed_instances/src/__init__.py | 0 .../src/using_idempotency.py | 14 ++ .../managed_instances/src/using_parameters.py | 11 ++ .../managed_instances/src/using_tracer.py | 28 ++++ mkdocs.yml | 4 + 18 files changed, 480 insertions(+) create mode 100644 docs/lambda-features/durable-functions.md create mode 100644 docs/lambda-features/index.md create mode 100644 docs/lambda-features/managed-instances.md create mode 100644 examples/lambda_features/__init__.py create mode 100644 examples/lambda_features/durable_functions/__init__.py create mode 100644 examples/lambda_features/durable_functions/src/__init__.py create mode 100644 examples/lambda_features/durable_functions/src/best_practice_idempotency.py create mode 100644 examples/lambda_features/durable_functions/src/best_practice_metrics.py create mode 100644 examples/lambda_features/durable_functions/src/using_idempotency.py create mode 100644 examples/lambda_features/durable_functions/src/using_logger.py create mode 100644 examples/lambda_features/durable_functions/src/using_parameters.py create mode 100644 examples/lambda_features/durable_functions/src/using_tracer.py create mode 100644 examples/lambda_features/managed_instances/__init__.py create mode 100644 examples/lambda_features/managed_instances/src/__init__.py create mode 100644 examples/lambda_features/managed_instances/src/using_idempotency.py create mode 100644 examples/lambda_features/managed_instances/src/using_parameters.py create mode 100644 examples/lambda_features/managed_instances/src/using_tracer.py diff --git a/docs/lambda-features/durable-functions.md b/docs/lambda-features/durable-functions.md new file mode 100644 index 00000000000..9a2e6f9b831 --- /dev/null +++ b/docs/lambda-features/durable-functions.md @@ -0,0 +1,151 @@ +--- +title: Durable Functions +description: Using Powertools for AWS Lambda (Python) with Lambda Durable Functions +--- + + + +[Lambda Durable Functions](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html){target="_blank" rel="nofollow"} enable you to build resilient multi-step workflows that can execute for up to one year. They use checkpoints to track progress and automatically recover from failures through replay. + +## Key concepts + +| Concept | Description | +| --------------------- | ------------------------------------------------------------------ | +| **Durable execution** | Complete lifecycle of a durable function, from start to completion | +| **Checkpoint** | Saved state that tracks progress through the workflow | +| **Replay** | Re-execution from the beginning, skipping completed checkpoints | +| **Step** | Business logic with built-in retries and progress tracking | +| **Wait** | Suspend execution without incurring compute charges | + +## How it works + +Durable functions use a **checkpoint/replay mechanism**: + +1. Your code runs always from the beginning +2. Completed operations are skipped using stored results +3. Execution of new steps continues from where it left off +4. State is automatically managed by the SDK + +## Powertools integration + +Powertools for AWS Lambda (Python) works seamlessly with Durable Functions. The [Durable Execution SDK](https://github.com/aws/aws-durable-execution-sdk-python){target="_blank" rel="nofollow"} has native integration with Logger via `context.set_logger()`. + +???+ note "Found an issue?" + If you encounter any issues using Powertools for AWS Lambda (Python) with Durable Functions, please [open an issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new?template=bug_report.yml){target="_blank"}. + +### Logger + +The Durable Execution SDK provides a `context.logger` instance that automatically handles **log deduplication during replays**. You can integrate Logger to get structured JSON logging while keeping the deduplication benefits. + +For the best experience, set the Logger on the durable context. This gives you structured JSON logging with automatic log deduplication during replays: + +```python hl_lines="5 8 12 15" title="Integrating Logger with Durable Functions" +--8<-- "examples/lambda_features/durable_functions/src/using_logger.py" +``` + +This gives you: + +- **JSON structured logging** from Powertools for AWS Lambda (Python) +- **Log deduplication** during replays (logs from completed operations don't repeat) +- **Automatic SDK enrichment** (execution_arn, parent_id, name, attempt) +- **Lambda context injection** (request_id, function_name, etc.) + +???+ warning "Direct logger usage" + If you use the Logger directly (not through `context.logger`), logs will be emitted on every replay: + + ```python + # Logs will duplicate during replays + logger.info("This appears on every replay") + + # Use context.logger instead for deduplication + context.logger.info("This appears only once") + ``` + +### Tracer + +Tracer works with Durable Functions. Each execution creates trace segments. + +???+ note "Trace continuity" + Due to the replay mechanism, traces may be interleaved. Each execution (including replays) creates separate trace segments. Use the `execution_arn` to correlate traces. + +```python hl_lines="5-6 9-10" title="Using Tracer with Durable Functions" +--8<-- "examples/lambda_features/durable_functions/src/using_tracer.py" +``` + +### Metrics + +Metrics work with Durable Functions, but be aware that **metrics may be emitted multiple times** during replay if not handled carefully. Emit metrics at workflow completion rather than during intermediate steps to avoid counting replays as new executions. + +```python hl_lines="6 9 18 19 20 21" title="Using Metrics with Durable Functions" +--8<-- "examples/lambda_features/durable_functions/src/best_practice_metrics.py" +``` + +### Idempotency + +The `@idempotent` decorator integrates with Durable Functions and is **replay-aware**. It's useful for protecting the Lambda handler entry point, especially for Event Source Mapping (ESM) invocations like SQS, Kinesis, or DynamoDB Streams. + +```python hl_lines="8 15" title="Using Idempotency with Durable Functions" +--8<-- "examples/lambda_features/durable_functions/src/using_idempotency.py" +``` + +???+ warning "Decorator ordering matters" + The `@idempotent` decorator must be placed **above** `@durable_execution`. This ensures the idempotency check runs first, preventing duplicate executions before the durable workflow begins. Reversing the order would cause the durable execution to start before the idempotency check, defeating its purpose. + +**When to use Powertools Idempotency:** + +- Protecting the Lambda handler entry point from duplicate invocations +- Methods you don't want to convert into steps but need idempotency guarantees +- Event Source Mapping triggers (SQS, Kinesis, DynamoDB Streams) + +**When you don't need it:** + +- Steps within a durable function are already idempotent via the checkpoint mechanism + +### Parameters + +Parameters work normally with Durable Functions. + +```python hl_lines="13" title="Using Parameters with Durable Functions" +--8<-- "examples/lambda_features/durable_functions/src/using_parameters.py" +``` + +???+ note "Parameter freshness" + If the replay or execution happens within the cache TTL on the same execution environment, the parameter value may come from cache. For long-running workflows (hours/days), parameters fetched at the start may become stale. Consider fetching parameters within steps that need the latest values, and customize the caching behavior with `max_age` to control freshness. + +## Best practices + +### Use Idempotency for ESM triggers + +When your durable function is triggered by Event Source Mappings (SQS, Kinesis, DynamoDB Streams), use the `@idempotent` decorator to protect against duplicate invocations. + +```python title="Idempotency for ESM" +--8<-- "examples/lambda_features/durable_functions/src/best_practice_idempotency.py" +``` + +## FAQ + +### Do I need Idempotency utility with Durable Functions? + +It depends on your use case. Steps within a durable function are already idempotent via checkpoints. However, the `@idempotent` decorator is useful for protecting the Lambda handler entry point, especially for Event Source Mapping invocations (SQS, Kinesis, DynamoDB Streams) where the same event might trigger multiple invocations. + +### Why do I see duplicate logs? + +If you're using the logger directly instead of `context.logger`, logs will be emitted on every replay. Use `context.set_logger(logger)` and then `context.logger.info()` to get automatic log deduplication. + +### How do I correlate logs across replays? + +Use the `execution_arn` field that's automatically added to every log entry when using `context.logger`: + +```sql +fields @timestamp, @message, execution_arn +| filter execution_arn = "arn:aws:lambda:us-east-1:123456789012:function:my-function:execution-id" +| sort @timestamp asc +``` + +### Can I use Tracer with Durable Functions? + +Yes, but be aware that each execution (including replays) creates separate trace segments. Use the `execution_arn` as a correlation identifier for end-to-end visibility. + +### How should I emit metrics without duplicates? + +Emit metrics at workflow completion rather than during intermediate steps. This ensures you count completed workflows, not replay attempts. diff --git a/docs/lambda-features/index.md b/docs/lambda-features/index.md new file mode 100644 index 00000000000..30d791c8601 --- /dev/null +++ b/docs/lambda-features/index.md @@ -0,0 +1,28 @@ +--- +title: Lambda Features +description: Using Powertools with advanced Lambda features +--- + + + +This section covers how to use Powertools for AWS Lambda (Python) with advanced Lambda features like Lambda Managed Instances and Durable Functions. + +
+ +- :material-server:{ .lg .middle } __Lambda Managed Instances__ + + --- + + Run Lambda functions on EC2 instances with multi-concurrent invocations + + [:octicons-arrow-right-24: Getting started](./managed-instances.md) + +- :material-state-machine:{ .lg .middle } __Durable Functions__ + + --- + + Build resilient multi-step workflows that can execute for up to one year + + [:octicons-arrow-right-24: Getting started](./durable-functions.md) + +
diff --git a/docs/lambda-features/managed-instances.md b/docs/lambda-features/managed-instances.md new file mode 100644 index 00000000000..38779673a7f --- /dev/null +++ b/docs/lambda-features/managed-instances.md @@ -0,0 +1,102 @@ +--- +title: Lambda Managed Instances +description: Using Powertools for AWS Lambda (Python) with Lambda Managed Instances +--- + + + +[Lambda Managed Instances](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances.html){target="_blank" rel="nofollow"} enables you to run Lambda functions on Amazon EC2 instances without managing infrastructure. It supports multi-concurrent invocations, EC2 pricing models, and specialized compute options like Graviton4. + +## Key differences from Lambda On Demand + +| Aspect | Lambda On Demand | Lambda Managed Instances | +| ---------------- | ------------------------------------------- | ----------------------------------------------- | +| **Concurrency** | Single invocation per execution environment | Multiple concurrent invocations per environment | +| **Python model** | One process, one request | Multiple processes, one request each | +| **Pricing** | Per-request duration | EC2-based with Savings Plans support | +| **Scaling** | Scale on demand with cold starts | Async scaling based on CPU | +| **Isolation** | Firecracker microVMs | Containers on EC2 Nitro | + +## How Lambda Python runtime handles concurrency + +The **Lambda Python runtime uses multiple processes** for concurrent requests. Each request runs in a separate process, which provides natural isolation between requests. + +This means: + +- **Each process has its own memory** - global variables are isolated per process +- **`/tmp` directory is shared** across all processes - use caution with file operations + +For more details on the isolation model, see [Lambda Managed Instances documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances.html){target="_blank" rel="nofollow"}. + +## Powertools integration + +Powertools for AWS Lambda (Python) works seamlessly with Lambda Managed Instances. All utilities are compatible with the multi-process concurrency model used by Python. + +### Logger, Tracer, and Metrics + +Core utilities work without any changes. Each process has its own instances, so correlation IDs and traces are naturally isolated per request. + +???+ note "VPC connectivity required" + Lambda Managed Instances run in your VPC. Ensure you have [network connectivity](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances-networking.html){target="_blank" rel="nofollow"} to send logs to CloudWatch, traces to X-Ray, and metrics to CloudWatch. + +```python hl_lines="5 6 7 10 11 12 20 25" title="Using Logger, Tracer, and Metrics with Managed Instances" +--8<-- "examples/lambda_features/managed_instances/src/using_tracer.py" +``` + +### Parameters + +The Parameters utility works as expected, but be aware that **caching is per-process**. + +```python hl_lines="9" title="Using Parameters with Managed Instances" +--8<-- "examples/lambda_features/managed_instances/src/using_parameters.py" +``` + +???+ tip "Cache behavior" + Since each process has its own cache, you might see more calls to SSM/Secrets Manager during initial warm-up. Once each process has cached the value, subsequent requests within that process use the cache. You can customize the caching behavior with `max_age` to control the TTL. + +### Idempotency + +Idempotency works without any changes. It uses DynamoDB for state management, which is external to the process. + +```python hl_lines="7 10" title="Using Idempotency with Managed Instances" +--8<-- "examples/lambda_features/managed_instances/src/using_idempotency.py" +``` + +## VPC connectivity + +Lambda Managed Instances require VPC configuration for: + +- Sending logs to CloudWatch Logs +- Sending traces to X-Ray +- Accessing AWS services (SSM, Secrets Manager, DynamoDB, etc.) + +Configure connectivity using one of these options: + +1. **VPC Endpoints** - Private connectivity without internet access +2. **NAT Gateway** - Internet access from private subnets +3. **Public subnet with Internet Gateway** - Direct internet access +4. **Egress-only Internet Gateway** - IPv6 outbound connectivity without inbound access ([learn more](https://docs.aws.amazon.com/vpc/latest/userguide/egress-only-internet-gateway.html){target="_blank" rel="nofollow"}) + +See [Networking for Lambda Managed Instances](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances-networking.html){target="_blank" rel="nofollow"} for detailed setup instructions. + +## FAQ + +### Does Powertools for AWS Lambda (Python) work with Lambda Managed Instances? + +Yes, all Powertools for AWS Lambda (Python) utilities work seamlessly with Lambda Managed Instances. The multi-process model in Python provides natural isolation between concurrent requests. + +### Is my code thread-safe? + +Lambda Managed Instances uses **multiple processes**, instead of threads. Each request runs in its own process with isolated memory. If you implement multi-threading within your handler, you are responsible for thread safety. + +### Why is my cache not shared between requests? + +Each process maintains its own cache (for Parameters, Feature Flags, etc.). This is expected behavior. The cache will warm up independently per process, which may result in slightly more calls to backend services during initial warm-up. + +### Can I use global variables? + +Yes, but remember they are **per-process**, not shared across concurrent requests. This is actually safer than shared state. + +### Do I need to change my existing Powertools for AWS Lambda (Python) code? + +No changes are required if you are running Powertools for AWS Lambda (Python) version **3.4.0** or later. Your existing code will work as-is with Lambda Managed Instances. diff --git a/examples/lambda_features/__init__.py b/examples/lambda_features/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/lambda_features/durable_functions/__init__.py b/examples/lambda_features/durable_functions/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/lambda_features/durable_functions/src/__init__.py b/examples/lambda_features/durable_functions/src/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/lambda_features/durable_functions/src/best_practice_idempotency.py b/examples/lambda_features/durable_functions/src/best_practice_idempotency.py new file mode 100644 index 00000000000..6d412b6127b --- /dev/null +++ b/examples/lambda_features/durable_functions/src/best_practice_idempotency.py @@ -0,0 +1,21 @@ +from aws_durable_execution_sdk_python import DurableContext, durable_execution # type: ignore[import-not-found] + +from aws_lambda_powertools.utilities.idempotency import ( + DynamoDBPersistenceLayer, + idempotent, +) + +persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable") + + +@idempotent(persistence_store=persistence_layer) +@durable_execution +def handler(event: dict, context: DurableContext) -> str: + # Protected against duplicate SQS/Kinesis/DynamoDB triggers + + result: str = context.step( + lambda _: "processed", + name="process", + ) + + return result diff --git a/examples/lambda_features/durable_functions/src/best_practice_metrics.py b/examples/lambda_features/durable_functions/src/best_practice_metrics.py new file mode 100644 index 00000000000..59bd2c037ad --- /dev/null +++ b/examples/lambda_features/durable_functions/src/best_practice_metrics.py @@ -0,0 +1,23 @@ +from aws_durable_execution_sdk_python import DurableContext, durable_execution # type: ignore[import-not-found] + +from aws_lambda_powertools import Metrics +from aws_lambda_powertools.metrics import MetricUnit + +metrics = Metrics() + + +@metrics.log_metrics +@durable_execution +def handler(event: dict, context: DurableContext) -> str: + result: str = context.step( + lambda _: "processed", + name="process", + ) + + # Emit metrics in a dedicated step to ensure they are only counted once + context.step( + lambda _: metrics.add_metric(name="WorkflowCompleted", unit=MetricUnit.Count, value=1), + name="emit_completion_metric", + ) + + return result diff --git a/examples/lambda_features/durable_functions/src/using_idempotency.py b/examples/lambda_features/durable_functions/src/using_idempotency.py new file mode 100644 index 00000000000..04654dd5c9d --- /dev/null +++ b/examples/lambda_features/durable_functions/src/using_idempotency.py @@ -0,0 +1,26 @@ +from aws_durable_execution_sdk_python import DurableContext, durable_execution # type: ignore[import-not-found] + +from aws_lambda_powertools.utilities.idempotency import ( + DynamoDBPersistenceLayer, + idempotent, +) + +persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable") + + +def process_order(event: dict) -> str: + return f"processed-{event.get('order_id')}" + + +@idempotent(persistence_store=persistence_layer) +@durable_execution +def handler(event: dict, context: DurableContext) -> str: + # Idempotency protects against duplicate ESM invocations + # Steps within the workflow are already idempotent via checkpoints + + result: str = context.step( + lambda _: process_order(event), + name="process_order", + ) + + return result diff --git a/examples/lambda_features/durable_functions/src/using_logger.py b/examples/lambda_features/durable_functions/src/using_logger.py new file mode 100644 index 00000000000..577a15eb583 --- /dev/null +++ b/examples/lambda_features/durable_functions/src/using_logger.py @@ -0,0 +1,25 @@ +from aws_durable_execution_sdk_python import DurableContext, durable_execution # type: ignore[import-not-found] + +from aws_lambda_powertools import Logger + +logger = Logger(service="order-processing") + + +@logger.inject_lambda_context +@durable_execution +def handler(event: dict, context: DurableContext) -> str: + # Set Logger on the context for automatic deduplication + context.set_logger(logger) + + # Logs via context.logger appear only once, even during replays + context.logger.info("Starting workflow", extra={"order_id": event.get("order_id")}) + + result: str = context.step( + lambda _: "processed", + name="process_order", + ) + + # This log won't repeat when the function replays after completing the step above + context.logger.info("Workflow completed", extra={"result": result}) + + return result diff --git a/examples/lambda_features/durable_functions/src/using_parameters.py b/examples/lambda_features/durable_functions/src/using_parameters.py new file mode 100644 index 00000000000..92f2c28256a --- /dev/null +++ b/examples/lambda_features/durable_functions/src/using_parameters.py @@ -0,0 +1,20 @@ +from aws_durable_execution_sdk_python import DurableContext, durable_execution # type: ignore[import-not-found] + +from aws_lambda_powertools.utilities import parameters + + +def call_api(api_key: str) -> str: + return f"called-with-{api_key[:4]}..." + + +@durable_execution +def handler(event: dict, context: DurableContext) -> str: + # Parameters may come from cache if replay hits the same execution environment within the TTL + api_key = parameters.get_secret("api-key") + + result: str = context.step( + lambda _: call_api(api_key), + name="call_api", + ) + + return result diff --git a/examples/lambda_features/durable_functions/src/using_tracer.py b/examples/lambda_features/durable_functions/src/using_tracer.py new file mode 100644 index 00000000000..a70b6f46277 --- /dev/null +++ b/examples/lambda_features/durable_functions/src/using_tracer.py @@ -0,0 +1,27 @@ +from aws_durable_execution_sdk_python import DurableContext, durable_execution # type: ignore[import-not-found] + +from aws_lambda_powertools import Logger, Tracer + +tracer = Tracer() +logger = Logger() + + +@logger.inject_lambda_context +@tracer.capture_lambda_handler +@durable_execution +def handler(event: dict, context: DurableContext) -> str: + context.set_logger(logger) + + result: str = context.step( + lambda _: process_data(), + name="process_data", + ) + + return result + + +@tracer.capture_method +def process_data() -> str: + # This is traced on first execution + # On replay, the cached result is used + return "processed" diff --git a/examples/lambda_features/managed_instances/__init__.py b/examples/lambda_features/managed_instances/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/lambda_features/managed_instances/src/__init__.py b/examples/lambda_features/managed_instances/src/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/lambda_features/managed_instances/src/using_idempotency.py b/examples/lambda_features/managed_instances/src/using_idempotency.py new file mode 100644 index 00000000000..e0e054d07f6 --- /dev/null +++ b/examples/lambda_features/managed_instances/src/using_idempotency.py @@ -0,0 +1,14 @@ +from aws_lambda_powertools.utilities.idempotency import ( + DynamoDBPersistenceLayer, + idempotent, +) +from aws_lambda_powertools.utilities.typing import LambdaContext + +persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable") + + +@idempotent(persistence_store=persistence_layer) +def lambda_handler(event: dict, context: LambdaContext) -> dict: + # Idempotency is guaranteed across all concurrent requests + # DynamoDB handles the distributed locking + return {"statusCode": 200, "body": "Order processed"} diff --git a/examples/lambda_features/managed_instances/src/using_parameters.py b/examples/lambda_features/managed_instances/src/using_parameters.py new file mode 100644 index 00000000000..36ded9cc9c6 --- /dev/null +++ b/examples/lambda_features/managed_instances/src/using_parameters.py @@ -0,0 +1,11 @@ +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + # Cache is per-process, not shared across concurrent requests + # Each process maintains its own cache + # This is generally fine - cache will warm up per process + api_key = parameters.get_secret("my-api-key", max_age=300) # noqa: F841 + + return {"statusCode": 200} diff --git a/examples/lambda_features/managed_instances/src/using_tracer.py b/examples/lambda_features/managed_instances/src/using_tracer.py new file mode 100644 index 00000000000..3cb4ee6f7fd --- /dev/null +++ b/examples/lambda_features/managed_instances/src/using_tracer.py @@ -0,0 +1,28 @@ +from aws_lambda_powertools import Logger, Metrics, Tracer +from aws_lambda_powertools.metrics import MetricUnit +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +metrics = Metrics() + + +@tracer.capture_lambda_handler +@metrics.log_metrics +@logger.inject_lambda_context +def lambda_handler(event: dict, context: LambdaContext) -> dict: + order_id = event.get("order_id", "unknown") + logger.append_keys(order_id=order_id) + + result = process_order(order_id) + + # Metrics are flushed per request + metrics.add_metric(name="OrderProcessed", unit=MetricUnit.Count, value=1) + + return {"statusCode": 200, "body": result} + + +@tracer.capture_method +def process_order(order_id: str) -> str: + logger.info("Processing order") + return f"Processed order {order_id}" diff --git a/mkdocs.yml b/mkdocs.yml index 72921ac161d..6bea356bac6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -40,6 +40,10 @@ nav: - utilities/middleware_factory.md - utilities/jmespath_functions.md - CloudFormation Custom Resources: https://github.com/aws-cloudformation/custom-resource-helper" target="_blank + - Lambda Features: + - lambda-features/index.md + - lambda-features/managed-instances.md + - lambda-features/durable-functions.md - Build recipes: - build_recipes/index.md - Getting started: build_recipes/getting-started.md From 45d25e95ddf499fe84da84731bc43ba46e3aae19 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 8 Apr 2026 23:46:54 +0800 Subject: [PATCH 45/84] feat(event_handler): adding status_code OpenAPI field (#8130) * feat(event_handler): adding status_code OpenAPI field * feat(event_handler): adding status_code OpenAPI field --- .../event_handler/api_gateway.py | 33 ++++++- .../event_handler/bedrock_agent.py | 11 +++ .../event_handler/openapi/constants.py | 1 + .../event_handler/openapi/schema_generator.py | 12 ++- .../_openapi_customization_operations.md | 3 +- docs/core/event_handler/openapi.md | 2 +- .../src/customizing_api_operations.py | 12 +++ .../_pydantic/test_api_gateway.py | 66 ++++++++++++++ .../_pydantic/test_openapi_responses.py | 86 +++++++++++++++++++ 9 files changed, 218 insertions(+), 8 deletions(-) diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 7ffaa884761..f54d486080f 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -26,6 +26,7 @@ DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, DEFAULT_OPENAPI_TITLE, DEFAULT_OPENAPI_VERSION, + DEFAULT_STATUS_CODE, ) from aws_lambda_powertools.event_handler.openapi.exceptions import ( RequestUnsupportedContentType, @@ -283,7 +284,7 @@ class BedrockResponse(Generic[ResponseT]): def __init__( self, body: Any = None, - status_code: int = 200, + status_code: int = DEFAULT_STATUS_CODE, content_type: str = DEFAULT_CONTENT_TYPE, session_attributes: dict[str, Any] | None = None, prompt_session_attributes: dict[str, Any] | None = None, @@ -387,6 +388,7 @@ def __init__( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Response]] | None = None, ): """ @@ -432,6 +434,9 @@ def __init__( Enable or disable validation for this specific route. If None, inherits from resolver setting. custom_response_validation_http_code: int | HTTPStatus | None, optional Whether to have custom http status code for this route if response validation fails + status_code: int + The default HTTP status code for successful responses. Used in both the OpenAPI schema + and the actual response when the handler returns a dict. Defaults to 200. middlewares: list[Callable[..., Response]] | None The list of route middlewares to be called in order. """ @@ -471,6 +476,7 @@ def __init__( self._body_field: ModelField | None = None self.custom_response_validation_http_code = custom_response_validation_http_code + self.status_code = status_code # Cache whether this route's handler declares Depends() parameters self._has_dependencies: bool | None = None @@ -664,6 +670,7 @@ def _get_openapi_path( response_description=self.response_description, body_field=self.body_field, custom_response_validation_http_code=self.custom_response_validation_http_code, + status_code=self.status_code, dependant=dependant, operation_ids=operation_ids, model_name_map=model_name_map, @@ -820,6 +827,7 @@ def route( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: raise NotImplementedError() @@ -883,6 +891,7 @@ def get( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: """Get route decorator with GET `method` @@ -925,6 +934,7 @@ def lambda_handler(event, context): deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -946,6 +956,7 @@ def post( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: """Post route decorator with POST `method` @@ -989,6 +1000,7 @@ def lambda_handler(event, context): deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -1010,6 +1022,7 @@ def put( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: """Put route decorator with PUT `method` @@ -1053,6 +1066,7 @@ def lambda_handler(event, context): deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -1074,6 +1088,7 @@ def delete( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: """Delete route decorator with DELETE `method` @@ -1116,6 +1131,7 @@ def lambda_handler(event, context): deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -1137,6 +1153,7 @@ def patch( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: """Patch route decorator with PATCH `method` @@ -1182,6 +1199,7 @@ def lambda_handler(event, context): deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -1203,6 +1221,7 @@ def head( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: """Head route decorator with HEAD `method` @@ -1247,6 +1266,7 @@ def lambda_handler(event, context): deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -2357,6 +2377,7 @@ def route( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: """Route decorator includes parameter `method`""" @@ -2392,6 +2413,7 @@ def register_resolver(func: AnyCallableT) -> AnyCallableT: deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -2779,12 +2801,15 @@ def _to_response(self, result: dict | tuple | Response | BedrockResponse) -> Res - tuple[dict, int]: Same dict handling as above but with the option of including a status code - Response: returned as is, and allows for more flexibility """ - status_code = HTTPStatus.OK if isinstance(result, (Response, BedrockResponse)): return result elif isinstance(result, tuple) and len(result) == 2: # Unpack result dict and status code from tuple result, status_code = result + else: + # Use the route's status_code if available, otherwise default to 200 + route: Route | None = self.context.get("_route") + status_code = route.status_code if route else HTTPStatus.OK logger.debug("Simple response detected, serializing return before constructing final response") return Response( @@ -2903,6 +2928,7 @@ def route( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: def register_route(func: AnyCallableT) -> AnyCallableT: @@ -2931,6 +2957,7 @@ def register_route(func: AnyCallableT) -> AnyCallableT: deprecated, enable_validation, custom_response_validation_http_code, + status_code, ) # Collate Middleware for routes @@ -3000,6 +3027,7 @@ def route( deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[AnyCallableT], AnyCallableT]: # NOTE: see #1552 for more context. @@ -3021,6 +3049,7 @@ def route( deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) diff --git a/aws_lambda_powertools/event_handler/bedrock_agent.py b/aws_lambda_powertools/event_handler/bedrock_agent.py index e9aa82ee01f..a49ba38c214 100644 --- a/aws_lambda_powertools/event_handler/bedrock_agent.py +++ b/aws_lambda_powertools/event_handler/bedrock_agent.py @@ -15,6 +15,7 @@ DEFAULT_API_VERSION, DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, DEFAULT_OPENAPI_VERSION, + DEFAULT_STATUS_CODE, ) if TYPE_CHECKING: @@ -129,6 +130,7 @@ def get( # type: ignore[override] deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ) -> Callable[[Callable[..., Any]], Callable[..., Any]]: security = None @@ -150,6 +152,7 @@ def get( # type: ignore[override] deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -172,6 +175,7 @@ def post( # type: ignore[override] deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ): security = None @@ -193,6 +197,7 @@ def post( # type: ignore[override] deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -215,6 +220,7 @@ def put( # type: ignore[override] deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ): security = None @@ -236,6 +242,7 @@ def put( # type: ignore[override] deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -258,6 +265,7 @@ def patch( # type: ignore[override] deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable] | None = None, ): security = None @@ -279,6 +287,7 @@ def patch( # type: ignore[override] deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) @@ -301,6 +310,7 @@ def delete( # type: ignore[override] deprecated: bool = False, enable_validation: bool | None = None, custom_response_validation_http_code: int | HTTPStatus | None = None, + status_code: int = DEFAULT_STATUS_CODE, middlewares: list[Callable[..., Any]] | None = None, ): security = None @@ -322,6 +332,7 @@ def delete( # type: ignore[override] deprecated, enable_validation, custom_response_validation_http_code, + status_code, middlewares, ) diff --git a/aws_lambda_powertools/event_handler/openapi/constants.py b/aws_lambda_powertools/event_handler/openapi/constants.py index c125e89d0e7..7c5b938920a 100644 --- a/aws_lambda_powertools/event_handler/openapi/constants.py +++ b/aws_lambda_powertools/event_handler/openapi/constants.py @@ -3,3 +3,4 @@ DEFAULT_OPENAPI_TITLE = "Powertools for AWS Lambda (Python) API" DEFAULT_CONTENT_TYPE = "application/json" DEFAULT_OPENAPI_RESPONSE_DESCRIPTION = "Successful Response" +DEFAULT_STATUS_CODE = 200 diff --git a/aws_lambda_powertools/event_handler/openapi/schema_generator.py b/aws_lambda_powertools/event_handler/openapi/schema_generator.py index 5d409693937..6334a3b53cc 100644 --- a/aws_lambda_powertools/event_handler/openapi/schema_generator.py +++ b/aws_lambda_powertools/event_handler/openapi/schema_generator.py @@ -36,6 +36,7 @@ from aws_lambda_powertools.event_handler.openapi.constants import ( DEFAULT_CONTENT_TYPE, DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + DEFAULT_STATUS_CODE, ) @@ -54,6 +55,7 @@ def generate_openapi_path( response_description: str | None, body_field: ModelField | None, custom_response_validation_http_code: HTTPStatus | None, + status_code: int = DEFAULT_STATUS_CODE, dependant: Dependant, operation_ids: set[str], model_name_map: dict[TypeModelOrEnum, str], @@ -108,6 +110,7 @@ def generate_openapi_path( responses=responses, response_description=response_description, custom_response_validation_http_code=custom_response_validation_http_code, + status_code=status_code, dependant=dependant, model_name_map=model_name_map, field_mapping=field_mapping, @@ -220,6 +223,7 @@ def _build_responses( responses: dict[int, OpenAPIResponse] | None, response_description: str | None, custom_response_validation_http_code: HTTPStatus | None, + status_code: int = DEFAULT_STATUS_CODE, dependant: Dependant, model_name_map: dict[TypeModelOrEnum, str], field_mapping: dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], @@ -237,9 +241,9 @@ def _build_responses( ) if responses: - for status_code in list(responses): - operation_responses[status_code] = _build_custom_response( - response=copy.deepcopy(responses[status_code]), + for resp_code in list(responses): + operation_responses[resp_code] = _build_custom_response( + response=copy.deepcopy(responses[resp_code]), dependant=dependant, model_name_map=model_name_map, field_mapping=field_mapping, @@ -251,7 +255,7 @@ def _build_responses( field_mapping=field_mapping, ) - operation_responses[200] = { + operation_responses[status_code] = { "description": response_description or DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, "content": {DEFAULT_CONTENT_TYPE: response_schema}, } diff --git a/docs/core/event_handler/_openapi_customization_operations.md b/docs/core/event_handler/_openapi_customization_operations.md index 0072ec1fae4..dbea969c99f 100644 --- a/docs/core/event_handler/_openapi_customization_operations.md +++ b/docs/core/event_handler/_openapi_customization_operations.md @@ -13,4 +13,5 @@ Here's a breakdown of various customizable fields: | `tags` | `List[str]` | Tags are a way to categorize and group endpoints within the API documentation. They can help organize the operations by resources or other heuristic. | | `operation_id` | `str` | A unique identifier for the operation, which can be used for referencing this operation in documentation or code. This ID must be unique across all operations described in the API. | | `include_in_schema` | `bool` | A boolean value that determines whether or not this operation should be included in the OpenAPI schema. Setting it to `False` can hide the endpoint from generated documentation and schema exports, which might be useful for private or experimental endpoints. | -| `deprecated` | `bool` | A boolean value that determines whether or not this operation should be marked as deprecated in the OpenAPI schema. | +| `deprecated` | `bool` | A boolean value that determines whether or not this operation should be marked as deprecated in the OpenAPI schema. | +| `status_code` | `int` | The default HTTP status code for successful responses. Defaults to `200`. This value is used both in the OpenAPI schema and as the actual response status code when the handler returns a dictionary or plain value (not a `Response` object or tuple). | diff --git a/docs/core/event_handler/openapi.md b/docs/core/event_handler/openapi.md index 5a4980fafec..d32797db1d7 100644 --- a/docs/core/event_handler/openapi.md +++ b/docs/core/event_handler/openapi.md @@ -73,7 +73,7 @@ To implement these customizations, include extra parameters when defining your r === "customizing_api_operations.py" - ```python hl_lines="11-20" + ```python hl_lines="11-20 29-36" --8<-- "examples/event_handler_rest/src/customizing_api_operations.py" ``` diff --git a/examples/event_handler_rest/src/customizing_api_operations.py b/examples/event_handler_rest/src/customizing_api_operations.py index e455fc7dadd..d7e9afeba6d 100644 --- a/examples/event_handler_rest/src/customizing_api_operations.py +++ b/examples/event_handler_rest/src/customizing_api_operations.py @@ -26,5 +26,17 @@ def get_todo_title(todo_id: int) -> str: return todo.json()["title"] +@app.post( + "/todos", + summary="Creates a new todo item", + description="Creates a new todo item and returns it", + response_description="The created todo object", + status_code=201, + tags=["Todos"], +) +def create_todo(title: str) -> dict: + return {"id": 1, "title": title} + + def lambda_handler(event: dict, context: LambdaContext) -> dict: return app.resolve(event, context) diff --git a/tests/functional/event_handler/_pydantic/test_api_gateway.py b/tests/functional/event_handler/_pydantic/test_api_gateway.py index ce3fd89e864..32a6e3c549d 100644 --- a/tests/functional/event_handler/_pydantic/test_api_gateway.py +++ b/tests/functional/event_handler/_pydantic/test_api_gateway.py @@ -80,3 +80,69 @@ def get_lambda(param: int): ... assert result["statusCode"] == 422 assert result["multiValueHeaders"]["Content-Type"] == [content_types.APPLICATION_JSON] assert "missing" in result["body"] + + +def test_route_custom_status_code_with_dict(): + # GIVEN a route with a custom status_code returning a dict + app = ApiGatewayResolver(enable_validation=True) + + @app.post("/my/path", status_code=201) + def create_item(): + return {"name": "test"} + + event = {"httpMethod": "POST", "path": "/my/path", "body": "{}"} + + # WHEN calling the event handler + result = app(event, {}) + + # THEN the response should use the route's custom status code + assert result["statusCode"] == 201 + + +def test_route_custom_status_code_tuple_override(): + # GIVEN a route with status_code=201 but handler returns a tuple with 202 + app = ApiGatewayResolver(enable_validation=True) + + @app.post("/my/path", status_code=201) + def create_item(): + return {"name": "test"}, 202 + + event = {"httpMethod": "POST", "path": "/my/path", "body": "{}"} + + # WHEN calling the event handler + result = app(event, {}) + + # THEN the tuple status code should override the route's status code + assert result["statusCode"] == 202 + + +def test_route_custom_status_code_response_object_override(): + # GIVEN a route with status_code=201 but handler returns a Response with 204 + app = ApiGatewayResolver(enable_validation=True) + + @app.post("/my/path", status_code=201) + def create_item(): + return Response(status_code=204, content_type=content_types.APPLICATION_JSON, body="{}") + + event = {"httpMethod": "POST", "path": "/my/path", "body": "{}"} + + # WHEN calling the event handler + result = app(event, {}) + + # THEN the Response object's status code should take precedence + assert result["statusCode"] == 204 + + +def test_route_default_status_code_with_dict(): + # GIVEN a route without custom status_code returning a dict + app = ApiGatewayResolver(enable_validation=True) + + @app.get("/my/path") + def get_items(): + return {"items": []} + + # WHEN calling the event handler + result = app(LOAD_GW_EVENT, {}) + + # THEN the response should default to 200 + assert result["statusCode"] == 200 diff --git a/tests/functional/event_handler/_pydantic/test_openapi_responses.py b/tests/functional/event_handler/_pydantic/test_openapi_responses.py index 71c7d186cbe..785d2b8416c 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_responses.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_responses.py @@ -370,3 +370,89 @@ def handler() -> UserResponse: assert "example2" in examples assert examples["example2"].summary == "Example 2" assert examples["example2"].value["id"] == 2 + + +def test_openapi_custom_status_code(): + # GIVEN a route with a custom status_code + app = APIGatewayRestResolver(enable_validation=True) + + class Item(BaseModel): + name: str + + @app.post("/items", status_code=201) + def create_item() -> Item: + return Item(name="test") + + # WHEN we retrieve the OpenAPI schema + schema = app.get_openapi_schema() + responses = schema.paths["/items"].post.responses + + # THEN the schema should use 201 as the success response code instead of 200 + assert 201 in responses + assert responses[201].description == "Successful Response" + assert 200 not in responses + + +def test_openapi_custom_status_code_with_description(): + # GIVEN a route with a custom status_code and response_description + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/items", status_code=201, response_description="Item created") + def create_item(): + return {"name": "test"} + + # WHEN we retrieve the OpenAPI schema + schema = app.get_openapi_schema() + responses = schema.paths["/items"].post.responses + + # THEN the schema should use 201 with the custom description + assert 201 in responses + assert responses[201].description == "Item created" + assert 200 not in responses + + +def test_openapi_default_status_code(): + # GIVEN a route without a custom status_code + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/items") + def get_items(): + return {"items": []} + + # WHEN we retrieve the OpenAPI schema + schema = app.get_openapi_schema() + responses = schema.paths["/items"].get.responses + + # THEN the schema should default to 200 + assert 200 in responses + assert responses[200].description == "Successful Response" + + +def test_openapi_custom_status_code_all_methods(): + # GIVEN routes with custom status_code on different HTTP methods + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/items", status_code=201) + def create(): + return {} + + @app.put("/items", status_code=204) + def update(): + return {} + + @app.delete("/items", status_code=204) + def delete(): + return {} + + @app.patch("/items", status_code=202) + def patch(): + return {} + + # WHEN we retrieve the OpenAPI schema + schema = app.get_openapi_schema() + + # THEN each method should have the correct custom status code + assert 201 in schema.paths["/items"].post.responses + assert 204 in schema.paths["/items"].put.responses + assert 204 in schema.paths["/items"].delete.responses + assert 202 in schema.paths["/items"].patch.responses From 8673edea27ac0165b1e24a4065c96e04bd28f96c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:11:17 +0800 Subject: [PATCH 46/84] chore(deps): bump cryptography from 46.0.6 to 46.0.7 (#8132) Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.6 to 46.0.7. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/46.0.6...46.0.7) --- updated-dependencies: - dependency-name: cryptography dependency-version: 46.0.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 107 ++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/poetry.lock b/poetry.lock index f5445bb54a2..28fd37d775e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1041,6 +1041,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"}, @@ -1127,7 +1128,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\""} @@ -1468,63 +1468,62 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" -version = "46.0.6" +version = "46.0.7" 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" groups = ["main", "dev"] files = [ - {file = "cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19"}, - {file = "cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738"}, - {file = "cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c"}, - {file = "cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f"}, - {file = "cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2"}, - {file = "cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124"}, - {file = "cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4"}, - {file = "cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a"}, - {file = "cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d"}, - {file = "cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736"}, - {file = "cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed"}, - {file = "cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4"}, - {file = "cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa"}, - {file = "cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58"}, - {file = "cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb"}, - {file = "cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72"}, - {file = "cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c"}, - {file = "cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f"}, - {file = "cryptography-46.0.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead"}, - {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8"}, - {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0"}, - {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b"}, - {file = "cryptography-46.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a"}, - {file = "cryptography-46.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e"}, - {file = "cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759"}, + {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"}, ] -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\""} @@ -1537,7 +1536,7 @@ 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.6)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +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]] @@ -3395,11 +3394,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 f06db0a1df157d6f66efb59940dc681805a008d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:24:57 +0200 Subject: [PATCH 47/84] chore(deps-dev): bump aws-cdk from 2.1117.0 to 2.1118.0 in the aws-cdk group (#8142) 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.1117.0 to 2.1118.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1118.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1118.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> --- 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 28f81e58656..faae155108c 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.1117.0" + "aws-cdk": "^2.1118.0" } }, "node_modules/aws-cdk": { - "version": "2.1117.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1117.0.tgz", - "integrity": "sha512-2NbSDDw8LTkGv0uhEDffttmNvgyTAWV5EkLkyPUGAGECzBdwCmbgmRxSoUhbzxZ0XEd1eaqbdVTFRWgtsbj31g==", + "version": "2.1118.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1118.0.tgz", + "integrity": "sha512-Tfd865GRewDTXIbTVtix/l+v8t3rZENvdHcQQZS2wXYVXfHzljULFXe9JKkgZUNDPB1zo9tSBUu8jjiHRm7nWg==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 2c97f75843e..2820cd2f584 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.1117.0" + "aws-cdk": "^2.1118.0" } } From 6bcb8a33782df51033958f55aabb69b2b41a722b Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 14 Apr 2026 11:06:45 +0200 Subject: [PATCH 48/84] chore: bump dependabot dependencies. (#8152) * chore(deps): bump the github-actions group with 5 updates Bumps the github-actions group with 5 updates: | Package | From | To | | --- | --- | --- | | [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) | `6.0.0` | `6.1.0` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` | | [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) | `1.13.0` | `1.14.0` | | [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) | `7.1.1` | `7.2.0` | | [actions/github-script](https://github.com/actions/github-script) | `8.0.0` | `9.0.0` | Updates `aws-actions/configure-aws-credentials` from 6.0.0 to 6.1.0 - [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/8df5847569e6427dd6c4fb1cf565c83acfa8afa7...ec61189d14ec14c8efccab744f656cffd0e33f37) Updates `actions/upload-artifact` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a) Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e...cef221092ed1bacb1cc03d23a2d87d1d172e277b) Updates `release-drafter/release-drafter` from 7.1.1 to 7.2.0 - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/139054aeaa9adc52ab36ddf67437541f039b88e2...5de93583980a40bd78603b6dfdcda5b4df377b32) Updates `actions/github-script` from 8.0.0 to 9.0.0 - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/ed597411d8f924073f98dfc5c65a23a2325f34cd...3a2844b7e9c422d3c10d287c895573f7108da1b3) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/upload-artifact dependency-version: 7.0.1 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.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: release-drafter/release-drafter dependency-version: 7.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/github-script dependency-version: 9.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump the dev-dependencies group with 3 updates Bumps the dev-dependencies group with 3 updates: [pytest](https://github.com/pytest-dev/pytest), [mypy](https://github.com/python/mypy) and [ruff](https://github.com/astral-sh/ruff). Updates `pytest` from 9.0.2 to 9.0.3 - [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.0.2...9.0.3) Updates `mypy` from 1.20.0 to 1.20.1 - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.20.0...v1.20.1) Updates `ruff` from 0.15.9 to 0.15.10 - [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.9...0.15.10) --- updated-dependencies: - dependency-name: pytest dependency-version: 9.0.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: mypy dependency-version: 1.20.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: ruff dependency-version: 0.15.10 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump nox from 2026.2.9 to 2026.4.10 Bumps [nox](https://github.com/wntrblm/nox) from 2026.2.9 to 2026.4.10. - [Release notes](https://github.com/wntrblm/nox/releases) - [Changelog](https://github.com/wntrblm/nox/blob/main/CHANGELOG.md) - [Commits](https://github.com/wntrblm/nox/compare/2026.02.09...2026.04.10) --- updated-dependencies: - dependency-name: nox dependency-version: 2026.4.10 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump types-python-dateutil Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.9.0.20260402 to 2.9.0.20260408. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-python-dateutil dependency-version: 2.9.0.20260408 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump ty from 0.0.27 to 0.0.29 Bumps [ty](https://github.com/astral-sh/ty) from 0.0.27 to 0.0.29. - [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.27...0.0.29) --- updated-dependencies: - dependency-name: ty dependency-version: 0.0.29 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump aws-cdk-lib from 2.248.0 to 2.249.0 Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.248.0 to 2.249.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.248.0...v2.249.0) --- updated-dependencies: - dependency-name: aws-cdk-lib dependency-version: 2.249.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump pytest from 7.4.4 to 9.0.3 in /layer_v3 Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.4 to 9.0.3. - [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/7.4.4...9.0.3) --- updated-dependencies: - dependency-name: pytest dependency-version: 9.0.3 dependency-type: direct:development ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump pytest from 9.0.2 to 9.0.3 Bumps [pytest](https://github.com/pytest-dev/pytest) from 9.0.2 to 9.0.3. - [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.0.2...9.0.3) --- updated-dependencies: - dependency-name: pytest dependency-version: 9.0.3 dependency-type: direct:development ... Signed-off-by: dependabot[bot] * fix(ci): correct configure-aws-credentials version comment from v4.3.0 to v6.1.0 The Dependabot PR updated the SHA pin correctly but kept the stale version comment. This fixes all workflow files to reflect the actual version (6.1.0). Co-Authored-By: Claude Opus 4.6 * chore: regenerate poetry.lock to fix content-hash mismatch After merging multiple Dependabot PRs the content-hash in poetry.lock was stale. Regenerated with `poetry lock` to match pyproject.toml. 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 | 4 +- .github/workflows/layer_govcloud.yml | 10 +- .../workflows/layer_govcloud_python313.yml | 10 +- .github/workflows/layer_govcloud_verify.yml | 6 +- .github/workflows/layers_partition_verify.yml | 8 +- .github/workflows/layers_partitions.yml | 14 +- .github/workflows/ossf_scorecard.yml | 2 +- .github/workflows/pre-release.yml | 2 +- .github/workflows/publish_v3_layer.yml | 2 +- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release-v3.yml | 6 +- .../reusable_deploy_v3_layer_stack.yml | 4 +- .github/workflows/reusable_deploy_v3_sar.yml | 4 +- .github/workflows/reusable_publish_docs.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- .github/workflows/update_ssm.yml | 2 +- layer_v3/poetry.lock | 40 +++- layer_v3/pyproject.toml | 2 +- poetry.lock | 218 +++++++++--------- pyproject.toml | 4 +- 20 files changed, 179 insertions(+), 165 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index f7964960315..ab10d310b0e 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@828e78a26eee3554dc2e1d96048004548fbb169f - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 with: aws-region: ${{ inputs.region }} role-to-assume: ${{ secrets.REGION_IAM_ROLE }} @@ -96,7 +96,7 @@ jobs: steps: - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-region: us-east-1 role-to-assume: ${{ secrets.REGION_IAM_ROLE }} diff --git a/.github/workflows/layer_govcloud.yml b/.github/workflows/layer_govcloud.yml index 6106e538a09..0ce1b7af356 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -70,14 +70,14 @@ jobs: aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }} --query 'Content.Location' | xargs curl -L -o ${{ matrix.layer }}_${{ matrix.arch }}.zip aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }} > ${{ matrix.layer }}_${{ matrix.arch }}.json - name: Store Zip - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.zip path: ${{ matrix.layer }}_${{ matrix.arch }}.zip retention-days: 1 if-no-files-found: error - name: Store Metadata - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.json path: ${{ matrix.layer }}_${{ matrix.arch }}.json @@ -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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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 c55c3123f3e..6f7c6a94d38 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -65,14 +65,14 @@ jobs: aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }} --query 'Content.Location' | xargs curl -L -o ${{ matrix.layer }}_${{ matrix.arch }}.zip aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }} > ${{ matrix.layer }}_${{ matrix.arch }}.json - name: Store Zip - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.zip path: ${{ matrix.layer }}_${{ matrix.arch }}.zip retention-days: 1 if-no-files-found: error - name: Store Metadata - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}_${{ matrix.arch }}.json path: ${{ matrix.layer }}_${{ matrix.arch }}.json @@ -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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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 b6434ab026c..3cce653182e 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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 acac8bbeceb..c1d72353898 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -98,7 +98,7 @@ jobs: run: | aws --region us-east-1 lambda get-layer-version-by-arn --arn 'arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }}' > '${{ matrix.layer }}-${{ matrix.arch }}.json' - name: Store Metadata - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}-${{ matrix.arch }}.json path: ${{ matrix.layer }}-${{ matrix.arch }}.json @@ -107,7 +107,7 @@ jobs: verify: name: Verify - needs: + needs: - setup - commercial runs-on: ubuntu-latest @@ -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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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 2da5ec66e38..caceb773dc6 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -95,14 +95,14 @@ jobs: aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }} --query 'Content.Location' | xargs curl -L -o ${{ matrix.layer }}-${{ matrix.arch }}.zip aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }} > ${{ matrix.layer }}-${{ matrix.arch }}.json - name: Store Zip - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}-${{ matrix.arch }}.zip path: ${{ matrix.layer }}-${{ matrix.arch }}.zip retention-days: 1 if-no-files-found: error - name: Store Metadata - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}-${{ matrix.arch }}.json path: ${{ matrix.layer }}-${{ matrix.arch }}.json @@ -111,7 +111,7 @@ jobs: copy: name: Copy - needs: + needs: - setup - download runs-on: ubuntu-latest @@ -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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }} aws-region: ${{ matrix.region}} @@ -160,7 +160,7 @@ jobs: id: create-layer run: | cat '${{ matrix.layer }}-${{ matrix.arch }}.json' | jq '{"LayerName": "${{ matrix.layer }}-${{ matrix.arch }}", "Description": .Description, "CompatibleRuntimes": .CompatibleRuntimes, "CompatibleArchitectures": .CompatibleArchitectures, "LicenseInfo": .LicenseInfo}' > input.json - + LAYER_VERSION=$(aws --region ${{ matrix.region}} lambda publish-layer-version \ --zip-file 'fileb://./${{ matrix.layer }}-${{ matrix.arch }}.zip' \ --cli-input-json file://./input.json \ @@ -187,7 +187,7 @@ jobs: jq -s -r '["Layer Arn", "Runtimes", "Version", "Description", "SHA256"], ([.[0], .[1]] | .[] | [.LayerArn, (.CompatibleRuntimes | join("/")), .Version, .Description, .Content.CodeSha256]) |@tsv' '${{ matrix.layer }}-${{ matrix.arch }}.json' $layer_output | column -t -s $'\t' - name: Store Metadata - ${{ matrix.region }} - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.layer }}-${{ matrix.arch }}-${{ matrix.region }}.json path: ${{ matrix.layer }}-${{ matrix.arch }}-${{ matrix.region }}.json diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index 5045dc11327..3c6e87ab8c7 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -35,7 +35,7 @@ jobs: repo_token: ${{ secrets.SCORECARD_TOKEN }} # read-only fine-grained token to read branch protection settings - name: "Upload results" - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: SARIF file path: results.sarif diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index f638a77e62d..07cf205ba20 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@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 # 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/publish_v3_layer.yml b/.github/workflows/publish_v3_layer.yml index a4884039c5e..200e850675f 100644 --- a/.github/workflows/publish_v3_layer.yml +++ b/.github/workflows/publish_v3_layer.yml @@ -169,7 +169,7 @@ jobs: - name: zip output run: zip -r cdk.py${{ matrix.python-version }}.out.zip cdk.out - name: Archive CDK artifacts - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: cdk-layer-artifact-py${{ matrix.python-version }} path: layer_v3/cdk.py${{ matrix.python-version }}.out.zip diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 6e13b235559..c6b23774277 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@139054aeaa9adc52ab36ddf67437541f039b88e2 # v7.1.1 + - uses: release-drafter/release-drafter@5de93583980a40bd78603b6dfdcda5b4df377b32 # v7.2.0 diff --git a/.github/workflows/release-v3.yml b/.github/workflows/release-v3.yml index 5b36d1018fd..64099e11413 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@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 # 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@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + # uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 # with: # repository-url: https://test.pypi.org/legacy/ @@ -377,7 +377,7 @@ jobs: integrity_hash: ${{ needs.seal.outputs.integrity_hash }} artifact_name: ${{ needs.seal.outputs.artifact_name }} - name: Close issues related to this release - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index 9d8d12e928a..8112b19d953 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} @@ -209,7 +209,7 @@ jobs: cat cdk-layer-stack/${{steps.constants.outputs.LAYER_VERSION}} - name: Save Layer ARN artifact if: ${{ inputs.stage == 'PROD' }} - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: cdk-layer-stack-${{ matrix.region }}-${{ matrix.python-version }} path: ./layer_v3/cdk-layer-stack/* # NOTE: upload-artifact does not inherit working-directory setting. diff --git a/.github/workflows/reusable_deploy_v3_sar.yml b/.github/workflows/reusable_deploy_v3_sar.yml index 6b76d27578e..17f63216996 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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 83771abb145..683992f4ac4 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -68,7 +68,7 @@ jobs: env: BRANCH: ${{ inputs.git_ref }} - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 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 812148974fc..6a1e861d3de 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -72,7 +72,7 @@ jobs: - name: Install dependencies run: make dev-quality-code - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: role-to-assume: ${{ secrets.AWS_TEST_ROLE_ARN }} aws-region: ${{ env.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/update_ssm.yml b/.github/workflows/update_ssm.yml index 78aff7e8172..994f1fb7685 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@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v4.3.0 + uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets[format('{0}', steps.transform.outputs.CONVERTED_REGION)] }} diff --git a/layer_v3/poetry.lock b/layer_v3/poetry.lock index 7ab9c82dc68..283262858e7 100644 --- a/layer_v3/poetry.lock +++ b/layer_v3/poetry.lock @@ -305,28 +305,44 @@ files = [ {file = "publication-0.0.3.tar.gz", hash = "sha256:68416a0de76dddcdd2930d1c8ef853a743cc96c82416c4e4d3b5d901c6276dc4"}, ] +[[package]] +name = "pygments" +version = "2.20.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + [[package]] name = "pytest" -version = "7.4.4" +version = "9.0.3" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, + {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, ] [package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1.0.1" +packaging = ">=22" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] [[package]] name = "python-dateutil" @@ -479,4 +495,4 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [metadata] lock-version = "2.1" python-versions = "^3.10" -content-hash = "3dc6a5fee955e5a822626957f89f37c55b1e0adc6fbf61267357edb26a944d7c" +content-hash = "55e0062a4839c65fd80947421f94e712530dda1c9dd1aed9954d75a73b882fd9" diff --git a/layer_v3/pyproject.toml b/layer_v3/pyproject.toml index 5dffa424144..fd67c31419d 100644 --- a/layer_v3/pyproject.toml +++ b/layer_v3/pyproject.toml @@ -11,7 +11,7 @@ python = "^3.10" aws-cdk-lib = "^2.223.0" [tool.poetry.group.dev.dependencies] -pytest = "^7.1.2" +pytest = ">=7.1.2,<10.0.0" boto3 = "^1.24.46" urllib3 = ">=1.25.4,!=2.2.0,<3" diff --git a/poetry.lock b/poetry.lock index 28fd37d775e..649b08915ab 100644 --- a/poetry.lock +++ b/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.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" @@ -241,14 +241,14 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.248.0" +version = "2.249.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.248.0-py3-none-any.whl", hash = "sha256:e89db288365371e6b42aaae8b45ad2064615dfbe87e95741a2f2bb7ec1f33dad"}, - {file = "aws_cdk_lib-2.248.0.tar.gz", hash = "sha256:a00c73bfa6865ef62d700d6f97dd4124979ccfe69dc1ef70f2526aa49c52bbc8"}, + {file = "aws_cdk_lib-2.249.0-py3-none-any.whl", hash = "sha256:c36a7891027c6252479b26ddb3e21bdc54d1fdf403c7928c8da6e8040e4674fa"}, + {file = "aws_cdk_lib-2.249.0.tar.gz", hash = "sha256:7a4c27b3b22253c099696e54dc6cdd193b718c8d43fd692f91c820921a15dc6e"}, ] [package.dependencies] @@ -325,7 +325,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"}, @@ -1041,7 +1041,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"}, @@ -1128,6 +1127,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 = "platform_python_implementation != \"PyPy\" and (extra == \"all\" or extra == \"datamasking\")", dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1524,6 +1524,7 @@ files = [ {file = "cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4"}, {file = "cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5"}, ] +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\""} @@ -1833,7 +1834,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"}, @@ -1915,7 +1916,6 @@ 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] @@ -1934,7 +1934,6 @@ 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] @@ -1950,7 +1949,6 @@ python-versions = ">=3.10" groups = ["dev"] files = [ {file = "griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f"}, - {file = "griffelib-2.0.0.tar.gz", hash = "sha256:e504d637a089f5cab9b5daf18f7645970509bf4f53eda8d79ed71cce8bd97934"}, ] [package.extras] @@ -2914,56 +2912,56 @@ dill = ">=0.4.1" [[package]] name = "mypy" -version = "1.20.0" +version = "1.20.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mypy-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8"}, - {file = "mypy-1.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a"}, - {file = "mypy-1.20.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865"}, - {file = "mypy-1.20.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca"}, - {file = "mypy-1.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018"}, - {file = "mypy-1.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13"}, - {file = "mypy-1.20.0-cp310-cp310-win_arm64.whl", hash = "sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281"}, - {file = "mypy-1.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b"}, - {file = "mypy-1.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367"}, - {file = "mypy-1.20.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62"}, - {file = "mypy-1.20.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0"}, - {file = "mypy-1.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f"}, - {file = "mypy-1.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e"}, - {file = "mypy-1.20.0-cp311-cp311-win_arm64.whl", hash = "sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442"}, - {file = "mypy-1.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214"}, - {file = "mypy-1.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e"}, - {file = "mypy-1.20.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651"}, - {file = "mypy-1.20.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5"}, - {file = "mypy-1.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78"}, - {file = "mypy-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489"}, - {file = "mypy-1.20.0-cp312-cp312-win_arm64.whl", hash = "sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33"}, - {file = "mypy-1.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134"}, - {file = "mypy-1.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c"}, - {file = "mypy-1.20.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe"}, - {file = "mypy-1.20.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f"}, - {file = "mypy-1.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726"}, - {file = "mypy-1.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69"}, - {file = "mypy-1.20.0-cp313-cp313-win_arm64.whl", hash = "sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e"}, - {file = "mypy-1.20.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948"}, - {file = "mypy-1.20.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5"}, - {file = "mypy-1.20.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188"}, - {file = "mypy-1.20.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83"}, - {file = "mypy-1.20.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2"}, - {file = "mypy-1.20.0-cp314-cp314-win_amd64.whl", hash = "sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732"}, - {file = "mypy-1.20.0-cp314-cp314-win_arm64.whl", hash = "sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef"}, - {file = "mypy-1.20.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1"}, - {file = "mypy-1.20.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436"}, - {file = "mypy-1.20.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6"}, - {file = "mypy-1.20.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526"}, - {file = "mypy-1.20.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787"}, - {file = "mypy-1.20.0-cp314-cp314t-win_amd64.whl", hash = "sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb"}, - {file = "mypy-1.20.0-cp314-cp314t-win_arm64.whl", hash = "sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd"}, - {file = "mypy-1.20.0-py3-none-any.whl", hash = "sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e"}, - {file = "mypy-1.20.0.tar.gz", hash = "sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3"}, + {file = "mypy-1.20.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3ba5d1e712ada9c3b6223dcbc5a31dac334ed62991e5caa17bcf5a4ddc349af0"}, + {file = "mypy-1.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e731284c117b0987fb1e6c5013a56f33e7faa1fce594066ab83876183ce1c66"}, + {file = "mypy-1.20.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f8e945b872a05f4fbefabe2249c0b07b6b194e5e11a86ebee9edf855de09806c"}, + {file = "mypy-1.20.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fc88acef0dc9b15246502b418980478c1bfc9702057a0e1e7598d01a7af8937"}, + {file = "mypy-1.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:14911a115c73608f155f648b978c5055d16ff974e6b1b5512d7fedf4fa8b15c6"}, + {file = "mypy-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:76d9b4c992cca3331d9793ef197ae360ea44953cf35beb2526e95b9e074f2866"}, + {file = "mypy-1.20.1-cp310-cp310-win_arm64.whl", hash = "sha256:b408722f80be44845da555671a5ef3a0c63f51ca5752b0c20e992dc9c0fbd3cd"}, + {file = "mypy-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c01eb9bac2c6a962d00f9d23421cd2913840e65bba365167d057bd0b4171a92e"}, + {file = "mypy-1.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55d12ddbd8a9cac5b276878bd534fa39fff5bf543dc6ae18f25d30c8d7d27fca"}, + {file = "mypy-1.20.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0aa322c1468b6cdfc927a44ce130f79bb44bcd34eb4a009eb9f96571fd80955"}, + {file = "mypy-1.20.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3f8bc95899cf676b6e2285779a08a998cc3a7b26f1026752df9d2741df3c79e8"}, + {file = "mypy-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:47c2b90191a870a04041e910277494b0d92f0711be9e524d45c074fe60c00b65"}, + {file = "mypy-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:9857dc8d2ec1a392ffbda518075beb00ac58859979c79f9e6bdcb7277082c2f2"}, + {file = "mypy-1.20.1-cp311-cp311-win_arm64.whl", hash = "sha256:09d8df92bb25b6065ab91b178da843dda67b33eb819321679a6e98a907ce0e10"}, + {file = "mypy-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:36ee2b9c6599c230fea89bbd79f401f9f9f8e9fcf0c777827789b19b7da90f51"}, + {file = "mypy-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fba3fb0968a7b48806b0c90f38d39296f10766885a94c83bd21399de1e14eb28"}, + {file = "mypy-1.20.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef1415a637cd3627d6304dfbeddbadd21079dafc2a8a753c477ce4fc0c2af54f"}, + {file = "mypy-1.20.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef3461b1ad5cd446e540016e90b5984657edda39f982f4cc45ca317b628f5a37"}, + {file = "mypy-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:542dd63c9e1339b6092eb25bd515f3a32a1453aee8c9521d2ddb17dacd840237"}, + {file = "mypy-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:1d55c7cd8ca22e31f93af2a01160a9e95465b5878de23dba7e48116052f20a8d"}, + {file = "mypy-1.20.1-cp312-cp312-win_arm64.whl", hash = "sha256:f5b84a79070586e0d353ee07b719d9d0a4aa7c8ee90c0ea97747e98cbe193019"}, + {file = "mypy-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f3886c03e40afefd327bd70b3f634b39ea82e87f314edaa4d0cce4b927ddcc1"}, + {file = "mypy-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e860eb3904f9764e83bafd70c8250bdffdc7dde6b82f486e8156348bf7ceb184"}, + {file = "mypy-1.20.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4b5aac6e785719da51a84f5d09e9e843d473170a9045b1ea7ea1af86225df4b"}, + {file = "mypy-1.20.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f37b6cd0fe2ad3a20f05ace48ca3523fc52ff86940e34937b439613b6854472e"}, + {file = "mypy-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4bbb0f6b54ce7cc350ef4a770650d15fa70edd99ad5267e227133eda9c94218"}, + {file = "mypy-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:c3dc20f8ec76eecd77148cdd2f1542ed496e51e185713bf488a414f862deb8f2"}, + {file = "mypy-1.20.1-cp313-cp313-win_arm64.whl", hash = "sha256:a9d62bbac5d6d46718e2b0330b25e6264463ed832722b8f7d4440ff1be3ca895"}, + {file = "mypy-1.20.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:12927b9c0ed794daedcf1dab055b6c613d9d5659ac511e8d936d96f19c087d12"}, + {file = "mypy-1.20.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:752507dd481e958b2c08fc966d3806c962af5a9433b5bf8f3bdd7175c20e34fe"}, + {file = "mypy-1.20.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c614655b5a065e56274c6cbbe405f7cf7e96c0654db7ba39bc680238837f7b08"}, + {file = "mypy-1.20.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2c3f6221a76f34d5100c6d35b3ef6b947054123c3f8d6938a4ba00b1308aa572"}, + {file = "mypy-1.20.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4bdfc06303ac06500af71ea0cdbe995c502b3c9ba32f3f8313523c137a25d1b6"}, + {file = "mypy-1.20.1-cp314-cp314-win_amd64.whl", hash = "sha256:0131edd7eba289973d1ba1003d1a37c426b85cdef76650cd02da6420898a5eb3"}, + {file = "mypy-1.20.1-cp314-cp314-win_arm64.whl", hash = "sha256:33f02904feb2c07e1fdf7909026206396c9deeb9e6f34d466b4cfedb0aadbbe4"}, + {file = "mypy-1.20.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:168472149dd8cc505c98cefd21ad77e4257ed6022cd5ed2fe2999bed56977a5a"}, + {file = "mypy-1.20.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:eb674600309a8f22790cca883a97c90299f948183ebb210fbef6bcee07cb1986"}, + {file = "mypy-1.20.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef2b2e4cc464ba9795459f2586923abd58a0055487cbe558cb538ea6e6bc142a"}, + {file = "mypy-1.20.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dee461d396dd46b3f0ed5a098dbc9b8860c81c46ad44fa071afcfbc149f167c9"}, + {file = "mypy-1.20.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e364926308b3e66f1361f81a566fc1b2f8cd47fc8525e8136d4058a65a4b4f02"}, + {file = "mypy-1.20.1-cp314-cp314t-win_amd64.whl", hash = "sha256:a0c17fbd746d38c70cbc42647cfd884f845a9708a4b160a8b4f7e70d41f4d7fa"}, + {file = "mypy-1.20.1-cp314-cp314t-win_arm64.whl", hash = "sha256:db2cb89654626a912efda69c0d5c1d22d948265e2069010d3dde3abf751c7d08"}, + {file = "mypy-1.20.1-py3-none-any.whl", hash = "sha256:1aae28507f253fe82d883790d1c0a0d35798a810117c88184097fe8881052f06"}, + {file = "mypy-1.20.1.tar.gz", hash = "sha256:6fc3f4ecd52de81648fed1945498bf42fa2993ddfad67c9056df36ae5757f804"}, ] [package.dependencies] @@ -3229,14 +3227,14 @@ test-extras = ["pytest-mpl", "pytest-randomly"] [[package]] name = "nox" -version = "2026.2.9" +version = "2026.4.10" description = "Flexible test automation." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "nox-2026.2.9-py3-none-any.whl", hash = "sha256:1b7143bc8ecdf25f2353201326152c5303ae4ae56ca097b1fb6179ad75164c47"}, - {file = "nox-2026.2.9.tar.gz", hash = "sha256:1bc8a202ee8cd69be7aaada63b2a7019126899a06fc930a7aee75585bf8ee41b"}, + {file = "nox-2026.4.10-py3-none-any.whl", hash = "sha256:082c117627590d9b90aa21f86df89b310b07c5842539524203bcb3c719f116c1"}, + {file = "nox-2026.4.10.tar.gz", hash = "sha256:2d0af5374f3f37a295428c927d1b04a8182aa01762897d172446dda2f1ce9692"}, ] [package.dependencies] @@ -3251,7 +3249,7 @@ virtualenv = {version = ">=20.15", markers = "python_version >= \"3.10\""} [package.extras] pbs = ["pbs-installer[all] (>=2025.1.6)"] -tox-to-nox = ["importlib-resources ; python_version < \"3.9\"", "jinja2", "tox (>=4)"] +tox-to-nox = ["jinja2", "tox (>=4)"] uv = ["uv (>=0.1.6)"] [[package]] @@ -3394,11 +3392,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" @@ -3411,7 +3409,7 @@ files = [ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3553,7 +3551,7 @@ files = [ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -3619,14 +3617,14 @@ extra = ["pygments (>=2.19.1)"] [[package]] name = "pytest" -version = "9.0.2" +version = "9.0.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b"}, - {file = "pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11"}, + {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, + {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, ] [package.dependencies] @@ -4303,30 +4301,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.9" +version = "0.15.10" 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.9-py3-none-linux_armv6l.whl", hash = "sha256:6efbe303983441c51975c243e26dff328aca11f94b70992f35b093c2e71801e1"}, - {file = "ruff-0.15.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4965bac6ac9ea86772f4e23587746f0b7a395eccabb823eb8bfacc3fa06069f7"}, - {file = "ruff-0.15.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf05aad70ca5b5a0a4b0e080df3a6b699803916d88f006efd1f5b46302daab8"}, - {file = "ruff-0.15.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9439a342adb8725f32f92732e2bafb6d5246bd7a5021101166b223d312e8fc59"}, - {file = "ruff-0.15.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c5e6faf9d97c8edc43877c3f406f47446fc48c40e1442d58cfcdaba2acea745"}, - {file = "ruff-0.15.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b34a9766aeec27a222373d0b055722900fbc0582b24f39661aa96f3fe6ad901"}, - {file = "ruff-0.15.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89dd695bc72ae76ff484ae54b7e8b0f6b50f49046e198355e44ea656e521fef9"}, - {file = "ruff-0.15.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce187224ef1de1bd225bc9a152ac7102a6171107f026e81f317e4257052916d5"}, - {file = "ruff-0.15.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b0c7c341f68adb01c488c3b7d4b49aa8ea97409eae6462d860a79cf55f431b6"}, - {file = "ruff-0.15.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:55cc15eee27dc0eebdfcb0d185a6153420efbedc15eb1d38fe5e685657b0f840"}, - {file = "ruff-0.15.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6537f6eed5cda688c81073d46ffdfb962a5f29ecb6f7e770b2dc920598997ed"}, - {file = "ruff-0.15.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6d3fcbca7388b066139c523bda744c822258ebdcfbba7d24410c3f454cc9af71"}, - {file = "ruff-0.15.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:058d8e99e1bfe79d8a0def0b481c56059ee6716214f7e425d8e737e412d69677"}, - {file = "ruff-0.15.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8e1ddb11dbd61d5983fa2d7d6370ef3eb210951e443cace19594c01c72abab4c"}, - {file = "ruff-0.15.9-py3-none-win32.whl", hash = "sha256:bde6ff36eaf72b700f32b7196088970bf8fdb2b917b7accd8c371bfc0fd573ec"}, - {file = "ruff-0.15.9-py3-none-win_amd64.whl", hash = "sha256:45a70921b80e1c10cf0b734ef09421f71b5aa11d27404edc89d7e8a69505e43d"}, - {file = "ruff-0.15.9-py3-none-win_arm64.whl", hash = "sha256:0694e601c028fd97dc5c6ee244675bc241aeefced7ef80cd9c6935a871078f53"}, - {file = "ruff-0.15.9.tar.gz", hash = "sha256:29cbb1255a9797903f6dde5ba0188c707907ff44a9006eb273b5a17bfa0739a2"}, + {file = "ruff-0.15.10-py3-none-linux_armv6l.whl", hash = "sha256:0744e31482f8f7d0d10a11fcbf897af272fefdfcb10f5af907b18c2813ff4d5f"}, + {file = "ruff-0.15.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b1e7c16ea0ff5a53b7c2df52d947e685973049be1cdfe2b59a9c43601897b22e"}, + {file = "ruff-0.15.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93cc06a19e5155b4441dd72808fdf84290d84ad8a39ca3b0f994363ade4cebb1"}, + {file = "ruff-0.15.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e1dd04312997c99ea6965df66a14fb4f03ba978564574ffc68b0d61fd3989e"}, + {file = "ruff-0.15.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8154d43684e4333360fedd11aaa40b1b08a4e37d8ffa9d95fee6fa5b37b6fab1"}, + {file = "ruff-0.15.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ab88715f3a6deb6bde6c227f3a123410bec7b855c3ae331b4c006189e895cef"}, + {file = "ruff-0.15.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a768ff5969b4f44c349d48edf4ab4f91eddb27fd9d77799598e130fb628aa158"}, + {file = "ruff-0.15.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ee3ef42dab7078bda5ff6a1bcba8539e9857deb447132ad5566a038674540d0"}, + {file = "ruff-0.15.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51cb8cc943e891ba99989dd92d61e29b1d231e14811db9be6440ecf25d5c1609"}, + {file = "ruff-0.15.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e59c9bdc056a320fb9ea1700a8d591718b8faf78af065484e801258d3a76bc3f"}, + {file = "ruff-0.15.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:136c00ca2f47b0018b073f28cb5c1506642a830ea941a60354b0e8bc8076b151"}, + {file = "ruff-0.15.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b80a2f3c9c8a950d6237f2ca12b206bccff626139be9fa005f14feb881a1ae8"}, + {file = "ruff-0.15.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e3e53c588164dc025b671c9df2462429d60357ea91af7e92e9d56c565a9f1b07"}, + {file = "ruff-0.15.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b0c52744cf9f143a393e284125d2576140b68264a93c6716464e129a3e9adb48"}, + {file = "ruff-0.15.10-py3-none-win32.whl", hash = "sha256:d4272e87e801e9a27a2e8df7b21011c909d9ddd82f4f3281d269b6ba19789ca5"}, + {file = "ruff-0.15.10-py3-none-win_amd64.whl", hash = "sha256:28cb32d53203242d403d819fd6983152489b12e4a3ae44993543d6fe62ab42ed"}, + {file = "ruff-0.15.10-py3-none-win_arm64.whl", hash = "sha256:601d1610a9e1f1c2165a4f561eeaa2e2ea1e97f3287c5aa258d3dab8b57c6188"}, + {file = "ruff-0.15.10.tar.gz", hash = "sha256:d1f86e67ebfdef88e00faefa1552b5e510e1d35f3be7d423dc7e84e63788c94e"}, ] [[package]] @@ -4622,29 +4620,29 @@ files = [ [[package]] name = "ty" -version = "0.0.27" +version = "0.0.29" description = "An extremely fast Python type checker, written in Rust." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "ty-0.0.27-py3-none-linux_armv6l.whl", hash = "sha256:eb14456b8611c9e8287aa9b633f4d2a0d9f3082a31796969e0b50bdda8930281"}, - {file = "ty-0.0.27-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:02e662184703db7586118df611cf24a000d35dae38d950053d1dd7b6736fd2c4"}, - {file = "ty-0.0.27-py3-none-macosx_11_0_arm64.whl", hash = "sha256:be5fc2899441f7f8f7ef40f9ffd006075a5ff6b06c44e8d2aa30e1b900c12f51"}, - {file = "ty-0.0.27-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30231e652b14742a76b64755e54bf0cb1cd4c128bcaf625222e0ca92a2094887"}, - {file = "ty-0.0.27-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a119b1168f64261b3205a37e40b5b6c4aac8fd58e4587988f4e4b22c3c79847"}, - {file = "ty-0.0.27-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e38f4e187b6975d2cbebf0f1eb1221f8f64f6e509bad14d7bb2a91afc97e4956"}, - {file = "ty-0.0.27-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a07b1a8fbb23844f6d22091275430d9ac617175f34aa99159b268193de210389"}, - {file = "ty-0.0.27-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3ec4033031f240836bb0337274bac5c49dde312c7c6d7575451ed719bf8ffa3"}, - {file = "ty-0.0.27-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:924a8849afd500d260bf5b7296165a05b7424fbb6b19113f30f3b999d682873f"}, - {file = "ty-0.0.27-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d8270026c07e7423a1b3a3fd065b46ed1478748f0662518b523b57744f3fa025"}, - {file = "ty-0.0.27-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e26e9735d3bdfd95d881111ad1cf570eab8188d8c3be36d6bcaad044d38984d8"}, - {file = "ty-0.0.27-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7c09cc9a699810609acc0090af8d0db68adaee6e60a7c3e05ab80cc954a83db7"}, - {file = "ty-0.0.27-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2d3e02853bb037221a456e034b1898aaa573e6374fbb53884e33cb7513ccb85a"}, - {file = "ty-0.0.27-py3-none-win32.whl", hash = "sha256:34e7377f2047c14dbbb7bf5322e84114db7a5f2cb470db6bee63f8f3550cfc1e"}, - {file = "ty-0.0.27-py3-none-win_amd64.whl", hash = "sha256:3f7e4145aad8b815ed69b324c93b5b773eb864dda366ca16ab8693ff88ce6f36"}, - {file = "ty-0.0.27-py3-none-win_arm64.whl", hash = "sha256:95bf8d01eb96bb2ba3ffc39faff19da595176448e80871a7b362f4d2de58476c"}, - {file = "ty-0.0.27.tar.gz", hash = "sha256:d7a8de3421d92420b40c94fe7e7d4816037560621903964dd035cf9bd0204a73"}, + {file = "ty-0.0.29-py3-none-linux_armv6l.whl", hash = "sha256:b8a40955f7660d3eaceb0d964affc81b790c0765e7052921a5f861ff8a471c30"}, + {file = "ty-0.0.29-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6b6849adae15b00bbe2d3c5b078967dcb62eba37d38936b8eeb4c81a82d2e3b8"}, + {file = "ty-0.0.29-py3-none-macosx_11_0_arm64.whl", hash = "sha256:dcdd9b17209788152f7b7ea815eda07989152325052fe690013537cc7904ce49"}, + {file = "ty-0.0.29-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d8ed4789bae78ffaf94462c0d25589a734cab0366b86f2bbcb1bb90e1a7a169"}, + {file = "ty-0.0.29-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91ec374b8565e0ad0900011c24641ebbef2da51adbd4fb69ff3280c8a7eceb02"}, + {file = "ty-0.0.29-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:298a8d5faa2502d3810bbbb47a030b9455495b9921594206043c785dd61548cf"}, + {file = "ty-0.0.29-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c8fba1a3524c6109d1e020d92301c79d41bf442fa8d335b9fa366239339cb70"}, + {file = "ty-0.0.29-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c48adf88a70d264128c39ee922ed14a947817fced1e93c08c1a89c9244edcde"}, + {file = "ty-0.0.29-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ce0a7a0e96bc7b42518cd3a1a6a6298ef64ff40ca4614355c1aa807059b5c6f"}, + {file = "ty-0.0.29-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6ac86a05b4a3731d45365ab97780acc7b8146fa62fccb3cbe94fe6546c67a97"}, + {file = "ty-0.0.29-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6bbbf53141af0f3150bf288d716263f1a3550054e4b3551ca866d38192ba9891"}, + {file = "ty-0.0.29-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1c9e06b770c1d0ff5efc51e34312390db31d53fcf3088163f413030b42b74f84"}, + {file = "ty-0.0.29-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0307fe37e3f000ef1a4ae230bbaf511508a78d24a5e51b40902a21b09d5e6037"}, + {file = "ty-0.0.29-py3-none-win32.whl", hash = "sha256:7a2a898217960a825f8bc0087e1fdbaf379606175e98f9807187221d53a4a8ed"}, + {file = "ty-0.0.29-py3-none-win_amd64.whl", hash = "sha256:fc1294200226b91615acbf34e0a9ad81caf98c081e9c6a912a31b0a7b603bc3f"}, + {file = "ty-0.0.29-py3-none-win_arm64.whl", hash = "sha256:f9794bbd1bb3ce13f78c191d0c89ae4c63f52c12b6daa0c6fe220b90d019d12c"}, + {file = "ty-0.0.29.tar.gz", hash = "sha256:e7936cca2f691eeda631876c92809688dbbab68687c3473f526cd83b6a9228d8"}, ] [[package]] @@ -4720,14 +4718,14 @@ types-cffi = "*" [[package]] name = "types-python-dateutil" -version = "2.9.0.20260402" +version = "2.9.0.20260408" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_python_dateutil-2.9.0.20260402-py3-none-any.whl", hash = "sha256:7827e6a9c93587cc18e766944254d1351a2396262e4abe1510cbbd7601c5e01f"}, - {file = "types_python_dateutil-2.9.0.20260402.tar.gz", hash = "sha256:a980142b9966713acb382c467e35c5cc4208a2f91b10b8d785a0ae6765df6c0b"}, + {file = "types_python_dateutil-2.9.0.20260408-py3-none-any.whl", hash = "sha256:473139d514a71c9d1fbd8bb328974bedcb1cc3dba57aad04ffa4157f483c216f"}, + {file = "types_python_dateutil-2.9.0.20260408.tar.gz", hash = "sha256:8b056ec01568674235f64ecbcef928972a5fac412f5aab09c516dfa2acfbb582"}, ] [[package]] @@ -4808,7 +4806,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" @@ -5126,7 +5124,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" @@ -5182,4 +5180,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "b25255bc28d8bd32a551f513c491e2b4aa72491f57c80689fb1be294f583adfa" +content-hash = "6413dbddcb0a105cd5a278bf10d8e0eaca15eb825ef1d92619b94531c8e76375" diff --git a/pyproject.toml b/pyproject.toml index 6b512b6001f..dfe411b112b 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.10" +ruff = ">=0.5.1,<0.15.11" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.8" types-redis = "^4.6.0.7" @@ -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.28" +ty = ">=0.0.23,<0.0.30" [tool.coverage.run] source = ["aws_lambda_powertools"] From cd8829bbe34dc4163bebd340ea671b9548325317 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 14 Apr 2026 12:07:02 +0200 Subject: [PATCH 49/84] feat(event_handler): enrich request object (#8153) --- .../event_handler/api_gateway.py | 1 + .../event_handler/request.py | 87 +++++++++++++---- docs/core/event_handler/api_gateway.md | 90 +++++++++++------- .../dependency_injection_with_middleware.py | 36 +++++++ .../src/dependency_injection_with_request.py | 3 +- .../required_dependencies/test_depends.py | 93 +++++++++++++++++++ .../required_dependencies/test_request.py | 81 ++++++++++++++++ 7 files changed, 342 insertions(+), 49 deletions(-) create mode 100644 examples/event_handler_rest/src/dependency_injection_with_middleware.py diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index f54d486080f..041f6f7abf3 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -1327,6 +1327,7 @@ def my_middleware(app, next_middleware): route_path=route.openapi_path, path_parameters=self.context.get("_route_args", {}), current_event=self.current_event, + context=self.context, ) self.context["_request"] = request return request diff --git a/aws_lambda_powertools/event_handler/request.py b/aws_lambda_powertools/event_handler/request.py index e402c094ded..59d1f84d962 100644 --- a/aws_lambda_powertools/event_handler/request.py +++ b/aws_lambda_powertools/event_handler/request.py @@ -12,11 +12,35 @@ class Request: """Represents the resolved HTTP request. Provides structured access to the matched route pattern, extracted path parameters, - HTTP method, headers, query parameters, and body. Available via ``app.request`` - inside middleware and, when added as a type-annotated parameter, inside route handlers. + HTTP method, headers, query parameters, body, the full Powertools proxy event + (``resolved_event``), and the shared resolver context (``context``). + + Available via ``app.request`` inside middleware and, when added as a type-annotated + parameter, inside ``Depends()`` dependency functions and route handlers. Examples -------- + **Dependency injection with Depends()** + + ```python + from typing import Annotated + from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Request, Depends + + app = APIGatewayRestResolver() + + def get_auth_user(request: Request) -> str: + # Full event access via resolved_event + token = request.resolved_event.get_header_value("authorization", default_value="") + user = validate_token(token) + # Bridge with middleware via shared context + request.context["user"] = user + return user + + @app.get("/orders") + def list_orders(user: Annotated[str, Depends(get_auth_user)]): + return {"user": user} + ``` + **Middleware usage** ```python @@ -39,32 +63,21 @@ def auth_middleware(app: APIGatewayRestResolver, next_middleware: NextMiddleware app.use(middlewares=[auth_middleware]) ``` - - **Route handler injection (type-annotated)** - - ```python - from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Request - - app = APIGatewayRestResolver() - - @app.get("/applications/") - def get_application(application_id: str, request: Request): - user_agent = request.headers.get("user-agent") - return {"id": application_id, "user_agent": user_agent} - ``` """ - __slots__ = ("_current_event", "_path_parameters", "_route_path") + __slots__ = ("_context", "_current_event", "_path_parameters", "_route_path") def __init__( self, route_path: str, path_parameters: dict[str, Any], current_event: BaseProxyEvent, + context: dict[str, Any] | None = None, ) -> None: self._route_path = route_path self._path_parameters = path_parameters self._current_event = current_event + self._context = context if context is not None else {} @property def route(self) -> str: @@ -113,3 +126,45 @@ def body(self) -> str | None: def json_body(self) -> Any: """Request body deserialized as a Python object (dict / list), or ``None``.""" return self._current_event.json_body + + @property + def resolved_event(self) -> BaseProxyEvent: + """Full Powertools proxy event with all helpers and properties. + + Provides access to the complete ``BaseProxyEvent`` (or subclass) that + Powertools resolved for the current invocation. This includes cookies, + request context, path, and event-source-specific properties that are not + available through the convenience properties on :class:`Request`. + + Examples + -------- + ```python + def get_request_details(request: Request) -> dict: + event = request.resolved_event + return { + "path": event.path, + "cookies": event.cookies, + "request_context": event.request_context, + } + ``` + """ + return self._current_event + + @property + def context(self) -> dict[str, Any]: + """Shared resolver context (``app.context``) for this invocation. + + Provides read/write access to the same ``dict`` that middleware and + ``app.append_context()`` populate. This enables incremental migration + from middleware-based data sharing to ``Depends()``-based injection: + middleware writes to ``app.context``, dependencies read from + ``request.context``. + + Examples + -------- + ```python + def get_current_user(request: Request) -> dict: + return request.context["user"] + ``` + """ + return self._context diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 0ffd8cee15c..2a7955f38c0 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -1365,6 +1365,37 @@ You can use `append_context` when you want to share data between your App and Ro --8<-- "examples/event_handler_rest/src/split_route_append_context_module.py" ``` +#### Sample layout + +This is a sample project layout for a monolithic function with routes split in different files (`/todos`, `/health`). + +```shell hl_lines="4 7 10 12-13" title="Sample project layout" +. +├── pyproject.toml # project app & dev dependencies; poetry, pipenv, etc. +├── poetry.lock +├── src +│ ├── __init__.py +│ ├── requirements.txt # sam build detect it automatically due to CodeUri: src. poetry export --format src/requirements.txt +│ └── todos +│ ├── __init__.py +│ ├── main.py # this will be our todos Lambda fn; it could be split in folders if we want separate fns same code base +│ └── routers # routers module +│ ├── __init__.py +│ ├── health.py # /health routes. from routers import todos; health.router +│ └── todos.py # /todos routes. from .routers import todos; todos.router +├── template.yml # SAM. CodeUri: src, Handler: todos.main.lambda_handler +└── tests + ├── __init__.py + ├── unit + │ ├── __init__.py + │ └── test_todos.py # unit tests for the todos router + │ └── test_health.py # unit tests for the health router + └── functional + ├── __init__.py + ├── conftest.py # pytest fixtures for the functional tests + └── test_main.py # functional tests for the main lambda handler +``` + ### Dependency injection You can use `Depends()` to declare dependencies that are automatically resolved and injected into your route handlers. This provides type-safe, composable, and testable dependency injection. @@ -1389,10 +1420,36 @@ Dependencies can depend on other dependencies, forming a composable tree. Shared Dependencies that need access to the current request can declare a parameter typed as `Request`. It will be injected automatically. -```python hl_lines="5-6 12 20" +The `Request` object provides: + +* **`headers`**, **`query_parameters`**, **`body`**, **`json_body`**: common request data +* **`resolved_event`**: the full Powertools proxy event with all helpers, cookies, request context, and path +* **`context`**: shared resolver context (`app.context`) for bridging data between middleware and dependencies + +```python hl_lines="5-6 14 20" --8<-- "examples/event_handler_rest/src/dependency_injection_with_request.py" ``` +#### Combining middleware and Depends() + +Middleware and `Depends()` are **complementary patterns**. Use middleware for request interception (auth gates, redirects, response modification) and `Depends()` for typed data injection. + +The bridge between them is `request.context`: middleware writes to `app.context`, and dependencies read from `request.context`: + +```python hl_lines="12-18 22-23 27" +--8<-- "examples/event_handler_rest/src/dependency_injection_with_middleware.py" +``` + +???+ tip "When to use middleware vs Depends()" + | Use case | Middleware | Depends() | + | --- | --- | --- | + | Return custom HTTP responses (redirects, 401s) | **Yes** | No, can only return values or raise exceptions | + | Short-circuit the request pipeline | **Yes** | No | + | Pre/post-process responses (add headers, compress) | **Yes** | No | + | Inject typed, testable data into handlers | No | **Yes** | + | Compose a dependency tree with caching | No | **Yes** | + | Override dependencies in tests | No | **Yes**, via `dependency_overrides` | + #### Testing with dependency overrides Use `dependency_overrides` to replace any dependency with a mock or stub during testing - no monkeypatching needed. @@ -1407,37 +1464,6 @@ Use `dependency_overrides` to replace any dependency with a mock or stub during ???+ info "`append_context` vs `Depends()`" `append_context` remains available for backward compatibility. `Depends()` is recommended for new code because it provides type safety, IDE autocomplete, composable dependency trees, and `dependency_overrides` for testing. -#### Sample layout - -This is a sample project layout for a monolithic function with routes split in different files (`/todos`, `/health`). - -```shell hl_lines="4 7 10 12-13" title="Sample project layout" -. -├── pyproject.toml # project app & dev dependencies; poetry, pipenv, etc. -├── poetry.lock -├── src -│ ├── __init__.py -│ ├── requirements.txt # sam build detect it automatically due to CodeUri: src. poetry export --format src/requirements.txt -│ └── todos -│ ├── __init__.py -│ ├── main.py # this will be our todos Lambda fn; it could be split in folders if we want separate fns same code base -│ └── routers # routers module -│ ├── __init__.py -│ ├── health.py # /health routes. from routers import todos; health.router -│ └── todos.py # /todos routes. from .routers import todos; todos.router -├── template.yml # SAM. CodeUri: src, Handler: todos.main.lambda_handler -└── tests - ├── __init__.py - ├── unit - │ ├── __init__.py - │ └── test_todos.py # unit tests for the todos router - │ └── test_health.py # unit tests for the health router - └── functional - ├── __init__.py - ├── conftest.py # pytest fixtures for the functional tests - └── test_main.py # functional tests for the main lambda handler -``` - ### Considerations This utility is optimized for fast startup, minimal feature set, and to quickly on-board customers familiar with frameworks like Flask — it's not meant to be a fully fledged framework. diff --git a/examples/event_handler_rest/src/dependency_injection_with_middleware.py b/examples/event_handler_rest/src/dependency_injection_with_middleware.py new file mode 100644 index 00000000000..63ee419c345 --- /dev/null +++ b/examples/event_handler_rest/src/dependency_injection_with_middleware.py @@ -0,0 +1,36 @@ +from typing_extensions import Annotated + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver, Response +from aws_lambda_powertools.event_handler.depends import Depends +from aws_lambda_powertools.event_handler.request import Request +from aws_lambda_powertools.utilities.typing import LambdaContext + +app = APIGatewayHttpResolver() + + +# Middleware handles auth — it can return HTTP responses (redirects, 401s) +def auth_middleware(app, next_middleware): + token = app.current_event.headers.get("authorization", "") + if not token: + return Response(status_code=401, body="Unauthorized") + + # Middleware writes to app.context + app.append_context(user={"id": "user-123", "role": "admin"}) + return next_middleware(app) + + +app.use(middlewares=[auth_middleware]) + + +# Depends() reads what middleware wrote via request.context — typed and testable +def get_current_user(request: Request) -> dict: + return request.context["user"] + + +@app.get("/admin/dashboard") +def admin_dashboard(user: Annotated[dict, Depends(get_current_user)]): + return {"message": f"Welcome {user['id']}", "role": user["role"]} + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/dependency_injection_with_request.py b/examples/event_handler_rest/src/dependency_injection_with_request.py index c918b646f46..e8586294f32 100644 --- a/examples/event_handler_rest/src/dependency_injection_with_request.py +++ b/examples/event_handler_rest/src/dependency_injection_with_request.py @@ -10,7 +10,8 @@ def get_authenticated_user(request: Request) -> str: - user_id = request.headers.get("x-user-id") + # Use resolved_event for full Powertools event access (cookies, request_context, path, etc.) + user_id = request.resolved_event.headers.get("x-user-id", "") if not user_id: raise UnauthorizedError("Missing authentication") return user_id diff --git a/tests/functional/event_handler/required_dependencies/test_depends.py b/tests/functional/event_handler/required_dependencies/test_depends.py index 3131be2430e..d5e49e07cdd 100644 --- a/tests/functional/event_handler/required_dependencies/test_depends.py +++ b/tests/functional/event_handler/required_dependencies/test_depends.py @@ -414,3 +414,96 @@ def handler(val: Annotated[str, Depends(broken_dep)]): result = app(API_GW_V2_EVENT, {}) assert result["statusCode"] == 200 assert json.loads(result["body"]) == {"val": "it-works"} + + +# --------------------------------------------------------------------------- +# request.context — bridge between middleware and Depends() +# --------------------------------------------------------------------------- + + +def test_depends_request_context_writable(): + """Dependencies can write to request.context and handlers can read it.""" + app = APIGatewayHttpResolver() + + def set_tenant(request: Request) -> str: + tenant = request.headers.get("x-tenant-id", "default") + request.context["tenant"] = tenant + return tenant + + @app.post("/my/path") + def handler(tenant: Annotated[str, Depends(set_tenant)], request: Request): + return {"tenant": tenant, "from_context": request.context.get("tenant")} + + event = {**API_GW_V2_EVENT, "headers": {**API_GW_V2_EVENT.get("headers", {}), "x-tenant-id": "acme-corp"}} + result = app(event, {}) + + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["tenant"] == "acme-corp" + assert body["from_context"] == "acme-corp" + + +def test_depends_request_context_bridges_middleware(): + """Middleware writes to app.context, Depends() reads via request.context.""" + app = APIGatewayHttpResolver() + + def auth_middleware(app, next_middleware): + app.append_context(user="admin-user") + return next_middleware(app) + + app.use(middlewares=[auth_middleware]) + + def get_current_user(request: Request) -> str: + return request.context["user"] + + @app.post("/my/path") + def handler(user: Annotated[str, Depends(get_current_user)]): + return {"user": user} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"user": "admin-user"} + + +def test_depends_request_context_with_router(): + """request.context works when routes come from an included Router.""" + from aws_lambda_powertools.event_handler.api_gateway import Router + + app = APIGatewayHttpResolver() + router = Router() + + def mw(app, next_middleware): + app.append_context(role="admin") + return next_middleware(app) + + app.use(middlewares=[mw]) + + def get_role(request: Request) -> str: + return request.context["role"] + + @router.post("/my/path") + def handler(role: Annotated[str, Depends(get_role)]): + return {"role": role} + + app.include_router(router) + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + assert json.loads(result["body"]) == {"role": "admin"} + + +def test_depends_request_resolved_event(): + """Dependencies can access the full event via request.resolved_event.""" + app = APIGatewayHttpResolver() + + def get_path(request: Request) -> str: + return request.resolved_event.path + + @app.post("/my/path") + def handler(path: Annotated[str, Depends(get_path)]): + return {"path": path} + + result = app(API_GW_V2_EVENT, {}) + assert result["statusCode"] == 200 + body = json.loads(result["body"]) + assert body["path"] == "/my/path" diff --git a/tests/functional/event_handler/required_dependencies/test_request.py b/tests/functional/event_handler/required_dependencies/test_request.py index 02ae0da5b88..b00ae6659ba 100644 --- a/tests/functional/event_handler/required_dependencies/test_request.py +++ b/tests/functional/event_handler/required_dependencies/test_request.py @@ -586,3 +586,84 @@ def handler(request: Request): # All accesses should return the same cached instance assert len(ids_seen) == 3 assert ids_seen[0] == ids_seen[1] == ids_seen[2] + + +# --------------------------------------------------------------------------- +# resolved_event — full Powertools proxy event access +# --------------------------------------------------------------------------- + + +def test_request_resolved_event_exposes_full_event(): + """resolved_event should return the full BaseProxyEvent with all helpers.""" + app = APIGatewayRestResolver() + captured: list[Request] = [] + + def mw(app: APIGatewayRestResolver, next_middleware): + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/my/path") + def handler(): + return {} + + app(API_REST_EVENT, {}) + + req = captured[0] + resolved = req.resolved_event + + # resolved_event should be the same object as app.current_event + assert resolved is not None + assert resolved.http_method == "GET" + # Should have helper methods not available on Request directly + assert hasattr(resolved, "get_header_value") + assert hasattr(resolved, "get_query_string_value") + + +def test_request_resolved_event_provides_cookies_and_path(): + """resolved_event gives access to path and properties not on Request.""" + app = APIGatewayRestResolver() + captured: list[Request] = [] + + def mw(app: APIGatewayRestResolver, next_middleware): + captured.append(app.request) + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/items/") + def handler(item_id: str): + return {} + + event = _make_rest_event("/items/42", path_parameters={"item_id": "42"}) + app(event, {}) + + resolved = captured[0].resolved_event + assert resolved.path == "/items/42" + + +# --------------------------------------------------------------------------- +# context — shared resolver context (app.context) +# --------------------------------------------------------------------------- + + +def test_request_context_shares_app_context(): + """request.context should be the same dict as app.context.""" + app = APIGatewayRestResolver() + + def mw(app: APIGatewayRestResolver, next_middleware): + app.append_context(user="test-user") + return next_middleware(app) + + app.use(middlewares=[mw]) + + @app.get("/my/path") + def handler(request: Request): + return {"user": request.context.get("user")} + + result = app(API_REST_EVENT, {}) + assert result["statusCode"] == 200 + import json + + assert json.loads(result["body"]) == {"user": "test-user"} From 7fc9efb3bda38b961a559f6eb8f09fdc8ba957ab Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 14 Apr 2026 12:16:21 +0200 Subject: [PATCH 50/84] fix(data_class): merge querystring parameters in ALB/APIGW classes (#8154) fix(data_class): merge querystring parameters --- .../utilities/data_classes/alb_event.py | 12 ++++- .../data_classes/api_gateway_proxy_event.py | 12 ++++- .../required_dependencies/test_alb_event.py | 14 ++++++ .../test_api_gateway_proxy_event.py | 50 +++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/alb_event.py b/aws_lambda_powertools/utilities/data_classes/alb_event.py index 7d1541455d5..b9525e6a9f0 100644 --- a/aws_lambda_powertools/utilities/data_classes/alb_event.py +++ b/aws_lambda_powertools/utilities/data_classes/alb_event.py @@ -44,7 +44,17 @@ def request_context(self) -> ALBEventRequestContext: @property def resolved_query_string_parameters(self) -> dict[str, list[str]]: - params = self.multi_value_query_string_parameters or super().resolved_query_string_parameters + multi_value = self.multi_value_query_string_parameters + single_value = super().resolved_query_string_parameters + + if not multi_value: + params = single_value + elif not single_value: + params = multi_value + else: + # Merge both: multi_value takes precedence, single_value fills missing keys + params = {**single_value, **multi_value} + if not self.decode_query_parameters: return params diff --git a/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py b/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py index 6e24873e6d7..88f6cb8fa54 100644 --- a/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py +++ b/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py @@ -120,7 +120,17 @@ def multi_value_headers(self) -> dict[str, list[str]]: @property def resolved_query_string_parameters(self) -> dict[str, list[str]]: - return self.multi_value_query_string_parameters or super().resolved_query_string_parameters + multi_value = self.multi_value_query_string_parameters + single_value = super().resolved_query_string_parameters + + if not multi_value: + return single_value + + if not single_value: + return multi_value + + # Merge both: multi_value takes precedence, single_value fills missing keys + return {**single_value, **multi_value} @property def resolved_headers_field(self) -> dict[str, Any]: diff --git a/tests/unit/data_classes/required_dependencies/test_alb_event.py b/tests/unit/data_classes/required_dependencies/test_alb_event.py index 13d8b5907be..23ab7af6365 100644 --- a/tests/unit/data_classes/required_dependencies/test_alb_event.py +++ b/tests/unit/data_classes/required_dependencies/test_alb_event.py @@ -52,3 +52,17 @@ def test_alb_event_decode_multi_value_query_parameters(): # With decode_query_parameters, the key and value are not decoded parsed_event.decode_query_parameters = True assert parsed_event.resolved_query_string_parameters == {expected_key: expected_values} + + +def test_alb_event_merged_query_string_parameters(): + """When both multiValueQueryStringParameters and queryStringParameters are present, + resolved_query_string_parameters should merge them (GH #7993).""" + raw_event = load_event("albMultiValueQueryStringEvent.json") + raw_event["multiValueQueryStringParameters"] = {"ids": ["1", "2", "3"]} + raw_event["queryStringParameters"] = {"status": "fizzbuzz"} + + parsed_event = ALBEvent(raw_event) + resolved = parsed_event.resolved_query_string_parameters + + assert resolved["ids"] == ["1", "2", "3"] + assert resolved["status"] == ["fizzbuzz"] diff --git a/tests/unit/data_classes/required_dependencies/test_api_gateway_proxy_event.py b/tests/unit/data_classes/required_dependencies/test_api_gateway_proxy_event.py index ec71d815a7c..fd9ca1cca76 100644 --- a/tests/unit/data_classes/required_dependencies/test_api_gateway_proxy_event.py +++ b/tests/unit/data_classes/required_dependencies/test_api_gateway_proxy_event.py @@ -241,3 +241,53 @@ def test_api_gateway_proxy_v2_iam_event(): assert iam.principal_org_id == iam_raw["principalOrgId"] assert iam.user_arn == iam_raw["userArn"] assert iam.user_id == iam_raw["userId"] + + +def test_api_gateway_proxy_event_merged_query_string_parameters(): + """When both multiValueQueryStringParameters and queryStringParameters are present, + resolved_query_string_parameters should merge them (GH #7993).""" + raw_event = load_event("apiGatewayProxyEvent.json") + raw_event["multiValueQueryStringParameters"] = {"ids": ["1", "2", "3"]} + raw_event["queryStringParameters"] = {"status": "fizzbuzz"} + + parsed_event = APIGatewayProxyEvent(raw_event) + resolved = parsed_event.resolved_query_string_parameters + + assert resolved["ids"] == ["1", "2", "3"] + assert resolved["status"] == ["fizzbuzz"] + + +def test_api_gateway_proxy_event_multi_value_takes_precedence(): + """When the same key exists in both, multiValueQueryStringParameters wins.""" + raw_event = load_event("apiGatewayProxyEvent.json") + raw_event["multiValueQueryStringParameters"] = {"key": ["a", "b"]} + raw_event["queryStringParameters"] = {"key": "c"} + + parsed_event = APIGatewayProxyEvent(raw_event) + resolved = parsed_event.resolved_query_string_parameters + + assert resolved["key"] == ["a", "b"] + + +def test_api_gateway_proxy_event_only_single_value_query_params(): + """When only queryStringParameters is present, it should still work.""" + raw_event = load_event("apiGatewayProxyEvent.json") + raw_event["multiValueQueryStringParameters"] = None + raw_event["queryStringParameters"] = {"status": "active"} + + parsed_event = APIGatewayProxyEvent(raw_event) + resolved = parsed_event.resolved_query_string_parameters + + assert resolved["status"] == ["active"] + + +def test_api_gateway_proxy_event_only_multi_value_query_params(): + """When only multiValueQueryStringParameters is present, it should still work.""" + raw_event = load_event("apiGatewayProxyEvent.json") + raw_event["multiValueQueryStringParameters"] = {"ids": ["1", "2"]} + raw_event["queryStringParameters"] = None + + parsed_event = APIGatewayProxyEvent(raw_event) + resolved = parsed_event.resolved_query_string_parameters + + assert resolved["ids"] == ["1", "2"] From 53999ae12d7dd4ea25e429a5455e956c63d58e3b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:59:52 +0200 Subject: [PATCH 51/84] chore(ci): bump version to 3.28.0 (#8155) 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 60d93d7d3d7..067def9eece 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.27.0" +VERSION = "3.28.0" diff --git a/pyproject.toml b/pyproject.toml index dfe411b112b..e75809594be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "3.27.0" +version = "3.28.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 6f5d990abeb15ce2f512fadff2394b086fad35e1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:02:09 +0200 Subject: [PATCH 52/84] chore(ci): layer docs update (#8156) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Leandro Damascena --- CHANGELOG.md | 57 +++- 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, 374 insertions(+), 319 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ba57cc87b9..9ef5c4b5674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,65 @@ # Unreleased + +## [v3.28.0] - 2026-04-14 +## Bug Fixes + +* **data_class:** merge querystring parameters in ALB/APIGW classes ([#8154](https://github.com/aws-powertools/powertools-lambda-python/issues/8154)) + +## Maintenance + +* version bump + + ## [v3.27.0] - 2026-04-06 +## Bug Fixes + +* **data_classes:** support {proxy+} and path parameters in authorizer response ([#8092](https://github.com/aws-powertools/powertools-lambda-python/issues/8092)) +* **event_handler:** sync middleware receives real response in async ASGI context ([#8089](https://github.com/aws-powertools/powertools-lambda-python/issues/8089)) +* **event_handler:** support finding type annotated resolver when merging schemas ([#8074](https://github.com/aws-powertools/powertools-lambda-python/issues/8074)) +* **event_handler:** normalize Union and RootModel sequences in body validation ([#8067](https://github.com/aws-powertools/powertools-lambda-python/issues/8067)) +* **idempotency:** serialize Pydantic models with mode='json' for UUID/date support ([#8075](https://github.com/aws-powertools/powertools-lambda-python/issues/8075)) + +## Documentation + +* adding docs to Request object ([#8105](https://github.com/aws-powertools/powertools-lambda-python/issues/8105)) +* fix ranthebuilder link in Update we_made_this.md ([#8084](https://github.com/aws-powertools/powertools-lambda-python/issues/8084)) + +## Features + +* **event_handler:** add File parameter support for multipart/form-data uploads ([#8093](https://github.com/aws-powertools/powertools-lambda-python/issues/8093)) +* **event_handler:** add Cookie parameter support for OpenAPI utility ([#8095](https://github.com/aws-powertools/powertools-lambda-python/issues/8095)) +* **event_handler:** add Request object for middleware access to resolved route and args ([#8036](https://github.com/aws-powertools/powertools-lambda-python/issues/8036)) + ## Maintenance * version bump +* **deps:** bump valkey-glide from 2.2.7 to 2.3.0 ([#8080](https://github.com/aws-powertools/powertools-lambda-python/issues/8080)) +* **deps:** bump protobuf from 6.33.5 to 7.34.0 ([#8046](https://github.com/aws-powertools/powertools-lambda-python/issues/8046)) +* **deps:** bump mkdocs-material from 9.7.1 to 9.7.5 ([#8045](https://github.com/aws-powertools/powertools-lambda-python/issues/8045)) +* **deps:** bump requests from 2.32.4 to 2.33.0 in /docs ([#8070](https://github.com/aws-powertools/powertools-lambda-python/issues/8070)) +* **deps:** bump cryptography from 46.0.5 to 46.0.6 ([#8072](https://github.com/aws-powertools/powertools-lambda-python/issues/8072)) +* **deps:** bump squidfunk/mkdocs-material from `8f41b60` to `868ad4d` in /docs ([#8083](https://github.com/aws-powertools/powertools-lambda-python/issues/8083)) +* **deps:** bump the github-actions group across 1 directory with 10 updates ([#8081](https://github.com/aws-powertools/powertools-lambda-python/issues/8081)) +* **deps:** bump mkdocs-material from 9.7.5 to 9.7.6 ([#8079](https://github.com/aws-powertools/powertools-lambda-python/issues/8079)) +* **deps-dev:** bump aws-cdk from 2.1111.0 to 2.1113.0 in the aws-cdk group ([#8058](https://github.com/aws-powertools/powertools-lambda-python/issues/8058)) +* **deps-dev:** bump sentry-sdk from 2.54.0 to 2.56.0 ([#8082](https://github.com/aws-powertools/powertools-lambda-python/issues/8082)) +* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.243.0a0 to 2.248.0a0 ([#8103](https://github.com/aws-powertools/powertools-lambda-python/issues/8103)) +* **deps-dev:** bump the dev-dependencies group across 1 directory with 4 updates ([#8086](https://github.com/aws-powertools/powertools-lambda-python/issues/8086)) +* **deps-dev:** bump pygments from 2.19.2 to 2.20.0 ([#8077](https://github.com/aws-powertools/powertools-lambda-python/issues/8077)) +* **deps-dev:** bump requests from 2.32.5 to 2.33.0 ([#8069](https://github.com/aws-powertools/powertools-lambda-python/issues/8069)) +* **deps-dev:** bump ty from 0.0.23 to 0.0.26 ([#8078](https://github.com/aws-powertools/powertools-lambda-python/issues/8078)) +* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.315 to 0.1.316 ([#8061](https://github.com/aws-powertools/powertools-lambda-python/issues/8061)) +* **deps-dev:** bump boto3-stubs from 1.42.73 to 1.42.74 ([#8062](https://github.com/aws-powertools/powertools-lambda-python/issues/8062)) +* **deps-dev:** bump requests from 2.33.0 to 2.33.1 ([#8104](https://github.com/aws-powertools/powertools-lambda-python/issues/8104)) +* **deps-dev:** bump boto3-stubs from 1.42.67 to 1.42.68 ([#8043](https://github.com/aws-powertools/powertools-lambda-python/issues/8043)) +* **deps-dev:** bump nox from 2025.11.12 to 2026.2.9 ([#8044](https://github.com/aws-powertools/powertools-lambda-python/issues/8044)) +* **deps-dev:** bump aws-cdk from 2.1110.0 to 2.1111.0 in the aws-cdk group ([#8039](https://github.com/aws-powertools/powertools-lambda-python/issues/8039)) +* **deps-dev:** bump ruff from 0.15.8 to 0.15.9 in the dev-dependencies group ([#8100](https://github.com/aws-powertools/powertools-lambda-python/issues/8100)) +* **deps-dev:** bump isort from 7.0.0 to 8.0.1 ([#8101](https://github.com/aws-powertools/powertools-lambda-python/issues/8101)) +* **deps-dev:** bump types-requests from 2.32.4.20260107 to 2.33.0.20260402 ([#8102](https://github.com/aws-powertools/powertools-lambda-python/issues/8102)) @@ -7572,7 +7626,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.27.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.28.0...HEAD +[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 [v3.26.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.25.0...v3.26.0 [v3.25.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.24.0...v3.25.0 diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index fd0bc7b39c5..eb5391393bf 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:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 39270dc4c70..8e88de48908 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:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:31**{: .copyMe} | + | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | diff --git a/examples/build_recipes/cdk/basic/app.py b/examples/build_recipes/cdk/basic/app.py index 069c26f469c..d8509e7a1ce 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:31", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32", ) # 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 5e72d667f31..b526e04cc2b 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:31", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32", ) 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 a4fab0f25d1..37b9103eda3 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:31 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32 - !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 90352866e9e..c9aef4c6bcb 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:31 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32 - !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:31 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32 - !Ref DependenciesLayer Events: SQSEvent: diff --git a/examples/homepage/install/arm64/amplify.txt b/examples/homepage/install/arm64/amplify.txt index 3a97584cf65..78dee0ac047 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:31 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32 ❯ 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:31 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32 ? 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 21f06a602da..eb6685b800a 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:31", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/arm64/pulumi_arm64.py b/examples/homepage/install/arm64/pulumi_arm64.py index c73e2b10192..b7577b5509e 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:31", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/arm64/sam.yaml b/examples/homepage/install/arm64/sam.yaml index 081e34d550b..73d023bfc33 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:31 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32 diff --git a/examples/homepage/install/arm64/serverless.yml b/examples/homepage/install/arm64/serverless.yml index a453cfb548b..e6f8f335f77 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:31 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32 diff --git a/examples/homepage/install/arm64/terraform.tf b/examples/homepage/install/arm64/terraform.tf index c5fb60e62aa..aa986baa2ad 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:31"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32"] 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 48de3e9ad3c..24d0108a4a8 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:31 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 ❯ 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:31 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 ? 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 d1bf26202d9..cf774cba370 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:31", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32", ) 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 a0e6f9db425..d9aeef246f9 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:31", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml index 0192664e0a6..ac3d7545b46 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:31 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml index 4ac86076f24..23573959df0 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:31 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf index fcc999a872f..8db1d6ae3ff 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:31"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 1b1cd0e41a2..2bb425009cb 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:31 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index af840ffe615..2369678e037 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:31 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 Resources: CaptureLambdaHandlerExample: diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml index 66697f68760..6420c4331bf 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:31 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 # 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 cd21c5f1b3c..7ce2bc40715 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:31 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32 Resources: CaptureLambdaHandlerExample: From a54b39d6b3204500dc65988cec49de19db047e3f Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 15 Apr 2026 16:27:06 +0200 Subject: [PATCH 53/84] refactor(event_handler): extract async logic to a separated file (#8138) refactor(event_handler): extract async logic --- .../event_handler/http_resolver.py | 68 +---------- .../event_handler/middlewares/async_utils.py | 107 ++++++++++++++++++ 2 files changed, 109 insertions(+), 66 deletions(-) create mode 100644 aws_lambda_powertools/event_handler/middlewares/async_utils.py diff --git a/aws_lambda_powertools/event_handler/http_resolver.py b/aws_lambda_powertools/event_handler/http_resolver.py index 93e2fdc932e..168a6f44b8e 100644 --- a/aws_lambda_powertools/event_handler/http_resolver.py +++ b/aws_lambda_powertools/event_handler/http_resolver.py @@ -1,9 +1,7 @@ from __future__ import annotations -import asyncio import base64 import inspect -import threading import warnings from typing import TYPE_CHECKING, Any, Callable from urllib.parse import parse_qs @@ -15,6 +13,7 @@ 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 @@ -320,73 +319,10 @@ async def final_handler(app): next_handler = final_handler for middleware in reversed(all_middlewares): - next_handler = self._wrap_middleware_async(middleware, next_handler) + next_handler = wrap_middleware_async(middleware, next_handler) return await next_handler(self) - def _wrap_middleware_async(self, middleware: Callable, next_handler: Callable) -> Callable: - """Wrap a middleware to work in async context. - - For sync middlewares, we split execution into pre/post phases around the - call to next(). The sync middleware runs its pre-processing (e.g. request - validation), then we intercept the next() call, await the async handler, - and resume the middleware with the real response so post-processing - (e.g. response validation) sees the actual data. - """ - - async def wrapped(app): - if inspect.iscoroutinefunction(middleware): - return await middleware(app, next_handler) - - # We use an Event to coordinate: the sync middleware runs in a thread, - # calls sync_next which signals us to resolve the async handler, - # then waits for the real response. - middleware_called_next = asyncio.Event() - next_app_holder: list = [] - real_response_holder: list = [] - middleware_result_holder: list = [] - middleware_error_holder: list = [] - - def sync_next(app): - next_app_holder.append(app) - middleware_called_next.set() - # Block this thread until the real response is available - event = threading.Event() - next_app_holder.append(event) - event.wait() - return real_response_holder[0] - - def run_middleware(): - try: - result = middleware(app, sync_next) - middleware_result_holder.append(result) - except Exception as e: - middleware_error_holder.append(e) - - thread = threading.Thread(target=run_middleware, daemon=True) - thread.start() - - # Wait for the middleware to call next() - await middleware_called_next.wait() - - # Now resolve the async next_handler - real_response = await next_handler(next_app_holder[0]) - real_response_holder.append(real_response) - - # Signal the thread that the response is ready - threading_event = next_app_holder[1] - threading_event.set() - - # Wait for the middleware thread to finish - thread.join() - - if middleware_error_holder: - raise middleware_error_holder[0] - - return middleware_result_holder[0] - - return wrapped - async def _handle_not_found_async(self) -> dict: """Handle 404 responses, using custom not_found handler if registered.""" from http import HTTPStatus diff --git a/aws_lambda_powertools/event_handler/middlewares/async_utils.py b/aws_lambda_powertools/event_handler/middlewares/async_utils.py new file mode 100644 index 00000000000..b04db33f1e8 --- /dev/null +++ b/aws_lambda_powertools/event_handler/middlewares/async_utils.py @@ -0,0 +1,107 @@ +"""Async middleware utilities for bridging sync and async middleware execution.""" + +from __future__ import annotations + +import asyncio +import inspect +import threading +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from collections.abc import Callable + + from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, Response + + +def wrap_middleware_async(middleware: Callable, next_handler: Callable) -> Callable: + """Wrap a middleware to work in an async context. + + For async middlewares, delegates directly with ``await``. + + For sync middlewares, runs the middleware in a background thread and uses + ``asyncio.Event`` / ``threading.Event`` to coordinate the ``next()`` call + so the async handler can be awaited on the main event-loop while the sync + middleware blocks its own thread waiting for the result. + + Parameters + ---------- + middleware : Callable + A sync or async middleware ``(app, next_middleware) -> Response``. + next_handler : Callable + The next (async) handler in the chain. + + Returns + ------- + Callable + An async callable ``(app) -> Response`` that executes *middleware* + followed by *next_handler*. + """ + + async def wrapped(app: ApiGatewayResolver) -> Response: + if inspect.iscoroutinefunction(middleware): + return await middleware(app, next_handler) + + return await _run_sync_middleware_in_thread(middleware, next_handler, app) + + return wrapped + + +async def _run_sync_middleware_in_thread( + middleware: Callable, + next_handler: Callable, + app: Any, +) -> Any: + """Execute a **sync** middleware inside a daemon thread. + + The sync middleware calls ``sync_next(app)`` which: + + 1. Signals the async side that the middleware is ready for the next handler. + 2. Blocks the thread until the async handler has produced a response. + 3. Returns the response so the middleware can do post-processing. + + Meanwhile the async side awaits *next_handler*, feeds the response back, + and waits for the thread to finish. + """ + middleware_called_next = asyncio.Event() + next_app_holder: list = [] + real_response_holder: list = [] + middleware_result_holder: list = [] + middleware_error_holder: list = [] + + def sync_next(app: Any) -> Any: + next_app_holder.append(app) + middleware_called_next.set() + # Block this thread until the async handler resolves + event = threading.Event() + next_app_holder.append(event) + event.wait() + return real_response_holder[0] + + def run_middleware() -> None: + try: + result = middleware(app, sync_next) + middleware_result_holder.append(result) + except Exception as e: + middleware_error_holder.append(e) + + thread = threading.Thread(target=run_middleware, daemon=True) + thread.start() + + # Wait for the middleware to call next() + await middleware_called_next.wait() + + # Resolve the async next_handler on the event-loop + real_response = await next_handler(next_app_holder[0]) + real_response_holder.append(real_response) + + # Unblock the middleware thread + threading_event = next_app_holder[1] + threading_event.set() + + # Wait for the middleware thread to complete post-processing + thread.join() + + if middleware_error_holder: + raise middleware_error_holder[0] + + return middleware_result_holder[0] From bf411474ea17c219f2bf6658195dc7c733629e2c Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Sun, 19 Apr 2026 08:03:07 -0400 Subject: [PATCH 54/84] feat(event-handler): add _registered_api_adapter_async() internal building block (#8157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(event-handler): add _registered_api_adapter_async() internal building block - Add async counterpart to _registered_api_adapter() - Detects if route handler result is a coroutine using inspect.iscoroutine() - Awaits async handlers; passes sync handlers through unchanged - _to_response() remains sync (CPU-bound, no async benefit) - Move import inspect to top-level imports (consistent with file style) - Nothing calls this in the resolve chain yet — internal building block only Closes #8135 Part of parent: #3934 Next step: #8137 (public resolve_async()) will wire this in Signed-off-by: hirenkumar-n-dholariya * refactor(event-handler): move _registered_api_adapter_async to async_utils.py Per maintainer feedback on #8157 - function belongs in async_utils.py alongside other async event handler internals (wrap_middleware_async, _run_sync_middleware_in_thread, etc.) Signed-off-by: hirenkumar-n-dholariya * test(event-handler): add unit tests for _registered_api_adapter_async() Tests cover sync handler, async handler, and mixed scenarios as required by issue #8135 Signed-off-by: hirenkumar-n-dholariya * refactor(event-handler): move _registered_api_adapter_async to async_utils.py Per maintainer feedback on #8157 - function belongs in async_utils.py alongside other async event handler internals (wrap_middleware_async, _run_sync_middleware_in_thread, etc.) Signed-off-by: hirenkumar-n-dholariya * fix: small changes * fix: small changes * fix: small changes * fix: small changes --------- Signed-off-by: hirenkumar-n-dholariya Co-authored-by: Leandro Damascena --- .../event_handler/middlewares/async_utils.py | 62 +++- .../test_registered_api_adapter_async.py | 335 ++++++++++++++++++ 2 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 tests/functional/event_handler/required_dependencies/test_registered_api_adapter_async.py diff --git a/aws_lambda_powertools/event_handler/middlewares/async_utils.py b/aws_lambda_powertools/event_handler/middlewares/async_utils.py index b04db33f1e8..469ed1e96b1 100644 --- a/aws_lambda_powertools/event_handler/middlewares/async_utils.py +++ b/aws_lambda_powertools/event_handler/middlewares/async_utils.py @@ -4,13 +4,16 @@ import asyncio import inspect +import logging import threading from typing import TYPE_CHECKING, Any +logger = logging.getLogger(__name__) + if TYPE_CHECKING: from collections.abc import Callable - from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, Response + from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, BedrockResponse, Response def wrap_middleware_async(middleware: Callable, next_handler: Callable) -> Callable: @@ -105,3 +108,60 @@ def run_middleware() -> None: raise middleware_error_holder[0] return middleware_result_holder[0] + + +async def _registered_api_adapter_async( + app: ApiGatewayResolver, + next_middleware: Callable[..., Any], +) -> dict | tuple | Response | BedrockResponse: + """ + Async version of _registered_api_adapter. + + Detects if the route handler is a coroutine and awaits it. + _to_response() stays sync (CPU-bound — no async benefit). + + IMPORTANT: This is an internal building block only. + Nothing calls it in the resolve chain yet. It will be used + by resolve_async() (see issue #8137). + + Parameters + ---------- + app: ApiGatewayResolver + The API Gateway resolver + next_middleware: Callable[..., Any] + The function to handle the API + + Returns + ------- + Response + The API Response Object + """ + route_args: dict = app.context.get("_route_args", {}) + logger.debug(f"Calling API Route Handler: {route_args}") + + route = app.context.get("_route") + if route is not None: + if not route.request_param_name_checked: + from aws_lambda_powertools.event_handler.api_gateway import _find_request_param_name + + route.request_param_name = _find_request_param_name(next_middleware) + route.request_param_name_checked = True + if route.request_param_name: + route_args = {**route_args, route.request_param_name: app.request} + + if route.has_dependencies: + from aws_lambda_powertools.event_handler.depends import build_dependency_tree, solve_dependencies + + dep_values = solve_dependencies( + dependant=build_dependency_tree(route.func), + request=app.request, + dependency_overrides=app.dependency_overrides or None, + ) + route_args.update(dep_values) + + # Call handler — detect if result is a coroutine and await it + result = next_middleware(**route_args) + if inspect.iscoroutine(result): + result = await result + + return app._to_response(result) diff --git a/tests/functional/event_handler/required_dependencies/test_registered_api_adapter_async.py b/tests/functional/event_handler/required_dependencies/test_registered_api_adapter_async.py new file mode 100644 index 00000000000..10d5b4602f0 --- /dev/null +++ b/tests/functional/event_handler/required_dependencies/test_registered_api_adapter_async.py @@ -0,0 +1,335 @@ +import asyncio +import re +from typing import cast + +import pytest +from typing_extensions import Annotated + +from aws_lambda_powertools.event_handler import content_types +from aws_lambda_powertools.event_handler.api_gateway import ( + APIGatewayHttpResolver, + ApiGatewayResolver, + APIGatewayRestResolver, + BaseRouter, + ProxyEventType, + Response, + Route, +) +from aws_lambda_powertools.event_handler.depends import Depends +from aws_lambda_powertools.event_handler.middlewares.async_utils import _registered_api_adapter_async +from aws_lambda_powertools.event_handler.request import Request +from tests.functional.utils import load_event + +API_REST_EVENT = load_event("apiGatewayProxyEvent.json") +API_RESTV2_EVENT = load_event("apiGatewayProxyV2Event_GET.json") + + +def _setup_resolver_context(app: ApiGatewayResolver, event: dict) -> None: + """Populate the resolver context the same way resolve() does, without calling the full chain.""" + BaseRouter.current_event = app._to_proxy_event(cast(dict, event)) + BaseRouter.lambda_context = {} + + +@pytest.mark.parametrize( + "app, event", + [ + (ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent), API_REST_EVENT), + (APIGatewayRestResolver(), API_REST_EVENT), + (APIGatewayHttpResolver(), API_RESTV2_EVENT), + ], +) +def test_sync_handler_returns_response(app: ApiGatewayResolver, event): + # GIVEN a sync route handler + @app.get("/my/path") + def get_lambda(): + return Response(200, content_types.TEXT_HTML, "sync response") + + # WHEN resolving the event through the normal chain + result = app(event, {}) + + # THEN the sync handler is called and returns correctly + assert result["statusCode"] == 200 + assert result["body"] == "sync response" + + +@pytest.mark.parametrize( + "app, event", + [ + (ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent), API_REST_EVENT), + (APIGatewayRestResolver(), API_REST_EVENT), + (APIGatewayHttpResolver(), API_RESTV2_EVENT), + ], +) +def test_async_handler_is_awaited(app: ApiGatewayResolver, event): + # GIVEN an async route handler registered on the resolver + @app.get("/my/path") + async def get_lambda(): + return Response(200, content_types.TEXT_HTML, "async response") + + # WHEN populating context and calling the async adapter directly + _setup_resolver_context(app, event) + app.append_context(_route_args={}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN the async handler is awaited and returns correctly + assert result.status_code == 200 + assert result.body == "async response" + + +@pytest.mark.parametrize( + "app, event", + [ + (ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent), API_REST_EVENT), + (APIGatewayRestResolver(), API_REST_EVENT), + (APIGatewayHttpResolver(), API_RESTV2_EVENT), + ], +) +def test_sync_handler_through_adapter(app: ApiGatewayResolver, event): + # GIVEN a sync route handler + @app.get("/my/path") + def get_lambda(): + return Response(200, content_types.TEXT_HTML, "sync via adapter") + + # WHEN calling _registered_api_adapter_async with a sync handler + _setup_resolver_context(app, event) + app.append_context(_route_args={}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN sync handler works through the async adapter without issue + assert result.status_code == 200 + assert result.body == "sync via adapter" + + +@pytest.mark.parametrize( + "app, event", + [ + (ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent), API_REST_EVENT), + (APIGatewayRestResolver(), API_REST_EVENT), + (APIGatewayHttpResolver(), API_RESTV2_EVENT), + ], +) +def test_adapter_passes_route_args_to_async_handler(app: ApiGatewayResolver, event): + # GIVEN an async handler that expects route arguments + async def get_lambda(name: str): + return Response(200, content_types.TEXT_HTML, name) + + # WHEN route_args are set in the context + _setup_resolver_context(app, event) + app.append_context(_route_args={"name": "powertools"}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN the route args are passed to the handler + assert result.status_code == 200 + assert result.body == "powertools" + + +@pytest.mark.parametrize( + "app, event", + [ + (ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent), API_REST_EVENT), + (APIGatewayRestResolver(), API_REST_EVENT), + (APIGatewayHttpResolver(), API_RESTV2_EVENT), + ], +) +def test_adapter_passes_route_args_to_sync_handler(app: ApiGatewayResolver, event): + # GIVEN a sync handler that expects route arguments + def get_lambda(name: str): + return Response(200, content_types.TEXT_HTML, name) + + # WHEN route_args are set in the context + _setup_resolver_context(app, event) + app.append_context(_route_args={"name": "powertools"}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN the route args are passed to the sync handler + assert result.status_code == 200 + assert result.body == "powertools" + + +def test_adapter_converts_dict_response_from_async_handler(): + # GIVEN an async handler that returns a dict (not a Response object) + app = ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent) + + async def get_lambda(): + return {"message": "hello"} + + # WHEN calling through the async adapter + _setup_resolver_context(app, API_REST_EVENT) + app.append_context(_route_args={}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN _to_response normalizes the dict into a Response object + assert result.status_code == 200 + assert result.body is not None + + +def test_adapter_converts_tuple_response_from_async_handler(): + # GIVEN an async handler that returns a (dict, status_code) tuple + app = ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent) + + async def get_lambda(): + return {"created": True}, 201 + + # WHEN calling through the async adapter + _setup_resolver_context(app, API_REST_EVENT) + app.append_context(_route_args={}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN _to_response normalizes the tuple into a Response object + assert result.status_code == 201 + + +def test_adapter_with_no_route_in_context(): + # GIVEN a handler and no _route in context + app = ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent) + + async def get_lambda(): + return Response(200, content_types.TEXT_HTML, "no route") + + # WHEN _route is None in context (default) + _setup_resolver_context(app, API_REST_EVENT) + app.append_context(_route_args={}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN the adapter skips request injection and dependency resolution + assert result.status_code == 200 + assert result.body == "no route" + + +def test_adapter_injects_request_param(): + # GIVEN an async handler that declares a Request parameter + app = APIGatewayHttpResolver() + + async def get_lambda(request: Request): + return Response(200, content_types.TEXT_HTML, request.method) + + # WHEN a Route is present in context with request_param_name not yet checked + _setup_resolver_context(app, API_RESTV2_EVENT) + route = Route( + method="GET", + path="/my/path", + rule=re.compile(r"^/my/path$"), + func=get_lambda, + cors=False, + compress=False, + ) + app.append_context(_route=route, _route_args={}) + + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN the Request object is injected and request_param_name is cached + assert result.status_code == 200 + assert route.request_param_name_checked is True + assert route.request_param_name == "request" + + +def test_adapter_uses_cached_request_param_name(): + # GIVEN a Route where request_param_name was already resolved + app = APIGatewayHttpResolver() + + async def get_lambda(req: Request): + return Response(200, content_types.TEXT_HTML, req.method) + + _setup_resolver_context(app, API_RESTV2_EVENT) + route = Route( + method="GET", + path="/my/path", + rule=re.compile(r"^/my/path$"), + func=get_lambda, + cors=False, + compress=False, + ) + route.request_param_name = "req" + route.request_param_name_checked = True + app.append_context(_route=route, _route_args={}) + + # WHEN calling the adapter a second time (cache hit) + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN it still injects the Request using the cached param name + assert result.status_code == 200 + + +def test_adapter_resolves_dependencies(): + # GIVEN an async handler with Depends() parameters + app = APIGatewayHttpResolver() + + def get_greeting() -> str: + return "hello" + + async def get_lambda(greeting: Annotated[str, Depends(get_greeting)]): + return {"greeting": greeting} + + _setup_resolver_context(app, API_RESTV2_EVENT) + route = Route( + method="GET", + path="/my/path", + rule=re.compile(r"^/my/path$"), + func=get_lambda, + cors=False, + compress=False, + ) + app.append_context(_route=route, _route_args={}) + + # WHEN calling the adapter + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN dependencies are resolved and injected + assert result.status_code == 200 + + +def test_adapter_resolves_dependencies_with_sync_handler(): + # GIVEN a sync handler with Depends() parameters + app = APIGatewayHttpResolver() + + def get_greeting() -> str: + return "hello" + + def get_lambda(greeting: Annotated[str, Depends(get_greeting)]): + return {"greeting": greeting} + + _setup_resolver_context(app, API_RESTV2_EVENT) + route = Route( + method="GET", + path="/my/path", + rule=re.compile(r"^/my/path$"), + func=get_lambda, + cors=False, + compress=False, + ) + app.append_context(_route=route, _route_args={}) + + # WHEN calling the adapter with a sync handler that has dependencies + result = asyncio.run( + _registered_api_adapter_async(app, get_lambda), + ) + + # THEN dependencies are resolved and injected for sync handler too + assert result.status_code == 200 From 02900105e129a61fcb292847fe8286c755655c8d Mon Sep 17 00:00:00 2001 From: Amr Abed <3361565+amrabed@users.noreply.github.com> Date: Mon, 20 Apr 2026 06:29:19 -0400 Subject: [PATCH 55/84] docs: add lambda templates content (#8159) * Add blog post * Add GitHub repository * Address PR comments --- docs/we_made_this.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/we_made_this.md b/docs/we_made_this.md index b8a3445cc4f..07370d53d9e 100644 --- a/docs/we_made_this.md +++ b/docs/we_made_this.md @@ -156,6 +156,14 @@ Learn to implement data masking in AWS Lambda with Powertools, protecting sensit [Simplified Data Masking in AWS Lambda with Powertools](https://www.internetkatta.com/simplified-data-masking-in-aws-lambda-with-powertool){target="_blank" rel="nofollow"} +### Stop writing Lambda boilerplate + +Introducing the [AWS Lambda Templates](https://github.com/amrabed/aws-lambda-templates){target="_blank"} repository — a collection of production-ready Python Lambda templates for Bedrock Agent, REST API, GraphQL, DynamoDB Stream, EventBridge, S3, and SQS scenarios, pre-wired with Powertools for AWS Lambda, AWS CDK, Pydantic, and a robust testing infrastructure. + +> **Author: [Amr Abed :material-linkedin:](https://www.linkedin.com/in/amrabed){target="_blank" rel="nofollow"}** + +[Stop Writing Lambda Boilerplate](https://builder.aws.com/content/3CDoe07m8JBNTQyzcrYWTWkfNPz/stop-writing-lambda-boilerplate){target="_blank" rel="nofollow"} + ## Videos #### Building a resilient input handling with Parser From 1025f07290f5c7cdaca085f7854bdaa283f18005 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 20 Apr 2026 13:14:06 +0100 Subject: [PATCH 56/84] feat: add AsyncMiddlewareFrame support (#8158) * feat: adding AsyncMiddlewareFrame support * feat: adding AsyncMiddlewareFrame support --- .../event_handler/middlewares/async_utils.py | 50 ++++ .../test_async_middleware_frame.py | 214 ++++++++++++++++++ 2 files changed, 264 insertions(+) create mode 100644 tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py diff --git a/aws_lambda_powertools/event_handler/middlewares/async_utils.py b/aws_lambda_powertools/event_handler/middlewares/async_utils.py index 469ed1e96b1..d372790fbcf 100644 --- a/aws_lambda_powertools/event_handler/middlewares/async_utils.py +++ b/aws_lambda_powertools/event_handler/middlewares/async_utils.py @@ -110,6 +110,56 @@ def run_middleware() -> None: return middleware_result_holder[0] +class AsyncMiddlewareFrame: + """Async version of MiddlewareFrame for the async middleware chain. + + Each instance wraps a middleware (sync or async) and the next handler in the stack. + When called, it auto-detects whether the current middleware is sync or async: + + - **Async middleware**: awaited directly with ``(app, next_middleware)`` + - **Sync middleware**: executed in a background thread so the event loop is never blocked + + Parameters + ---------- + current_middleware : Callable + The current middleware function to be called as a request is processed. + next_middleware : Callable + The next middleware in the middleware stack. + """ + + def __init__( + self, + current_middleware: Callable[..., Any], + next_middleware: Callable[..., Any], + ) -> None: + self.current_middleware: Callable[..., Any] = current_middleware + self.next_middleware: Callable[..., Any] = next_middleware + self._next_middleware_name = next_middleware.__name__ + + @property + def __name__(self) -> str: # noqa: A003 + return self.current_middleware.__name__ + + def __str__(self) -> str: + middleware_name = self.__name__ + return f"[{middleware_name}] next call chain is {middleware_name} -> {self._next_middleware_name}" + + async def __call__(self, app: ApiGatewayResolver) -> dict | tuple | Response: + logger.debug("AsyncMiddlewareFrame: %s", self) + app._push_processed_stack_frame(str(self)) + + if inspect.iscoroutinefunction(self.current_middleware): + return await self.current_middleware(app, self.next_middleware) + + loop = asyncio.get_running_loop() + + def sync_next(app: ApiGatewayResolver) -> Any: + future = asyncio.run_coroutine_threadsafe(self.next_middleware(app), loop) + return future.result() + + return await asyncio.to_thread(self.current_middleware, app, sync_next) + + async def _registered_api_adapter_async( app: ApiGatewayResolver, next_middleware: Callable[..., Any], diff --git a/tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py b/tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py new file mode 100644 index 00000000000..b833ee19fae --- /dev/null +++ b/tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py @@ -0,0 +1,214 @@ +import asyncio + +from aws_lambda_powertools.event_handler import content_types +from aws_lambda_powertools.event_handler.api_gateway import ( + ApiGatewayResolver, + ProxyEventType, + Response, +) +from aws_lambda_powertools.event_handler.middlewares import NextMiddleware +from aws_lambda_powertools.event_handler.middlewares.async_utils import AsyncMiddlewareFrame +from tests.functional.utils import load_event + +API_REST_EVENT = load_event("apiGatewayProxyEvent.json") + + +def _make_app() -> ApiGatewayResolver: + app = ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent) + app.current_event = app._to_proxy_event(API_REST_EVENT) + app.lambda_context = {} + return app + + +class TestAsyncMiddlewareFrameWithAsyncMiddleware: + def test_async_middleware_is_awaited(self): + # GIVEN an async middleware and an async next handler + app = _make_app() + + async def my_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(middleware_called=True) + return await next_middleware(app) + + async def next_handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "from handler") + + frame = AsyncMiddlewareFrame(current_middleware=my_middleware, next_middleware=next_handler) + + # WHEN calling the frame + result = asyncio.run(frame(app)) + + # THEN the async middleware is invoked and the chain proceeds + assert result.status_code == 200 + assert result.body == "from handler" + assert app.context.get("middleware_called") is True + + def test_async_middleware_can_short_circuit(self): + # GIVEN an async middleware that returns early without calling next + app = _make_app() + + async def blocking_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + await asyncio.sleep(0) + return Response(403, content_types.TEXT_PLAIN, "forbidden") + + async def next_handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "should not reach") + + frame = AsyncMiddlewareFrame(current_middleware=blocking_middleware, next_middleware=next_handler) + + # WHEN calling the frame + result = asyncio.run(frame(app)) + + # THEN the middleware short-circuits the chain + assert result.status_code == 403 + assert result.body == "forbidden" + + def test_multiple_async_middlewares_chained(self): + # GIVEN two async middlewares chained together + app = _make_app() + + async def first_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(first=True) + return await next_middleware(app) + + async def second_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(second=True) + return await next_middleware(app) + + async def final_handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "done") + + # WHEN building a chain: first -> second -> handler + inner_frame = AsyncMiddlewareFrame(current_middleware=second_middleware, next_middleware=final_handler) + outer_frame = AsyncMiddlewareFrame(current_middleware=first_middleware, next_middleware=inner_frame) + + result = asyncio.run(outer_frame(app)) + + # THEN both middlewares run in order + assert result.status_code == 200 + assert app.context.get("first") is True + assert app.context.get("second") is True + + +class TestAsyncMiddlewareFrameWithSyncMiddleware: + def test_sync_middleware_is_bridged(self): + # GIVEN a sync middleware and an async next handler + app = _make_app() + + def sync_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(sync_called=True) + return next_middleware(app) + + async def next_handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "async handler") + + frame = AsyncMiddlewareFrame(current_middleware=sync_middleware, next_middleware=next_handler) + + # WHEN calling the frame + result = asyncio.run(frame(app)) + + # THEN the sync middleware is bridged via wrap_middleware_async + assert result.status_code == 200 + assert result.body == "async handler" + assert app.context.get("sync_called") is True + + def test_sync_middleware_can_short_circuit(self): + # GIVEN a sync middleware that returns early + app = _make_app() + + def sync_blocking(app: ApiGatewayResolver, next_middleware: NextMiddleware): + return Response(401, content_types.TEXT_PLAIN, "unauthorized") + + async def next_handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "should not reach") + + frame = AsyncMiddlewareFrame(current_middleware=sync_blocking, next_middleware=next_handler) + + # WHEN calling the frame + result = asyncio.run(frame(app)) + + # THEN the sync middleware short-circuits + assert result.status_code == 401 + assert result.body == "unauthorized" + + +class TestAsyncMiddlewareFrameMixedChain: + def test_sync_then_async_middleware(self): + # GIVEN a chain with sync middleware followed by async middleware + app = _make_app() + + def sync_mw(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(sync_ran=True) + return next_middleware(app) + + async def async_mw(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(async_ran=True) + return await next_middleware(app) + + async def handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "mixed chain") + + inner = AsyncMiddlewareFrame(current_middleware=async_mw, next_middleware=handler) + outer = AsyncMiddlewareFrame(current_middleware=sync_mw, next_middleware=inner) + + # WHEN calling the chain + result = asyncio.run(outer(app)) + + # THEN both middlewares execute in order + assert result.status_code == 200 + assert app.context.get("sync_ran") is True + assert app.context.get("async_ran") is True + + +class TestAsyncMiddlewareFrameProperties: + def test_name_property(self): + # GIVEN a middleware with a known name + def my_named_middleware(app, next_mw): + return next_mw(app) + + def next_handler(app): + return Response(200, content_types.TEXT_HTML, "ok") + + frame = AsyncMiddlewareFrame(current_middleware=my_named_middleware, next_middleware=next_handler) + + # THEN __name__ returns the current middleware name + assert frame.__name__ == "my_named_middleware" + + def test_str_representation(self): + # GIVEN a frame with named middleware and next handler + def auth_middleware(app, next_mw): + return next_mw(app) + + def logging_middleware(app): + return Response(200, content_types.TEXT_HTML, "ok") + + frame = AsyncMiddlewareFrame(current_middleware=auth_middleware, next_middleware=logging_middleware) + + # THEN str() shows the call chain + assert str(frame) == "[auth_middleware] next call chain is auth_middleware -> logging_middleware" + + def test_pushes_processed_stack_frame(self): + # GIVEN a frame + app = _make_app() + + async def my_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + return await next_middleware(app) + + async def handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "ok") + + frame = AsyncMiddlewareFrame(current_middleware=my_middleware, next_middleware=handler) + app._reset_processed_stack() + + # WHEN calling the frame + asyncio.run(frame(app)) + + # THEN the processed stack frame is recorded for debugging + assert len(app.processed_stack_frames) > 0 + assert "my_middleware" in app.processed_stack_frames[0] From d45302cd0b81281dffec3a58bded23a6215fd3a8 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 21 Apr 2026 08:42:43 +0100 Subject: [PATCH 57/84] chore(deps): batch update dependencies (#8168) - actions/setup-node 6.3.0 -> 6.4.0 - aws-cdk 2.1118.0 -> 2.1118.4 - aws-cdk-aws-lambda-python-alpha 2.248.0a0 -> 2.250.0a0 - boto3-stubs 1.42.84 -> 1.42.92 - ruff 0.15.10 -> 0.15.11 - ty 0.0.29 -> 0.0.32 - types-requests 2.33.0.20260402 -> 2.33.0.20260408 Co-authored-by: Claude Opus 4.6 --- .github/workflows/bootstrap_region.yml | 2 +- .github/workflows/publish_v3_layer.yml | 2 +- .../reusable_deploy_v3_layer_stack.yml | 2 +- .github/workflows/reusable_deploy_v3_sar.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- package-lock.json | 8 +- package.json | 2 +- poetry.lock | 114 +++++++++--------- pyproject.toml | 4 +- 9 files changed, 72 insertions(+), 66 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index ab10d310b0e..7bbfab18d76 100644 --- a/.github/workflows/bootstrap_region.yml +++ b/.github/workflows/bootstrap_region.yml @@ -48,7 +48,7 @@ jobs: with: ref: ${{ github.sha }} - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - name: Setup dependencies diff --git a/.github/workflows/publish_v3_layer.yml b/.github/workflows/publish_v3_layer.yml index 200e850675f..958402adf98 100644 --- a/.github/workflows/publish_v3_layer.yml +++ b/.github/workflows/publish_v3_layer.yml @@ -123,7 +123,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: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "18.20.4" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index 8112b19d953..a2ef355989f 100644 --- a/.github/workflows/reusable_deploy_v3_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v3_layer_stack.yml @@ -163,7 +163,7 @@ jobs: role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} mask-aws-account-id: true - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "18.20.4" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v3_sar.yml b/.github/workflows/reusable_deploy_v3_sar.yml index 17f63216996..67dcc7d44b7 100644 --- a/.github/workflows/reusable_deploy_v3_sar.yml +++ b/.github/workflows/reusable_deploy_v3_sar.yml @@ -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@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ env.NODE_VERSION }} - name: Download artifact diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 6a1e861d3de..dea1cc9e065 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -62,7 +62,7 @@ jobs: architecture: "x64" cache: "poetry" - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "20.10.0" - name: Install CDK CLI diff --git a/package-lock.json b/package-lock.json index faae155108c..bc967b5af6e 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.1118.0" + "aws-cdk": "^2.1118.4" } }, "node_modules/aws-cdk": { - "version": "2.1118.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1118.0.tgz", - "integrity": "sha512-Tfd865GRewDTXIbTVtix/l+v8t3rZENvdHcQQZS2wXYVXfHzljULFXe9JKkgZUNDPB1zo9tSBUu8jjiHRm7nWg==", + "version": "2.1118.4", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1118.4.tgz", + "integrity": "sha512-wJfRQdvb+FJ2cni059mYdmjhfwhMskP+PAB59BL9jhon+jYtjy8X3pbj3uzHgAOJwNhh6jGkP8xq36Cffccbbw==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 2820cd2f584..93ad13c3b51 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.1118.0" + "aws-cdk": "^2.1118.4" } } diff --git a/poetry.lock b/poetry.lock index 649b08915ab..0d9844350aa 100644 --- a/poetry.lock +++ b/poetry.lock @@ -205,18 +205,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-lambda-python-alpha" -version = "2.248.0a0" +version = "2.250.0a0" description = "The CDK Construct Library for AWS Lambda in Python" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_aws_lambda_python_alpha-2.248.0a0-py3-none-any.whl", hash = "sha256:bf9303515649511fb5299ef36cfcdc042f3422de05321ed30f565dcb3642737f"}, - {file = "aws_cdk_aws_lambda_python_alpha-2.248.0a0.tar.gz", hash = "sha256:2b5f4f3a2ca249355fd86509da800ae36b2e368cfec76372dc3dd25f25ef23af"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.250.0a0-py3-none-any.whl", hash = "sha256:792b8d64fca6089908f9d3462a9dd81a32493fd1422d50d0fd73592590b83c0b"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.250.0a0.tar.gz", hash = "sha256:55b09a9f31a7267c5ec10f1f64e8e1d3709eaad4738fd49e170671d1fa984f60"}, ] [package.dependencies] -aws-cdk-lib = ">=2.248.0,<3.0.0" +aws-cdk-lib = ">=2.250.0,<3.0.0" constructs = ">=10.5.0,<11.0.0" jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" @@ -241,14 +241,14 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.249.0" +version = "2.250.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.249.0-py3-none-any.whl", hash = "sha256:c36a7891027c6252479b26ddb3e21bdc54d1fdf403c7928c8da6e8040e4674fa"}, - {file = "aws_cdk_lib-2.249.0.tar.gz", hash = "sha256:7a4c27b3b22253c099696e54dc6cdd193b718c8d43fd692f91c820921a15dc6e"}, + {file = "aws_cdk_lib-2.250.0-py3-none-any.whl", hash = "sha256:427c9a062f350c16e301326fd6ca0440428f9cc0e85421aaa69a9afa57228acc"}, + {file = "aws_cdk_lib-2.250.0.tar.gz", hash = "sha256:6e5cb8def9208a45cede1376a81d7508b3889879ccc7e9cddaa4fd807da0b144"}, ] [package.dependencies] @@ -453,14 +453,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "boto3-stubs" -version = "1.42.84" -description = "Type annotations for boto3 1.42.84 generated with mypy-boto3-builder 8.12.0" +version = "1.42.92" +description = "Type annotations for boto3 1.42.92 generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "boto3_stubs-1.42.84-py3-none-any.whl", hash = "sha256:73c3f47fc18e27dfe6f17c1c4d3ee48ab6f926d1b7029d15e6771c8255a6f278"}, - {file = "boto3_stubs-1.42.84.tar.gz", hash = "sha256:c517c254e1d8f00af24f7df55c8b1061d1142405c5ac07e426ee2b5b709f3362"}, + {file = "boto3_stubs-1.42.92-py3-none-any.whl", hash = "sha256:b3994e60f0133b2dd3d9a88ceaeef48fa6367d9a9429426e919575768a1ad9c6"}, + {file = "boto3_stubs-1.42.92.tar.gz", hash = "sha256:4bc934069c5e8c7b3cdd2442569dae14e8272fe207d445bd38aa578b8463638f"}, ] [package.dependencies] @@ -485,7 +485,7 @@ account = ["mypy-boto3-account (>=1.42.0,<1.43.0)"] acm = ["mypy-boto3-acm (>=1.42.0,<1.43.0)"] acm-pca = ["mypy-boto3-acm-pca (>=1.42.0,<1.43.0)"] aiops = ["mypy-boto3-aiops (>=1.42.0,<1.43.0)"] -all = ["mypy-boto3-accessanalyzer (>=1.42.0,<1.43.0)", "mypy-boto3-account (>=1.42.0,<1.43.0)", "mypy-boto3-acm (>=1.42.0,<1.43.0)", "mypy-boto3-acm-pca (>=1.42.0,<1.43.0)", "mypy-boto3-aiops (>=1.42.0,<1.43.0)", "mypy-boto3-amp (>=1.42.0,<1.43.0)", "mypy-boto3-amplify (>=1.42.0,<1.43.0)", "mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)", "mypy-boto3-amplifyuibuilder (>=1.42.0,<1.43.0)", "mypy-boto3-apigateway (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewaymanagementapi (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewayv2 (>=1.42.0,<1.43.0)", "mypy-boto3-appconfig (>=1.42.0,<1.43.0)", "mypy-boto3-appconfigdata (>=1.42.0,<1.43.0)", "mypy-boto3-appfabric (>=1.42.0,<1.43.0)", "mypy-boto3-appflow (>=1.42.0,<1.43.0)", "mypy-boto3-appintegrations (>=1.42.0,<1.43.0)", "mypy-boto3-application-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-application-insights (>=1.42.0,<1.43.0)", "mypy-boto3-application-signals (>=1.42.0,<1.43.0)", "mypy-boto3-applicationcostprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-appmesh (>=1.42.0,<1.43.0)", "mypy-boto3-apprunner (>=1.42.0,<1.43.0)", "mypy-boto3-appstream (>=1.42.0,<1.43.0)", "mypy-boto3-appsync (>=1.42.0,<1.43.0)", "mypy-boto3-arc-region-switch (>=1.42.0,<1.43.0)", "mypy-boto3-arc-zonal-shift (>=1.42.0,<1.43.0)", "mypy-boto3-artifact (>=1.42.0,<1.43.0)", "mypy-boto3-athena (>=1.42.0,<1.43.0)", "mypy-boto3-auditmanager (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling-plans (>=1.42.0,<1.43.0)", "mypy-boto3-b2bi (>=1.42.0,<1.43.0)", "mypy-boto3-backup (>=1.42.0,<1.43.0)", "mypy-boto3-backup-gateway (>=1.42.0,<1.43.0)", "mypy-boto3-backupsearch (>=1.42.0,<1.43.0)", "mypy-boto3-batch (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-dashboards (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-data-exports (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-pricing-calculator (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-recommended-actions (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore-control (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-billing (>=1.42.0,<1.43.0)", "mypy-boto3-billingconductor (>=1.42.0,<1.43.0)", "mypy-boto3-braket (>=1.42.0,<1.43.0)", "mypy-boto3-budgets (>=1.42.0,<1.43.0)", "mypy-boto3-ce (>=1.42.0,<1.43.0)", "mypy-boto3-chatbot (>=1.42.0,<1.43.0)", "mypy-boto3-chime (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-identity (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-meetings (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-messaging (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-voice (>=1.42.0,<1.43.0)", "mypy-boto3-cleanrooms (>=1.42.0,<1.43.0)", "mypy-boto3-cleanroomsml (>=1.42.0,<1.43.0)", "mypy-boto3-cloud9 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudcontrol (>=1.42.0,<1.43.0)", "mypy-boto3-clouddirectory (>=1.42.0,<1.43.0)", "mypy-boto3-cloudformation (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsm (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsmv2 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearch (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearchdomain (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail-data (>=1.42.0,<1.43.0)", "mypy-boto3-cloudwatch (>=1.42.0,<1.43.0)", "mypy-boto3-codeartifact (>=1.42.0,<1.43.0)", "mypy-boto3-codebuild (>=1.42.0,<1.43.0)", "mypy-boto3-codecatalyst (>=1.42.0,<1.43.0)", "mypy-boto3-codecommit (>=1.42.0,<1.43.0)", "mypy-boto3-codeconnections (>=1.42.0,<1.43.0)", "mypy-boto3-codedeploy (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-reviewer (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-security (>=1.42.0,<1.43.0)", "mypy-boto3-codeguruprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-codepipeline (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-connections (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-identity (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-idp (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-sync (>=1.42.0,<1.43.0)", "mypy-boto3-comprehend (>=1.42.0,<1.43.0)", "mypy-boto3-comprehendmedical (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer-automation (>=1.42.0,<1.43.0)", "mypy-boto3-config (>=1.42.0,<1.43.0)", "mypy-boto3-connect (>=1.42.0,<1.43.0)", "mypy-boto3-connect-contact-lens (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaigns (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaignsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-connectcases (>=1.42.0,<1.43.0)", "mypy-boto3-connecthealth (>=1.42.0,<1.43.0)", "mypy-boto3-connectparticipant (>=1.42.0,<1.43.0)", "mypy-boto3-controlcatalog (>=1.42.0,<1.43.0)", "mypy-boto3-controltower (>=1.42.0,<1.43.0)", "mypy-boto3-cost-optimization-hub (>=1.42.0,<1.43.0)", "mypy-boto3-cur (>=1.42.0,<1.43.0)", "mypy-boto3-customer-profiles (>=1.42.0,<1.43.0)", "mypy-boto3-databrew (>=1.42.0,<1.43.0)", "mypy-boto3-dataexchange (>=1.42.0,<1.43.0)", "mypy-boto3-datapipeline (>=1.42.0,<1.43.0)", "mypy-boto3-datasync (>=1.42.0,<1.43.0)", "mypy-boto3-datazone (>=1.42.0,<1.43.0)", "mypy-boto3-dax (>=1.42.0,<1.43.0)", "mypy-boto3-deadline (>=1.42.0,<1.43.0)", "mypy-boto3-detective (>=1.42.0,<1.43.0)", "mypy-boto3-devicefarm (>=1.42.0,<1.43.0)", "mypy-boto3-devops-agent (>=1.42.0,<1.43.0)", "mypy-boto3-devops-guru (>=1.42.0,<1.43.0)", "mypy-boto3-directconnect (>=1.42.0,<1.43.0)", "mypy-boto3-discovery (>=1.42.0,<1.43.0)", "mypy-boto3-dlm (>=1.42.0,<1.43.0)", "mypy-boto3-dms (>=1.42.0,<1.43.0)", "mypy-boto3-docdb (>=1.42.0,<1.43.0)", "mypy-boto3-docdb-elastic (>=1.42.0,<1.43.0)", "mypy-boto3-drs (>=1.42.0,<1.43.0)", "mypy-boto3-ds (>=1.42.0,<1.43.0)", "mypy-boto3-ds-data (>=1.42.0,<1.43.0)", "mypy-boto3-dsql (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodb (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodbstreams (>=1.42.0,<1.43.0)", "mypy-boto3-ebs (>=1.42.0,<1.43.0)", "mypy-boto3-ec2 (>=1.42.0,<1.43.0)", "mypy-boto3-ec2-instance-connect (>=1.42.0,<1.43.0)", "mypy-boto3-ecr (>=1.42.0,<1.43.0)", "mypy-boto3-ecr-public (>=1.42.0,<1.43.0)", "mypy-boto3-ecs (>=1.42.0,<1.43.0)", "mypy-boto3-efs (>=1.42.0,<1.43.0)", "mypy-boto3-eks (>=1.42.0,<1.43.0)", "mypy-boto3-eks-auth (>=1.42.0,<1.43.0)", "mypy-boto3-elasticache (>=1.42.0,<1.43.0)", "mypy-boto3-elasticbeanstalk (>=1.42.0,<1.43.0)", "mypy-boto3-elb (>=1.42.0,<1.43.0)", "mypy-boto3-elbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-elementalinference (>=1.42.0,<1.43.0)", "mypy-boto3-emr (>=1.42.0,<1.43.0)", "mypy-boto3-emr-containers (>=1.42.0,<1.43.0)", "mypy-boto3-emr-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-entityresolution (>=1.42.0,<1.43.0)", "mypy-boto3-es (>=1.42.0,<1.43.0)", "mypy-boto3-events (>=1.42.0,<1.43.0)", "mypy-boto3-evs (>=1.42.0,<1.43.0)", "mypy-boto3-finspace (>=1.42.0,<1.43.0)", "mypy-boto3-finspace-data (>=1.42.0,<1.43.0)", "mypy-boto3-firehose (>=1.42.0,<1.43.0)", "mypy-boto3-fis (>=1.42.0,<1.43.0)", "mypy-boto3-fms (>=1.42.0,<1.43.0)", "mypy-boto3-forecast (>=1.42.0,<1.43.0)", "mypy-boto3-forecastquery (>=1.42.0,<1.43.0)", "mypy-boto3-frauddetector (>=1.42.0,<1.43.0)", "mypy-boto3-freetier (>=1.42.0,<1.43.0)", "mypy-boto3-fsx (>=1.42.0,<1.43.0)", "mypy-boto3-gamelift (>=1.42.0,<1.43.0)", "mypy-boto3-gameliftstreams (>=1.42.0,<1.43.0)", "mypy-boto3-geo-maps (>=1.42.0,<1.43.0)", "mypy-boto3-geo-places (>=1.42.0,<1.43.0)", "mypy-boto3-geo-routes (>=1.42.0,<1.43.0)", "mypy-boto3-glacier (>=1.42.0,<1.43.0)", "mypy-boto3-globalaccelerator (>=1.42.0,<1.43.0)", "mypy-boto3-glue (>=1.42.0,<1.43.0)", "mypy-boto3-grafana (>=1.42.0,<1.43.0)", "mypy-boto3-greengrass (>=1.42.0,<1.43.0)", "mypy-boto3-greengrassv2 (>=1.42.0,<1.43.0)", "mypy-boto3-groundstation (>=1.42.0,<1.43.0)", "mypy-boto3-guardduty (>=1.42.0,<1.43.0)", "mypy-boto3-health (>=1.42.0,<1.43.0)", "mypy-boto3-healthlake (>=1.42.0,<1.43.0)", "mypy-boto3-iam (>=1.42.0,<1.43.0)", "mypy-boto3-identitystore (>=1.42.0,<1.43.0)", "mypy-boto3-imagebuilder (>=1.42.0,<1.43.0)", "mypy-boto3-importexport (>=1.42.0,<1.43.0)", "mypy-boto3-inspector (>=1.42.0,<1.43.0)", "mypy-boto3-inspector-scan (>=1.42.0,<1.43.0)", "mypy-boto3-inspector2 (>=1.42.0,<1.43.0)", "mypy-boto3-internetmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-invoicing (>=1.42.0,<1.43.0)", "mypy-boto3-iot (>=1.42.0,<1.43.0)", "mypy-boto3-iot-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-jobs-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-managed-integrations (>=1.42.0,<1.43.0)", "mypy-boto3-iotdeviceadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents-data (>=1.42.0,<1.43.0)", "mypy-boto3-iotfleetwise (>=1.42.0,<1.43.0)", "mypy-boto3-iotsecuretunneling (>=1.42.0,<1.43.0)", "mypy-boto3-iotsitewise (>=1.42.0,<1.43.0)", "mypy-boto3-iotthingsgraph (>=1.42.0,<1.43.0)", "mypy-boto3-iottwinmaker (>=1.42.0,<1.43.0)", "mypy-boto3-iotwireless (>=1.42.0,<1.43.0)", "mypy-boto3-ivs (>=1.42.0,<1.43.0)", "mypy-boto3-ivs-realtime (>=1.42.0,<1.43.0)", "mypy-boto3-ivschat (>=1.42.0,<1.43.0)", "mypy-boto3-kafka (>=1.42.0,<1.43.0)", "mypy-boto3-kafkaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-kendra (>=1.42.0,<1.43.0)", "mypy-boto3-kendra-ranking (>=1.42.0,<1.43.0)", "mypy-boto3-keyspaces (>=1.42.0,<1.43.0)", "mypy-boto3-keyspacesstreams (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-archived-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-signaling (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisvideo (>=1.42.0,<1.43.0)", "mypy-boto3-kms (>=1.42.0,<1.43.0)", "mypy-boto3-lakeformation (>=1.42.0,<1.43.0)", "mypy-boto3-lambda (>=1.42.0,<1.43.0)", "mypy-boto3-launch-wizard (>=1.42.0,<1.43.0)", "mypy-boto3-lex-models (>=1.42.0,<1.43.0)", "mypy-boto3-lex-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-models (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-lightsail (>=1.42.0,<1.43.0)", "mypy-boto3-location (>=1.42.0,<1.43.0)", "mypy-boto3-logs (>=1.42.0,<1.43.0)", "mypy-boto3-lookoutequipment (>=1.42.0,<1.43.0)", "mypy-boto3-m2 (>=1.42.0,<1.43.0)", "mypy-boto3-machinelearning (>=1.42.0,<1.43.0)", "mypy-boto3-macie2 (>=1.42.0,<1.43.0)", "mypy-boto3-mailmanager (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain-query (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-agreement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-catalog (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-deployment (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-entitlement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-reporting (>=1.42.0,<1.43.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconvert (>=1.42.0,<1.43.0)", "mypy-boto3-medialive (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage-vod (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackagev2 (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore-data (>=1.42.0,<1.43.0)", "mypy-boto3-mediatailor (>=1.42.0,<1.43.0)", "mypy-boto3-medical-imaging (>=1.42.0,<1.43.0)", "mypy-boto3-memorydb (>=1.42.0,<1.43.0)", "mypy-boto3-meteringmarketplace (>=1.42.0,<1.43.0)", "mypy-boto3-mgh (>=1.42.0,<1.43.0)", "mypy-boto3-mgn (>=1.42.0,<1.43.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhub-config (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhuborchestrator (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhubstrategy (>=1.42.0,<1.43.0)", "mypy-boto3-mpa (>=1.42.0,<1.43.0)", "mypy-boto3-mq (>=1.42.0,<1.43.0)", "mypy-boto3-mturk (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-neptune (>=1.42.0,<1.43.0)", "mypy-boto3-neptune-graph (>=1.42.0,<1.43.0)", "mypy-boto3-neptunedata (>=1.42.0,<1.43.0)", "mypy-boto3-network-firewall (>=1.42.0,<1.43.0)", "mypy-boto3-networkflowmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-networkmanager (>=1.42.0,<1.43.0)", "mypy-boto3-networkmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-notificationscontacts (>=1.42.0,<1.43.0)", "mypy-boto3-nova-act (>=1.42.0,<1.43.0)", "mypy-boto3-oam (>=1.42.0,<1.43.0)", "mypy-boto3-observabilityadmin (>=1.42.0,<1.43.0)", "mypy-boto3-odb (>=1.42.0,<1.43.0)", "mypy-boto3-omics (>=1.42.0,<1.43.0)", "mypy-boto3-opensearch (>=1.42.0,<1.43.0)", "mypy-boto3-opensearchserverless (>=1.42.0,<1.43.0)", "mypy-boto3-organizations (>=1.42.0,<1.43.0)", "mypy-boto3-osis (>=1.42.0,<1.43.0)", "mypy-boto3-outposts (>=1.42.0,<1.43.0)", "mypy-boto3-panorama (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-account (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-benefits (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-channel (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-selling (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography-data (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-ad (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-scep (>=1.42.0,<1.43.0)", "mypy-boto3-pcs (>=1.42.0,<1.43.0)", "mypy-boto3-personalize (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-events (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-pi (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-email (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.42.0,<1.43.0)", "mypy-boto3-pipes (>=1.42.0,<1.43.0)", "mypy-boto3-polly (>=1.42.0,<1.43.0)", "mypy-boto3-pricing (>=1.42.0,<1.43.0)", "mypy-boto3-proton (>=1.42.0,<1.43.0)", "mypy-boto3-qapps (>=1.42.0,<1.43.0)", "mypy-boto3-qbusiness (>=1.42.0,<1.43.0)", "mypy-boto3-qconnect (>=1.42.0,<1.43.0)", "mypy-boto3-quicksight (>=1.42.0,<1.43.0)", "mypy-boto3-ram (>=1.42.0,<1.43.0)", "mypy-boto3-rbin (>=1.42.0,<1.43.0)", "mypy-boto3-rds (>=1.42.0,<1.43.0)", "mypy-boto3-rds-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-rekognition (>=1.42.0,<1.43.0)", "mypy-boto3-repostspace (>=1.42.0,<1.43.0)", "mypy-boto3-resiliencehub (>=1.42.0,<1.43.0)", "mypy-boto3-resource-explorer-2 (>=1.42.0,<1.43.0)", "mypy-boto3-resource-groups (>=1.42.0,<1.43.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.42.0,<1.43.0)", "mypy-boto3-rolesanywhere (>=1.42.0,<1.43.0)", "mypy-boto3-route53 (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-cluster (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-control-config (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-readiness (>=1.42.0,<1.43.0)", "mypy-boto3-route53domains (>=1.42.0,<1.43.0)", "mypy-boto3-route53globalresolver (>=1.42.0,<1.43.0)", "mypy-boto3-route53profiles (>=1.42.0,<1.43.0)", "mypy-boto3-route53resolver (>=1.42.0,<1.43.0)", "mypy-boto3-rtbfabric (>=1.42.0,<1.43.0)", "mypy-boto3-rum (>=1.42.0,<1.43.0)", "mypy-boto3-s3 (>=1.42.0,<1.43.0)", "mypy-boto3-s3control (>=1.42.0,<1.43.0)", "mypy-boto3-s3outposts (>=1.42.0,<1.43.0)", "mypy-boto3-s3tables (>=1.42.0,<1.43.0)", "mypy-boto3-s3vectors (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-edge (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-geospatial (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-metrics (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-savingsplans (>=1.42.0,<1.43.0)", "mypy-boto3-scheduler (>=1.42.0,<1.43.0)", "mypy-boto3-schemas (>=1.42.0,<1.43.0)", "mypy-boto3-sdb (>=1.42.0,<1.43.0)", "mypy-boto3-secretsmanager (>=1.42.0,<1.43.0)", "mypy-boto3-security-ir (>=1.42.0,<1.43.0)", "mypy-boto3-securityagent (>=1.42.0,<1.43.0)", "mypy-boto3-securityhub (>=1.42.0,<1.43.0)", "mypy-boto3-securitylake (>=1.42.0,<1.43.0)", "mypy-boto3-serverlessrepo (>=1.42.0,<1.43.0)", "mypy-boto3-service-quotas (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog-appregistry (>=1.42.0,<1.43.0)", "mypy-boto3-servicediscovery (>=1.42.0,<1.43.0)", "mypy-boto3-ses (>=1.42.0,<1.43.0)", "mypy-boto3-sesv2 (>=1.42.0,<1.43.0)", "mypy-boto3-shield (>=1.42.0,<1.43.0)", "mypy-boto3-signer (>=1.42.0,<1.43.0)", "mypy-boto3-signer-data (>=1.42.0,<1.43.0)", "mypy-boto3-signin (>=1.42.0,<1.43.0)", "mypy-boto3-simpledbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-simspaceweaver (>=1.42.0,<1.43.0)", "mypy-boto3-snow-device-management (>=1.42.0,<1.43.0)", "mypy-boto3-snowball (>=1.42.0,<1.43.0)", "mypy-boto3-sns (>=1.42.0,<1.43.0)", "mypy-boto3-socialmessaging (>=1.42.0,<1.43.0)", "mypy-boto3-sqs (>=1.42.0,<1.43.0)", "mypy-boto3-ssm (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-contacts (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-guiconnect (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-incidents (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-quicksetup (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-sap (>=1.42.0,<1.43.0)", "mypy-boto3-sso (>=1.42.0,<1.43.0)", "mypy-boto3-sso-admin (>=1.42.0,<1.43.0)", "mypy-boto3-sso-oidc (>=1.42.0,<1.43.0)", "mypy-boto3-stepfunctions (>=1.42.0,<1.43.0)", "mypy-boto3-storagegateway (>=1.42.0,<1.43.0)", "mypy-boto3-sts (>=1.42.0,<1.43.0)", "mypy-boto3-supplychain (>=1.42.0,<1.43.0)", "mypy-boto3-support (>=1.42.0,<1.43.0)", "mypy-boto3-support-app (>=1.42.0,<1.43.0)", "mypy-boto3-sustainability (>=1.42.0,<1.43.0)", "mypy-boto3-swf (>=1.42.0,<1.43.0)", "mypy-boto3-synthetics (>=1.42.0,<1.43.0)", "mypy-boto3-taxsettings (>=1.42.0,<1.43.0)", "mypy-boto3-textract (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-influxdb (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-query (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-write (>=1.42.0,<1.43.0)", "mypy-boto3-tnb (>=1.42.0,<1.43.0)", "mypy-boto3-transcribe (>=1.42.0,<1.43.0)", "mypy-boto3-transfer (>=1.42.0,<1.43.0)", "mypy-boto3-translate (>=1.42.0,<1.43.0)", "mypy-boto3-trustedadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-uxc (>=1.42.0,<1.43.0)", "mypy-boto3-verifiedpermissions (>=1.42.0,<1.43.0)", "mypy-boto3-voice-id (>=1.42.0,<1.43.0)", "mypy-boto3-vpc-lattice (>=1.42.0,<1.43.0)", "mypy-boto3-waf (>=1.42.0,<1.43.0)", "mypy-boto3-waf-regional (>=1.42.0,<1.43.0)", "mypy-boto3-wafv2 (>=1.42.0,<1.43.0)", "mypy-boto3-wellarchitected (>=1.42.0,<1.43.0)", "mypy-boto3-wickr (>=1.42.0,<1.43.0)", "mypy-boto3-wisdom (>=1.42.0,<1.43.0)", "mypy-boto3-workdocs (>=1.42.0,<1.43.0)", "mypy-boto3-workmail (>=1.42.0,<1.43.0)", "mypy-boto3-workmailmessageflow (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-instances (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-thin-client (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-web (>=1.42.0,<1.43.0)", "mypy-boto3-xray (>=1.42.0,<1.43.0)"] +all = ["mypy-boto3-accessanalyzer (>=1.42.0,<1.43.0)", "mypy-boto3-account (>=1.42.0,<1.43.0)", "mypy-boto3-acm (>=1.42.0,<1.43.0)", "mypy-boto3-acm-pca (>=1.42.0,<1.43.0)", "mypy-boto3-aiops (>=1.42.0,<1.43.0)", "mypy-boto3-amp (>=1.42.0,<1.43.0)", "mypy-boto3-amplify (>=1.42.0,<1.43.0)", "mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)", "mypy-boto3-amplifyuibuilder (>=1.42.0,<1.43.0)", "mypy-boto3-apigateway (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewaymanagementapi (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewayv2 (>=1.42.0,<1.43.0)", "mypy-boto3-appconfig (>=1.42.0,<1.43.0)", "mypy-boto3-appconfigdata (>=1.42.0,<1.43.0)", "mypy-boto3-appfabric (>=1.42.0,<1.43.0)", "mypy-boto3-appflow (>=1.42.0,<1.43.0)", "mypy-boto3-appintegrations (>=1.42.0,<1.43.0)", "mypy-boto3-application-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-application-insights (>=1.42.0,<1.43.0)", "mypy-boto3-application-signals (>=1.42.0,<1.43.0)", "mypy-boto3-applicationcostprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-appmesh (>=1.42.0,<1.43.0)", "mypy-boto3-apprunner (>=1.42.0,<1.43.0)", "mypy-boto3-appstream (>=1.42.0,<1.43.0)", "mypy-boto3-appsync (>=1.42.0,<1.43.0)", "mypy-boto3-arc-region-switch (>=1.42.0,<1.43.0)", "mypy-boto3-arc-zonal-shift (>=1.42.0,<1.43.0)", "mypy-boto3-artifact (>=1.42.0,<1.43.0)", "mypy-boto3-athena (>=1.42.0,<1.43.0)", "mypy-boto3-auditmanager (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling-plans (>=1.42.0,<1.43.0)", "mypy-boto3-b2bi (>=1.42.0,<1.43.0)", "mypy-boto3-backup (>=1.42.0,<1.43.0)", "mypy-boto3-backup-gateway (>=1.42.0,<1.43.0)", "mypy-boto3-backupsearch (>=1.42.0,<1.43.0)", "mypy-boto3-batch (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-dashboards (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-data-exports (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-pricing-calculator (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-recommended-actions (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore-control (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-billing (>=1.42.0,<1.43.0)", "mypy-boto3-billingconductor (>=1.42.0,<1.43.0)", "mypy-boto3-braket (>=1.42.0,<1.43.0)", "mypy-boto3-budgets (>=1.42.0,<1.43.0)", "mypy-boto3-ce (>=1.42.0,<1.43.0)", "mypy-boto3-chatbot (>=1.42.0,<1.43.0)", "mypy-boto3-chime (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-identity (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-meetings (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-messaging (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-voice (>=1.42.0,<1.43.0)", "mypy-boto3-cleanrooms (>=1.42.0,<1.43.0)", "mypy-boto3-cleanroomsml (>=1.42.0,<1.43.0)", "mypy-boto3-cloud9 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudcontrol (>=1.42.0,<1.43.0)", "mypy-boto3-clouddirectory (>=1.42.0,<1.43.0)", "mypy-boto3-cloudformation (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsm (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsmv2 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearch (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearchdomain (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail-data (>=1.42.0,<1.43.0)", "mypy-boto3-cloudwatch (>=1.42.0,<1.43.0)", "mypy-boto3-codeartifact (>=1.42.0,<1.43.0)", "mypy-boto3-codebuild (>=1.42.0,<1.43.0)", "mypy-boto3-codecatalyst (>=1.42.0,<1.43.0)", "mypy-boto3-codecommit (>=1.42.0,<1.43.0)", "mypy-boto3-codeconnections (>=1.42.0,<1.43.0)", "mypy-boto3-codedeploy (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-reviewer (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-security (>=1.42.0,<1.43.0)", "mypy-boto3-codeguruprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-codepipeline (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-connections (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-identity (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-idp (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-sync (>=1.42.0,<1.43.0)", "mypy-boto3-comprehend (>=1.42.0,<1.43.0)", "mypy-boto3-comprehendmedical (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer-automation (>=1.42.0,<1.43.0)", "mypy-boto3-config (>=1.42.0,<1.43.0)", "mypy-boto3-connect (>=1.42.0,<1.43.0)", "mypy-boto3-connect-contact-lens (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaigns (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaignsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-connectcases (>=1.42.0,<1.43.0)", "mypy-boto3-connecthealth (>=1.42.0,<1.43.0)", "mypy-boto3-connectparticipant (>=1.42.0,<1.43.0)", "mypy-boto3-controlcatalog (>=1.42.0,<1.43.0)", "mypy-boto3-controltower (>=1.42.0,<1.43.0)", "mypy-boto3-cost-optimization-hub (>=1.42.0,<1.43.0)", "mypy-boto3-cur (>=1.42.0,<1.43.0)", "mypy-boto3-customer-profiles (>=1.42.0,<1.43.0)", "mypy-boto3-databrew (>=1.42.0,<1.43.0)", "mypy-boto3-dataexchange (>=1.42.0,<1.43.0)", "mypy-boto3-datapipeline (>=1.42.0,<1.43.0)", "mypy-boto3-datasync (>=1.42.0,<1.43.0)", "mypy-boto3-datazone (>=1.42.0,<1.43.0)", "mypy-boto3-dax (>=1.42.0,<1.43.0)", "mypy-boto3-deadline (>=1.42.0,<1.43.0)", "mypy-boto3-detective (>=1.42.0,<1.43.0)", "mypy-boto3-devicefarm (>=1.42.0,<1.43.0)", "mypy-boto3-devops-agent (>=1.42.0,<1.43.0)", "mypy-boto3-devops-guru (>=1.42.0,<1.43.0)", "mypy-boto3-directconnect (>=1.42.0,<1.43.0)", "mypy-boto3-discovery (>=1.42.0,<1.43.0)", "mypy-boto3-dlm (>=1.42.0,<1.43.0)", "mypy-boto3-dms (>=1.42.0,<1.43.0)", "mypy-boto3-docdb (>=1.42.0,<1.43.0)", "mypy-boto3-docdb-elastic (>=1.42.0,<1.43.0)", "mypy-boto3-drs (>=1.42.0,<1.43.0)", "mypy-boto3-ds (>=1.42.0,<1.43.0)", "mypy-boto3-ds-data (>=1.42.0,<1.43.0)", "mypy-boto3-dsql (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodb (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodbstreams (>=1.42.0,<1.43.0)", "mypy-boto3-ebs (>=1.42.0,<1.43.0)", "mypy-boto3-ec2 (>=1.42.0,<1.43.0)", "mypy-boto3-ec2-instance-connect (>=1.42.0,<1.43.0)", "mypy-boto3-ecr (>=1.42.0,<1.43.0)", "mypy-boto3-ecr-public (>=1.42.0,<1.43.0)", "mypy-boto3-ecs (>=1.42.0,<1.43.0)", "mypy-boto3-efs (>=1.42.0,<1.43.0)", "mypy-boto3-eks (>=1.42.0,<1.43.0)", "mypy-boto3-eks-auth (>=1.42.0,<1.43.0)", "mypy-boto3-elasticache (>=1.42.0,<1.43.0)", "mypy-boto3-elasticbeanstalk (>=1.42.0,<1.43.0)", "mypy-boto3-elb (>=1.42.0,<1.43.0)", "mypy-boto3-elbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-elementalinference (>=1.42.0,<1.43.0)", "mypy-boto3-emr (>=1.42.0,<1.43.0)", "mypy-boto3-emr-containers (>=1.42.0,<1.43.0)", "mypy-boto3-emr-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-entityresolution (>=1.42.0,<1.43.0)", "mypy-boto3-es (>=1.42.0,<1.43.0)", "mypy-boto3-events (>=1.42.0,<1.43.0)", "mypy-boto3-evs (>=1.42.0,<1.43.0)", "mypy-boto3-finspace (>=1.42.0,<1.43.0)", "mypy-boto3-finspace-data (>=1.42.0,<1.43.0)", "mypy-boto3-firehose (>=1.42.0,<1.43.0)", "mypy-boto3-fis (>=1.42.0,<1.43.0)", "mypy-boto3-fms (>=1.42.0,<1.43.0)", "mypy-boto3-forecast (>=1.42.0,<1.43.0)", "mypy-boto3-forecastquery (>=1.42.0,<1.43.0)", "mypy-boto3-frauddetector (>=1.42.0,<1.43.0)", "mypy-boto3-freetier (>=1.42.0,<1.43.0)", "mypy-boto3-fsx (>=1.42.0,<1.43.0)", "mypy-boto3-gamelift (>=1.42.0,<1.43.0)", "mypy-boto3-gameliftstreams (>=1.42.0,<1.43.0)", "mypy-boto3-geo-maps (>=1.42.0,<1.43.0)", "mypy-boto3-geo-places (>=1.42.0,<1.43.0)", "mypy-boto3-geo-routes (>=1.42.0,<1.43.0)", "mypy-boto3-glacier (>=1.42.0,<1.43.0)", "mypy-boto3-globalaccelerator (>=1.42.0,<1.43.0)", "mypy-boto3-glue (>=1.42.0,<1.43.0)", "mypy-boto3-grafana (>=1.42.0,<1.43.0)", "mypy-boto3-greengrass (>=1.42.0,<1.43.0)", "mypy-boto3-greengrassv2 (>=1.42.0,<1.43.0)", "mypy-boto3-groundstation (>=1.42.0,<1.43.0)", "mypy-boto3-guardduty (>=1.42.0,<1.43.0)", "mypy-boto3-health (>=1.42.0,<1.43.0)", "mypy-boto3-healthlake (>=1.42.0,<1.43.0)", "mypy-boto3-iam (>=1.42.0,<1.43.0)", "mypy-boto3-identitystore (>=1.42.0,<1.43.0)", "mypy-boto3-imagebuilder (>=1.42.0,<1.43.0)", "mypy-boto3-importexport (>=1.42.0,<1.43.0)", "mypy-boto3-inspector (>=1.42.0,<1.43.0)", "mypy-boto3-inspector-scan (>=1.42.0,<1.43.0)", "mypy-boto3-inspector2 (>=1.42.0,<1.43.0)", "mypy-boto3-interconnect (>=1.42.0,<1.43.0)", "mypy-boto3-internetmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-invoicing (>=1.42.0,<1.43.0)", "mypy-boto3-iot (>=1.42.0,<1.43.0)", "mypy-boto3-iot-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-jobs-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-managed-integrations (>=1.42.0,<1.43.0)", "mypy-boto3-iotdeviceadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents-data (>=1.42.0,<1.43.0)", "mypy-boto3-iotfleetwise (>=1.42.0,<1.43.0)", "mypy-boto3-iotsecuretunneling (>=1.42.0,<1.43.0)", "mypy-boto3-iotsitewise (>=1.42.0,<1.43.0)", "mypy-boto3-iotthingsgraph (>=1.42.0,<1.43.0)", "mypy-boto3-iottwinmaker (>=1.42.0,<1.43.0)", "mypy-boto3-iotwireless (>=1.42.0,<1.43.0)", "mypy-boto3-ivs (>=1.42.0,<1.43.0)", "mypy-boto3-ivs-realtime (>=1.42.0,<1.43.0)", "mypy-boto3-ivschat (>=1.42.0,<1.43.0)", "mypy-boto3-kafka (>=1.42.0,<1.43.0)", "mypy-boto3-kafkaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-kendra (>=1.42.0,<1.43.0)", "mypy-boto3-kendra-ranking (>=1.42.0,<1.43.0)", "mypy-boto3-keyspaces (>=1.42.0,<1.43.0)", "mypy-boto3-keyspacesstreams (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-archived-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-signaling (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisvideo (>=1.42.0,<1.43.0)", "mypy-boto3-kms (>=1.42.0,<1.43.0)", "mypy-boto3-lakeformation (>=1.42.0,<1.43.0)", "mypy-boto3-lambda (>=1.42.0,<1.43.0)", "mypy-boto3-launch-wizard (>=1.42.0,<1.43.0)", "mypy-boto3-lex-models (>=1.42.0,<1.43.0)", "mypy-boto3-lex-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-models (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-lightsail (>=1.42.0,<1.43.0)", "mypy-boto3-location (>=1.42.0,<1.43.0)", "mypy-boto3-logs (>=1.42.0,<1.43.0)", "mypy-boto3-lookoutequipment (>=1.42.0,<1.43.0)", "mypy-boto3-m2 (>=1.42.0,<1.43.0)", "mypy-boto3-machinelearning (>=1.42.0,<1.43.0)", "mypy-boto3-macie2 (>=1.42.0,<1.43.0)", "mypy-boto3-mailmanager (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain-query (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-agreement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-catalog (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-deployment (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-discovery (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-entitlement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-reporting (>=1.42.0,<1.43.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconvert (>=1.42.0,<1.43.0)", "mypy-boto3-medialive (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage-vod (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackagev2 (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore-data (>=1.42.0,<1.43.0)", "mypy-boto3-mediatailor (>=1.42.0,<1.43.0)", "mypy-boto3-medical-imaging (>=1.42.0,<1.43.0)", "mypy-boto3-memorydb (>=1.42.0,<1.43.0)", "mypy-boto3-meteringmarketplace (>=1.42.0,<1.43.0)", "mypy-boto3-mgh (>=1.42.0,<1.43.0)", "mypy-boto3-mgn (>=1.42.0,<1.43.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhub-config (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhuborchestrator (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhubstrategy (>=1.42.0,<1.43.0)", "mypy-boto3-mpa (>=1.42.0,<1.43.0)", "mypy-boto3-mq (>=1.42.0,<1.43.0)", "mypy-boto3-mturk (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-neptune (>=1.42.0,<1.43.0)", "mypy-boto3-neptune-graph (>=1.42.0,<1.43.0)", "mypy-boto3-neptunedata (>=1.42.0,<1.43.0)", "mypy-boto3-network-firewall (>=1.42.0,<1.43.0)", "mypy-boto3-networkflowmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-networkmanager (>=1.42.0,<1.43.0)", "mypy-boto3-networkmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-notificationscontacts (>=1.42.0,<1.43.0)", "mypy-boto3-nova-act (>=1.42.0,<1.43.0)", "mypy-boto3-oam (>=1.42.0,<1.43.0)", "mypy-boto3-observabilityadmin (>=1.42.0,<1.43.0)", "mypy-boto3-odb (>=1.42.0,<1.43.0)", "mypy-boto3-omics (>=1.42.0,<1.43.0)", "mypy-boto3-opensearch (>=1.42.0,<1.43.0)", "mypy-boto3-opensearchserverless (>=1.42.0,<1.43.0)", "mypy-boto3-organizations (>=1.42.0,<1.43.0)", "mypy-boto3-osis (>=1.42.0,<1.43.0)", "mypy-boto3-outposts (>=1.42.0,<1.43.0)", "mypy-boto3-panorama (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-account (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-benefits (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-channel (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-selling (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography-data (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-ad (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-scep (>=1.42.0,<1.43.0)", "mypy-boto3-pcs (>=1.42.0,<1.43.0)", "mypy-boto3-personalize (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-events (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-pi (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-email (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.42.0,<1.43.0)", "mypy-boto3-pipes (>=1.42.0,<1.43.0)", "mypy-boto3-polly (>=1.42.0,<1.43.0)", "mypy-boto3-pricing (>=1.42.0,<1.43.0)", "mypy-boto3-proton (>=1.42.0,<1.43.0)", "mypy-boto3-qapps (>=1.42.0,<1.43.0)", "mypy-boto3-qbusiness (>=1.42.0,<1.43.0)", "mypy-boto3-qconnect (>=1.42.0,<1.43.0)", "mypy-boto3-quicksight (>=1.42.0,<1.43.0)", "mypy-boto3-ram (>=1.42.0,<1.43.0)", "mypy-boto3-rbin (>=1.42.0,<1.43.0)", "mypy-boto3-rds (>=1.42.0,<1.43.0)", "mypy-boto3-rds-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-rekognition (>=1.42.0,<1.43.0)", "mypy-boto3-repostspace (>=1.42.0,<1.43.0)", "mypy-boto3-resiliencehub (>=1.42.0,<1.43.0)", "mypy-boto3-resource-explorer-2 (>=1.42.0,<1.43.0)", "mypy-boto3-resource-groups (>=1.42.0,<1.43.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.42.0,<1.43.0)", "mypy-boto3-rolesanywhere (>=1.42.0,<1.43.0)", "mypy-boto3-route53 (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-cluster (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-control-config (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-readiness (>=1.42.0,<1.43.0)", "mypy-boto3-route53domains (>=1.42.0,<1.43.0)", "mypy-boto3-route53globalresolver (>=1.42.0,<1.43.0)", "mypy-boto3-route53profiles (>=1.42.0,<1.43.0)", "mypy-boto3-route53resolver (>=1.42.0,<1.43.0)", "mypy-boto3-rtbfabric (>=1.42.0,<1.43.0)", "mypy-boto3-rum (>=1.42.0,<1.43.0)", "mypy-boto3-s3 (>=1.42.0,<1.43.0)", "mypy-boto3-s3control (>=1.42.0,<1.43.0)", "mypy-boto3-s3files (>=1.42.0,<1.43.0)", "mypy-boto3-s3outposts (>=1.42.0,<1.43.0)", "mypy-boto3-s3tables (>=1.42.0,<1.43.0)", "mypy-boto3-s3vectors (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-edge (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-geospatial (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-metrics (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-savingsplans (>=1.42.0,<1.43.0)", "mypy-boto3-scheduler (>=1.42.0,<1.43.0)", "mypy-boto3-schemas (>=1.42.0,<1.43.0)", "mypy-boto3-sdb (>=1.42.0,<1.43.0)", "mypy-boto3-secretsmanager (>=1.42.0,<1.43.0)", "mypy-boto3-security-ir (>=1.42.0,<1.43.0)", "mypy-boto3-securityagent (>=1.42.0,<1.43.0)", "mypy-boto3-securityhub (>=1.42.0,<1.43.0)", "mypy-boto3-securitylake (>=1.42.0,<1.43.0)", "mypy-boto3-serverlessrepo (>=1.42.0,<1.43.0)", "mypy-boto3-service-quotas (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog-appregistry (>=1.42.0,<1.43.0)", "mypy-boto3-servicediscovery (>=1.42.0,<1.43.0)", "mypy-boto3-ses (>=1.42.0,<1.43.0)", "mypy-boto3-sesv2 (>=1.42.0,<1.43.0)", "mypy-boto3-shield (>=1.42.0,<1.43.0)", "mypy-boto3-signer (>=1.42.0,<1.43.0)", "mypy-boto3-signer-data (>=1.42.0,<1.43.0)", "mypy-boto3-signin (>=1.42.0,<1.43.0)", "mypy-boto3-simpledbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-simspaceweaver (>=1.42.0,<1.43.0)", "mypy-boto3-snow-device-management (>=1.42.0,<1.43.0)", "mypy-boto3-snowball (>=1.42.0,<1.43.0)", "mypy-boto3-sns (>=1.42.0,<1.43.0)", "mypy-boto3-socialmessaging (>=1.42.0,<1.43.0)", "mypy-boto3-sqs (>=1.42.0,<1.43.0)", "mypy-boto3-ssm (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-contacts (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-guiconnect (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-incidents (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-quicksetup (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-sap (>=1.42.0,<1.43.0)", "mypy-boto3-sso (>=1.42.0,<1.43.0)", "mypy-boto3-sso-admin (>=1.42.0,<1.43.0)", "mypy-boto3-sso-oidc (>=1.42.0,<1.43.0)", "mypy-boto3-stepfunctions (>=1.42.0,<1.43.0)", "mypy-boto3-storagegateway (>=1.42.0,<1.43.0)", "mypy-boto3-sts (>=1.42.0,<1.43.0)", "mypy-boto3-supplychain (>=1.42.0,<1.43.0)", "mypy-boto3-support (>=1.42.0,<1.43.0)", "mypy-boto3-support-app (>=1.42.0,<1.43.0)", "mypy-boto3-sustainability (>=1.42.0,<1.43.0)", "mypy-boto3-swf (>=1.42.0,<1.43.0)", "mypy-boto3-synthetics (>=1.42.0,<1.43.0)", "mypy-boto3-taxsettings (>=1.42.0,<1.43.0)", "mypy-boto3-textract (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-influxdb (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-query (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-write (>=1.42.0,<1.43.0)", "mypy-boto3-tnb (>=1.42.0,<1.43.0)", "mypy-boto3-transcribe (>=1.42.0,<1.43.0)", "mypy-boto3-transfer (>=1.42.0,<1.43.0)", "mypy-boto3-translate (>=1.42.0,<1.43.0)", "mypy-boto3-trustedadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-uxc (>=1.42.0,<1.43.0)", "mypy-boto3-verifiedpermissions (>=1.42.0,<1.43.0)", "mypy-boto3-voice-id (>=1.42.0,<1.43.0)", "mypy-boto3-vpc-lattice (>=1.42.0,<1.43.0)", "mypy-boto3-waf (>=1.42.0,<1.43.0)", "mypy-boto3-waf-regional (>=1.42.0,<1.43.0)", "mypy-boto3-wafv2 (>=1.42.0,<1.43.0)", "mypy-boto3-wellarchitected (>=1.42.0,<1.43.0)", "mypy-boto3-wickr (>=1.42.0,<1.43.0)", "mypy-boto3-wisdom (>=1.42.0,<1.43.0)", "mypy-boto3-workdocs (>=1.42.0,<1.43.0)", "mypy-boto3-workmail (>=1.42.0,<1.43.0)", "mypy-boto3-workmailmessageflow (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-instances (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-thin-client (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-web (>=1.42.0,<1.43.0)", "mypy-boto3-xray (>=1.42.0,<1.43.0)"] amp = ["mypy-boto3-amp (>=1.42.0,<1.43.0)"] amplify = ["mypy-boto3-amplify (>=1.42.0,<1.43.0)"] amplifybackend = ["mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)"] @@ -532,7 +532,7 @@ bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime ( bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)"] billing = ["mypy-boto3-billing (>=1.42.0,<1.43.0)"] billingconductor = ["mypy-boto3-billingconductor (>=1.42.0,<1.43.0)"] -boto3 = ["boto3 (==1.42.84)"] +boto3 = ["boto3 (==1.42.92)"] braket = ["mypy-boto3-braket (>=1.42.0,<1.43.0)"] budgets = ["mypy-boto3-budgets (>=1.42.0,<1.43.0)"] ce = ["mypy-boto3-ce (>=1.42.0,<1.43.0)"] @@ -668,6 +668,7 @@ importexport = ["mypy-boto3-importexport (>=1.42.0,<1.43.0)"] inspector = ["mypy-boto3-inspector (>=1.42.0,<1.43.0)"] inspector-scan = ["mypy-boto3-inspector-scan (>=1.42.0,<1.43.0)"] inspector2 = ["mypy-boto3-inspector2 (>=1.42.0,<1.43.0)"] +interconnect = ["mypy-boto3-interconnect (>=1.42.0,<1.43.0)"] internetmonitor = ["mypy-boto3-internetmonitor (>=1.42.0,<1.43.0)"] invoicing = ["mypy-boto3-invoicing (>=1.42.0,<1.43.0)"] iot = ["mypy-boto3-iot (>=1.42.0,<1.43.0)"] @@ -724,6 +725,7 @@ managedblockchain-query = ["mypy-boto3-managedblockchain-query (>=1.42.0,<1.43.0 marketplace-agreement = ["mypy-boto3-marketplace-agreement (>=1.42.0,<1.43.0)"] marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.42.0,<1.43.0)"] marketplace-deployment = ["mypy-boto3-marketplace-deployment (>=1.42.0,<1.43.0)"] +marketplace-discovery = ["mypy-boto3-marketplace-discovery (>=1.42.0,<1.43.0)"] marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.42.0,<1.43.0)"] marketplace-reporting = ["mypy-boto3-marketplace-reporting (>=1.42.0,<1.43.0)"] marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.42.0,<1.43.0)"] @@ -821,6 +823,7 @@ rtbfabric = ["mypy-boto3-rtbfabric (>=1.42.0,<1.43.0)"] rum = ["mypy-boto3-rum (>=1.42.0,<1.43.0)"] s3 = ["mypy-boto3-s3 (>=1.42.0,<1.43.0)"] s3control = ["mypy-boto3-s3control (>=1.42.0,<1.43.0)"] +s3files = ["mypy-boto3-s3files (>=1.42.0,<1.43.0)"] s3outposts = ["mypy-boto3-s3outposts (>=1.42.0,<1.43.0)"] s3tables = ["mypy-boto3-s3tables (>=1.42.0,<1.43.0)"] s3vectors = ["mypy-boto3-s3vectors (>=1.42.0,<1.43.0)"] @@ -1916,6 +1919,7 @@ 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] @@ -1934,6 +1938,7 @@ 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] @@ -1949,6 +1954,7 @@ python-versions = ">=3.10" groups = ["dev"] files = [ {file = "griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f"}, + {file = "griffelib-2.0.0.tar.gz", hash = "sha256:e504d637a089f5cab9b5daf18f7645970509bf4f53eda8d79ed71cce8bd97934"}, ] [package.extras] @@ -4301,30 +4307,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.10" +version = "0.15.11" 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.10-py3-none-linux_armv6l.whl", hash = "sha256:0744e31482f8f7d0d10a11fcbf897af272fefdfcb10f5af907b18c2813ff4d5f"}, - {file = "ruff-0.15.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b1e7c16ea0ff5a53b7c2df52d947e685973049be1cdfe2b59a9c43601897b22e"}, - {file = "ruff-0.15.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93cc06a19e5155b4441dd72808fdf84290d84ad8a39ca3b0f994363ade4cebb1"}, - {file = "ruff-0.15.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e1dd04312997c99ea6965df66a14fb4f03ba978564574ffc68b0d61fd3989e"}, - {file = "ruff-0.15.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8154d43684e4333360fedd11aaa40b1b08a4e37d8ffa9d95fee6fa5b37b6fab1"}, - {file = "ruff-0.15.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ab88715f3a6deb6bde6c227f3a123410bec7b855c3ae331b4c006189e895cef"}, - {file = "ruff-0.15.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a768ff5969b4f44c349d48edf4ab4f91eddb27fd9d77799598e130fb628aa158"}, - {file = "ruff-0.15.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ee3ef42dab7078bda5ff6a1bcba8539e9857deb447132ad5566a038674540d0"}, - {file = "ruff-0.15.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51cb8cc943e891ba99989dd92d61e29b1d231e14811db9be6440ecf25d5c1609"}, - {file = "ruff-0.15.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e59c9bdc056a320fb9ea1700a8d591718b8faf78af065484e801258d3a76bc3f"}, - {file = "ruff-0.15.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:136c00ca2f47b0018b073f28cb5c1506642a830ea941a60354b0e8bc8076b151"}, - {file = "ruff-0.15.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b80a2f3c9c8a950d6237f2ca12b206bccff626139be9fa005f14feb881a1ae8"}, - {file = "ruff-0.15.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e3e53c588164dc025b671c9df2462429d60357ea91af7e92e9d56c565a9f1b07"}, - {file = "ruff-0.15.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b0c52744cf9f143a393e284125d2576140b68264a93c6716464e129a3e9adb48"}, - {file = "ruff-0.15.10-py3-none-win32.whl", hash = "sha256:d4272e87e801e9a27a2e8df7b21011c909d9ddd82f4f3281d269b6ba19789ca5"}, - {file = "ruff-0.15.10-py3-none-win_amd64.whl", hash = "sha256:28cb32d53203242d403d819fd6983152489b12e4a3ae44993543d6fe62ab42ed"}, - {file = "ruff-0.15.10-py3-none-win_arm64.whl", hash = "sha256:601d1610a9e1f1c2165a4f561eeaa2e2ea1e97f3287c5aa258d3dab8b57c6188"}, - {file = "ruff-0.15.10.tar.gz", hash = "sha256:d1f86e67ebfdef88e00faefa1552b5e510e1d35f3be7d423dc7e84e63788c94e"}, + {file = "ruff-0.15.11-py3-none-linux_armv6l.whl", hash = "sha256:e927cfff503135c558eb581a0c9792264aae9507904eb27809cdcff2f2c847b7"}, + {file = "ruff-0.15.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7a1b5b2938d8f890b76084d4fa843604d787a912541eae85fd7e233398bbb73e"}, + {file = "ruff-0.15.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d4176f3d194afbdaee6e41b9ccb1a2c287dba8700047df474abfbe773825d1cb"}, + {file = "ruff-0.15.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b17c886fb88203ced3afe7f14e8d5ae96e9d2f4ccc0ee66aa19f2c2675a27e4"}, + {file = "ruff-0.15.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:49fafa220220afe7758a487b048de4c8f9f767f37dfefad46b9dd06759d003eb"}, + {file = "ruff-0.15.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2ab8427e74a00d93b8bda1307b1e60970d40f304af38bccb218e056c220120d"}, + {file = "ruff-0.15.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:195072c0c8e1fc8f940652073df082e37a5d9cb43b4ab1e4d0566ab8977a13b7"}, + {file = "ruff-0.15.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a0996d486af3920dec930a2e7daed4847dfc12649b537a9335585ada163e9e"}, + {file = "ruff-0.15.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bef2cb556d509259f1fe440bb9cd33c756222cf0a7afe90d15edf0866702431"}, + {file = "ruff-0.15.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:030d921a836d7d4a12cf6e8d984a88b66094ccb0e0f17ddd55067c331191bf19"}, + {file = "ruff-0.15.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0e783b599b4577788dbbb66b9addcef87e9a8832f4ce0c19e34bf55543a2f890"}, + {file = "ruff-0.15.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ae90592246625ba4a34349d68ec28d4400d75182b71baa196ddb9f82db025ef5"}, + {file = "ruff-0.15.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1f111d62e3c983ed20e0ca2e800f8d77433a5b1161947df99a5c2a3fb60514f0"}, + {file = "ruff-0.15.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:06f483d6646f59eaffba9ae30956370d3a886625f511a3108994000480621d1c"}, + {file = "ruff-0.15.11-py3-none-win32.whl", hash = "sha256:476a2aa56b7da0b73a3ee80b6b2f0e19cce544245479adde7baa65466664d5f3"}, + {file = "ruff-0.15.11-py3-none-win_amd64.whl", hash = "sha256:8b6756d88d7e234fb0c98c91511aae3cd519d5e3ed271cae31b20f39cb2a12a3"}, + {file = "ruff-0.15.11-py3-none-win_arm64.whl", hash = "sha256:063fed18cc1bbe0ee7393957284a6fe8b588c6a406a285af3ee3f46da2391ee4"}, + {file = "ruff-0.15.11.tar.gz", hash = "sha256:f092b21708bf0e7437ce9ada249dfe688ff9a0954fc94abab05dcea7dcd29c33"}, ] [[package]] @@ -4620,29 +4626,29 @@ files = [ [[package]] name = "ty" -version = "0.0.29" +version = "0.0.32" description = "An extremely fast Python type checker, written in Rust." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "ty-0.0.29-py3-none-linux_armv6l.whl", hash = "sha256:b8a40955f7660d3eaceb0d964affc81b790c0765e7052921a5f861ff8a471c30"}, - {file = "ty-0.0.29-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6b6849adae15b00bbe2d3c5b078967dcb62eba37d38936b8eeb4c81a82d2e3b8"}, - {file = "ty-0.0.29-py3-none-macosx_11_0_arm64.whl", hash = "sha256:dcdd9b17209788152f7b7ea815eda07989152325052fe690013537cc7904ce49"}, - {file = "ty-0.0.29-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d8ed4789bae78ffaf94462c0d25589a734cab0366b86f2bbcb1bb90e1a7a169"}, - {file = "ty-0.0.29-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91ec374b8565e0ad0900011c24641ebbef2da51adbd4fb69ff3280c8a7eceb02"}, - {file = "ty-0.0.29-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:298a8d5faa2502d3810bbbb47a030b9455495b9921594206043c785dd61548cf"}, - {file = "ty-0.0.29-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c8fba1a3524c6109d1e020d92301c79d41bf442fa8d335b9fa366239339cb70"}, - {file = "ty-0.0.29-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c48adf88a70d264128c39ee922ed14a947817fced1e93c08c1a89c9244edcde"}, - {file = "ty-0.0.29-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ce0a7a0e96bc7b42518cd3a1a6a6298ef64ff40ca4614355c1aa807059b5c6f"}, - {file = "ty-0.0.29-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6ac86a05b4a3731d45365ab97780acc7b8146fa62fccb3cbe94fe6546c67a97"}, - {file = "ty-0.0.29-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6bbbf53141af0f3150bf288d716263f1a3550054e4b3551ca866d38192ba9891"}, - {file = "ty-0.0.29-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1c9e06b770c1d0ff5efc51e34312390db31d53fcf3088163f413030b42b74f84"}, - {file = "ty-0.0.29-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0307fe37e3f000ef1a4ae230bbaf511508a78d24a5e51b40902a21b09d5e6037"}, - {file = "ty-0.0.29-py3-none-win32.whl", hash = "sha256:7a2a898217960a825f8bc0087e1fdbaf379606175e98f9807187221d53a4a8ed"}, - {file = "ty-0.0.29-py3-none-win_amd64.whl", hash = "sha256:fc1294200226b91615acbf34e0a9ad81caf98c081e9c6a912a31b0a7b603bc3f"}, - {file = "ty-0.0.29-py3-none-win_arm64.whl", hash = "sha256:f9794bbd1bb3ce13f78c191d0c89ae4c63f52c12b6daa0c6fe220b90d019d12c"}, - {file = "ty-0.0.29.tar.gz", hash = "sha256:e7936cca2f691eeda631876c92809688dbbab68687c3473f526cd83b6a9228d8"}, + {file = "ty-0.0.32-py3-none-linux_armv6l.whl", hash = "sha256:dacbc2f6cd698d488ae7436838ff929570455bf94bfa4d9fe57a630c552aff83"}, + {file = "ty-0.0.32-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914bbc4f605ce2a9e2a78982e28fae1d3359a169d141f9dc3b4c7749cd5eca81"}, + {file = "ty-0.0.32-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4787ac9fe1f86b1f3133f5c6732adbe2df5668b50c679ac6e2d98cd284da812f"}, + {file = "ty-0.0.32-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ea0a728af99fe40dd744cba6441a2404f80b7f4bde17aa6da393810af5ea57"}, + {file = "ty-0.0.32-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2850561f9b018ae33d7e5bbfa0ac414d3c518513edcffe43877dc9801446b9c5"}, + {file = "ty-0.0.32-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5fa2fb3c614349ee211d36476b49d88c5ef79a687cdb91b2872ad023b94d2f8"}, + {file = "ty-0.0.32-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b89969307ab2417d41c9be8059dd79feea577234e1e10d35132f5495e0d42c6"}, + {file = "ty-0.0.32-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b59868ede9b1d69a088f0d695df52a0061f95fa7baa1d5e0dc6fc9cf06e1334"}, + {file = "ty-0.0.32-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8300caf35345498e9b9b03e550bba03cee8f5f5f8ab4c83c3b1ff1b7403b7d3a"}, + {file = "ty-0.0.32-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:583c7094f4574b02f724db924f98b804d1387a0bd9405ecb5e078cc0f47fbcfb"}, + {file = "ty-0.0.32-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e44ebe1bb4143a5628bc4db67ac0dfebe14594af671e4ee66f6f2e983da56501"}, + {file = "ty-0.0.32-py3-none-musllinux_1_2_i686.whl", hash = "sha256:06f17ada3e069cba6148342ef88e9929156beca8473e8d4f101b68f66c75643e"}, + {file = "ty-0.0.32-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e96e60fa556cec04f15d7ea62d2ceee5982bd389233e961ab9fd42304e278175"}, + {file = "ty-0.0.32-py3-none-win32.whl", hash = "sha256:2ff2ebb4986b24aebcf1444db7db5ca41b36086040e95eea9f8fb851c11e805c"}, + {file = "ty-0.0.32-py3-none-win_amd64.whl", hash = "sha256:ba7284a4a954b598c1b31500352b3ec1f89bff533825592b5958848226fdc7ee"}, + {file = "ty-0.0.32-py3-none-win_arm64.whl", hash = "sha256:7e10aadbdbda989a7d567ee6a37f8b98d4d542e31e3b190a2879fd581f75d658"}, + {file = "ty-0.0.32.tar.gz", hash = "sha256:8743174c5f920f6700a4a0c9de140109189192ba16226884cd50095b43b8a45c"}, ] [[package]] @@ -4746,14 +4752,14 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.33.0.20260402" +version = "2.33.0.20260408" description = "Typing stubs for requests" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_requests-2.33.0.20260402-py3-none-any.whl", hash = "sha256:c98372d7124dd5d10af815ee25c013897592ff92af27b27e22c98984102c3254"}, - {file = "types_requests-2.33.0.20260402.tar.gz", hash = "sha256:1bdd3ada9b869741c5c4b887d2c8b4e38284a1449751823b5ebbccba3eefd9da"}, + {file = "types_requests-2.33.0.20260408-py3-none-any.whl", hash = "sha256:81f31d5ea4acb39f03be7bc8bed569ba6d5a9c5d97e89f45ac43d819b68ca50f"}, + {file = "types_requests-2.33.0.20260408.tar.gz", hash = "sha256:95b9a86376807a216b2fb412b47617b202091c3ea7c078f47cc358d5528ccb7b"}, ] [package.dependencies] @@ -5180,4 +5186,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "6413dbddcb0a105cd5a278bf10d8e0eaca15eb825ef1d92619b94531c8e76375" +content-hash = "1f2cdd13aaff7bb08f2b86bb460b8f9688597ad0819225c0f4af051f10077590" diff --git a/pyproject.toml b/pyproject.toml index e75809594be..46835912a74 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.11" +ruff = ">=0.5.1,<0.15.12" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.8" types-redis = "^4.6.0.7" @@ -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.30" +ty = ">=0.0.23,<0.0.33" [tool.coverage.run] source = ["aws_lambda_powertools"] From 3c588e9e33b6117d45f185fcdad395f3faeac54e Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 23 Apr 2026 18:30:46 +0100 Subject: [PATCH 58/84] feat(event_handler): adding resolve async internal (#8170) * feat: addin resolve async internal * feat: addin resolve async internal * feat: addin resolve async internal * feat: addin resolve async internal * feat: addin resolve async internal --- .../event_handler/api_gateway.py | 145 +++++++ .../event_handler/http_resolver.py | 6 +- .../test_resolve_async_validation.py | 55 +++ .../test_resolve_async.py | 372 ++++++++++++++++++ 4 files changed, 575 insertions(+), 3 deletions(-) create mode 100644 tests/functional/event_handler/_pydantic/test_resolve_async_validation.py create mode 100644 tests/functional/event_handler/required_dependencies/test_resolve_async.py diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 041f6f7abf3..7b2a228725a 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -613,6 +613,63 @@ def _build_middleware_stack(self, router_middlewares: list[Callable[..., Any]], self._middleware_stack_built = True + async def call_async( + self, + router_middlewares: list[Callable], + app: ApiGatewayResolver, + route_arguments: dict[str, str], + ) -> dict | tuple | Response: + from aws_lambda_powertools.event_handler.middlewares.async_utils import ( + AsyncMiddlewareFrame, + _registered_api_adapter_async, + ) + + all_middlewares: list[Callable[..., Any]] = [] + + route_validation_enabled = ( + self.enable_validation if self.enable_validation is not None else app._enable_validation + ) + + if route_validation_enabled and not hasattr(app, "_request_validation_middleware"): + from aws_lambda_powertools.event_handler.middlewares.openapi_validation import ( + OpenAPIRequestValidationMiddleware, + OpenAPIResponseValidationMiddleware, + ) + + app._request_validation_middleware = OpenAPIRequestValidationMiddleware() + app._response_validation_middleware = OpenAPIResponseValidationMiddleware( + validation_serializer=app._serializer, + has_response_validation_error=app._has_response_validation_error, + ) + + if route_validation_enabled and hasattr(app, "_request_validation_middleware"): + all_middlewares.append(app._request_validation_middleware) + + all_middlewares.extend(router_middlewares + self.middlewares) + + if route_validation_enabled and hasattr(app, "_response_validation_middleware"): + all_middlewares.append(app._response_validation_middleware) + + all_middlewares.append(_registered_api_adapter_async) + + logger.debug(f"Building async middleware stack: {all_middlewares}") + + if app._debug: + print(f"\nProcessing Route (async):::{self.func.__name__} ({app.context['_path']})") + print("\nAsync Middleware Stack:") + print("=================") + print("\n".join(getattr(item, "__name__", "Unknown") for item in all_middlewares)) + print("=================") + + app.append_context(_route_args=route_arguments) + + # Build async chain from inside-out (not cached — avoids state conflicts with sync cache) + next_handler: Callable = self.func + for handler in reversed(all_middlewares): + next_handler = AsyncMiddlewareFrame(current_middleware=handler, next_middleware=next_handler) + + return await next_handler(app) + @property def dependant(self) -> Dependant: if self._dependant is None: @@ -2509,6 +2566,94 @@ def resolve(self, event: Mapping[str, Any], context: LambdaContext) -> dict[str, return response + async def _resolve_async(self) -> ResponseBuilder: + 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: Match | None = route.rule.match(path) + if match_results: + logger.debug("Found a registered route. Calling async function") + 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) + + return await self._handle_not_found_async(method=method, path=path) + + async def _call_route_async(self, route: Route, route_arguments: dict[str, str]) -> ResponseBuilder: + try: + self._reset_processed_stack() + + response = await route.call_async( + router_middlewares=self._router_middlewares, + app=self, + route_arguments=route_arguments, + ) + + return self._response_builder_class( + response=self._to_response(response), # type: ignore[arg-type] + serializer=self._serializer, + route=route, + ) + except Exception as exc: + response_builder = self._call_exception_handler(exc, route) + if response_builder: + return response_builder + + logger.exception(exc) + if self._debug: + return self._response_builder_class( + response=Response( + status_code=500, + content_type=content_types.TEXT_PLAIN, + body="".join(traceback.format_exc()), + ), + serializer=self._serializer, + route=route, + ) + + raise + + async def _handle_not_found_async(self, method: str, path: str) -> ResponseBuilder: + logger.debug(f"No match found for path {path} and method {method}") + + def not_found_handler(): + _headers: dict[str, Any] = {} + + if self._cors and method == "OPTIONS": + logger.debug("Pre-flight request detected. Returning CORS with empty response") + _headers["Access-Control-Allow-Methods"] = CORSConfig.build_allow_methods(self._cors_methods) + return Response(status_code=204, content_type=None, headers=_headers, body="") + + custom_not_found_handler = self.exception_handler_manager.lookup_exception_handler(NotFoundError) + if custom_not_found_handler: + return custom_not_found_handler(NotFoundError()) + + return Response( + status_code=HTTPStatus.NOT_FOUND.value, + content_type=content_types.APPLICATION_JSON, + headers=_headers, + body={"statusCode": HTTPStatus.NOT_FOUND.value, "message": "Not found"}, + ) + + route = Route( + rule=self._compile_regex(r".*"), + method=method, + path=path, + func=not_found_handler, + cors=self._cors_enabled, + compress=False, + ) + + self.append_context(_route=route, _path=path) + + return await self._call_route_async(route=route, route_arguments={}) + def __call__(self, event, context) -> Any: return self.resolve(event, context) diff --git a/aws_lambda_powertools/event_handler/http_resolver.py b/aws_lambda_powertools/event_handler/http_resolver.py index 168a6f44b8e..da72f6fca4d 100644 --- a/aws_lambda_powertools/event_handler/http_resolver.py +++ b/aws_lambda_powertools/event_handler/http_resolver.py @@ -239,7 +239,7 @@ def _get_base_path(self) -> str: """Return the base path for HTTP resolver (no stage prefix).""" return "" - async def _resolve_async(self) -> dict: + 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) @@ -258,7 +258,7 @@ async def _resolve_async(self) -> dict: # Handle not found return await self._handle_not_found_async() - async def _call_route_async(self, route: Route, route_arguments: dict[str, str]) -> dict: + 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 @@ -323,7 +323,7 @@ async def final_handler(app): return await next_handler(self) - async def _handle_not_found_async(self) -> dict: + 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 diff --git a/tests/functional/event_handler/_pydantic/test_resolve_async_validation.py b/tests/functional/event_handler/_pydantic/test_resolve_async_validation.py new file mode 100644 index 00000000000..92b414f72b5 --- /dev/null +++ b/tests/functional/event_handler/_pydantic/test_resolve_async_validation.py @@ -0,0 +1,55 @@ +import asyncio + +from aws_lambda_powertools.event_handler.api_gateway import ( + APIGatewayHttpResolver, + BaseRouter, +) +from tests.functional.utils import load_event + +API_RESTV2_EVENT = load_event("apiGatewayProxyV2Event_GET.json") + + +def _setup_app(app, event): + BaseRouter.current_event = app._to_proxy_event(event) + BaseRouter.lambda_context = {} + + +class TestResolveAsyncValidation: + def test_validation_middleware_created_and_used(self): + # GIVEN a resolver with validation enabled and an async handler + app = APIGatewayHttpResolver(enable_validation=True) + + @app.get("/my/path") + async def get_lambda() -> dict: + await asyncio.sleep(0) + return {"message": "validated"} + + # WHEN calling _resolve_async + _setup_app(app, API_RESTV2_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN the validation middlewares are created and the response is valid + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + assert hasattr(app, "_request_validation_middleware") + assert hasattr(app, "_response_validation_middleware") + + def test_validation_middleware_lazy_created_for_per_route_validation(self): + # GIVEN a resolver WITHOUT global validation, but a route WITH enable_validation=True + app = APIGatewayHttpResolver() + assert not hasattr(app, "_request_validation_middleware") + + @app.get("/my/path", enable_validation=True) + async def get_lambda() -> dict: + await asyncio.sleep(0) + return {"message": "lazy validated"} + + # WHEN calling _resolve_async (triggers lazy creation in Route.call_async) + _setup_app(app, API_RESTV2_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN validation middlewares are lazily created on the app + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + assert hasattr(app, "_request_validation_middleware") + assert hasattr(app, "_response_validation_middleware") diff --git a/tests/functional/event_handler/required_dependencies/test_resolve_async.py b/tests/functional/event_handler/required_dependencies/test_resolve_async.py new file mode 100644 index 00000000000..4726db89d2a --- /dev/null +++ b/tests/functional/event_handler/required_dependencies/test_resolve_async.py @@ -0,0 +1,372 @@ +import asyncio + +import pytest + +from aws_lambda_powertools.event_handler import content_types +from aws_lambda_powertools.event_handler.api_gateway import ( + ALBResolver, + APIGatewayHttpResolver, + ApiGatewayResolver, + APIGatewayRestResolver, + BaseRouter, + CORSConfig, + ProxyEventType, + Response, +) +from aws_lambda_powertools.event_handler.middlewares import NextMiddleware +from tests.functional.utils import load_event + +API_REST_EVENT = load_event("apiGatewayProxyEvent.json") +API_RESTV2_EVENT = load_event("apiGatewayProxyV2Event_GET.json") +ALB_EVENT = load_event("albEvent.json") + + +def _setup_app(app, event): + BaseRouter.current_event = app._to_proxy_event(event) + BaseRouter.lambda_context = {} + + +RESOLVER_IDS = ["ApiGatewayResolver", "APIGatewayRestResolver", "APIGatewayHttpResolver", "ALBResolver"] + + +@pytest.fixture( + params=[ + ("apigw_v1", API_REST_EVENT, "/my/path"), + ("apigw_rest", API_REST_EVENT, "/my/path"), + ("apigw_v2", API_RESTV2_EVENT, "/my/path"), + ("alb", ALB_EVENT, "/lambda"), + ], + ids=RESOLVER_IDS, +) +def resolver_and_event(request): + key, event, path = request.param + resolvers = { + "apigw_v1": ApiGatewayResolver(proxy_type=ProxyEventType.APIGatewayProxyEvent), + "apigw_rest": APIGatewayRestResolver(), + "apigw_v2": APIGatewayHttpResolver(), + "alb": ALBResolver(), + } + return resolvers[key], event, path + + +class TestResolveAsyncWithAsyncHandlers: + def test_async_handler_through_resolve_chain(self, resolver_and_event): + # GIVEN an async handler registered on the resolver + app, event, path = resolver_and_event + + @app.get(path) + async def get_lambda(): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "async works") + + # WHEN calling _resolve_async after setting up context + _setup_app(app, event) + result = asyncio.run(app._resolve_async()) + + # THEN the async handler is awaited and returns a ResponseBuilder + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + assert response["body"] == "async works" + + def test_async_handler_returning_dict(self, resolver_and_event): + # GIVEN an async handler that returns a dict + app, event, path = resolver_and_event + + @app.get(path) + async def get_lambda(): + await asyncio.sleep(0) + return {"message": "hello"} + + # WHEN calling _resolve_async + _setup_app(app, event) + result = asyncio.run(app._resolve_async()) + + # THEN the dict is normalized into a Response + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + + def test_async_handler_returning_tuple(self, resolver_and_event): + # GIVEN an async handler that returns a (dict, status_code) tuple + app, event, path = resolver_and_event + + @app.get(path) + async def get_lambda(): + await asyncio.sleep(0) + return {"created": True}, 201 + + # WHEN calling _resolve_async + _setup_app(app, event) + result = asyncio.run(app._resolve_async()) + + # THEN the tuple is normalized with the correct status code + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 201 + + +class TestResolveAsyncWithSyncHandlers: + def test_sync_handler_works_through_async_chain(self, resolver_and_event): + # GIVEN a sync handler + app, event, path = resolver_and_event + + @app.get(path) + def get_lambda(): + return Response(200, content_types.TEXT_HTML, "sync via async") + + # WHEN calling _resolve_async + _setup_app(app, event) + result = asyncio.run(app._resolve_async()) + + # THEN the sync handler works through the async chain + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + assert response["body"] == "sync via async" + + +class TestResolveAsyncRouteArguments: + def test_route_args_passed_to_async_handler(self): + # GIVEN an async handler with a path parameter + app = APIGatewayHttpResolver() + + @app.get("/my/") + async def get_lambda(name: str): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, name) + + # WHEN resolving a matching event + event = load_event("apiGatewayProxyV2Event_GET.json") + event["rawPath"] = "/my/powertools" + event["requestContext"]["http"]["path"] = "/my/powertools" + _setup_app(app, event) + result = asyncio.run(app._resolve_async()) + + # THEN route arguments are passed to the handler + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + assert response["body"] == "powertools" + + +class TestResolveAsyncNotFound: + def test_not_found_returns_404(self, resolver_and_event): + # GIVEN no matching route + app, event, _path = resolver_and_event + + @app.get("/other/path") + async def get_lambda(): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "should not reach") + + # WHEN resolving an event with a non-matching path + _setup_app(app, event) + result = asyncio.run(app._resolve_async()) + + # THEN a 404 response is returned + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 404 + + def test_custom_not_found_handler(self): + # GIVEN a custom not_found handler + app = APIGatewayRestResolver() + + @app.not_found + def custom_not_found(exc): + return Response(404, content_types.APPLICATION_JSON, '{"error": "custom 404"}') + + @app.get("/other") + def get_lambda(): + return Response(200, content_types.TEXT_HTML, "not reached") + + # WHEN resolving with no matching route + _setup_app(app, API_REST_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN the custom handler is called + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 404 + assert response["body"] == '{"error": "custom 404"}' + + def test_cors_preflight_returns_204(self): + # GIVEN a resolver with CORS enabled + app = APIGatewayRestResolver(cors=CORSConfig()) + + @app.get("/my/path") + def get_lambda(): + return Response(200, content_types.TEXT_HTML, "ok") + + # WHEN an OPTIONS request arrives for a non-matching path + event = load_event("apiGatewayProxyEvent.json") + event["httpMethod"] = "OPTIONS" + _setup_app(app, event) + result = asyncio.run(app._resolve_async()) + + # THEN a 204 pre-flight response is returned + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 204 + + +class TestResolveAsyncExceptionHandling: + def test_exception_handler_catches_async_error(self): + # GIVEN an async handler that raises and an exception handler + app = APIGatewayRestResolver() + + @app.exception_handler(ValueError) + def handle_value_error(exc): + return Response(422, content_types.APPLICATION_JSON, '{"error": "validation failed"}') + + @app.get("/my/path") + async def get_lambda(): + await asyncio.sleep(0) + raise ValueError("bad input") + + # WHEN resolving + _setup_app(app, API_REST_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN the exception handler catches the error + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 422 + + +class TestResolveAsyncMiddleware: + def test_sync_middleware_in_async_chain(self): + # GIVEN a sync middleware + app = APIGatewayRestResolver() + + def my_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(sync_mw_called=True) + return next_middleware(app) + + @app.get("/my/path", middlewares=[my_middleware]) + async def get_lambda(): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "with middleware") + + # WHEN calling _resolve_async + _setup_app(app, API_REST_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN the sync middleware runs in the async chain + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + assert response["body"] == "with middleware" + assert app.context.get("sync_mw_called") is True + + def test_async_middleware_in_async_chain(self): + # GIVEN an async middleware + app = APIGatewayRestResolver() + + async def my_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + app.append_context(async_mw_called=True) + return await next_middleware(app) + + @app.get("/my/path", middlewares=[my_middleware]) + async def get_lambda(): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "async mw") + + # WHEN calling _resolve_async + _setup_app(app, API_REST_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN the async middleware runs correctly + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 200 + assert app.context.get("async_mw_called") is True + + def test_not_found_goes_through_middleware(self): + # GIVEN a global middleware + middleware_called = [] + + def tracking_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + middleware_called.append(True) + return next_middleware(app) + + app = APIGatewayRestResolver() + app.use([tracking_middleware]) + + @app.get("/other/path") + def get_lambda(): + return Response(200, content_types.TEXT_HTML, "not reached") + + # WHEN resolving with a non-matching path + _setup_app(app, API_REST_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN the middleware still runs (404 goes through chain) + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 404 + assert len(middleware_called) > 0 + + +class TestResolveAsyncProcessedStack: + def test_processed_stack_frames_recorded(self): + # GIVEN an async handler + app = APIGatewayRestResolver() + + @app.get("/my/path") + async def get_lambda(): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "ok") + + # WHEN calling _resolve_async + _setup_app(app, API_REST_EVENT) + asyncio.run(app._resolve_async()) + + # THEN the processed stack frames are populated + assert len(app.processed_stack_frames) > 0 + assert any("_registered_api_adapter_async" in frame for frame in app.processed_stack_frames) + + +class TestResolveAsyncDebugMode: + def test_debug_mode_prints_middleware_stack(self, capsys): + # GIVEN a resolver with debug=True + app = APIGatewayRestResolver(debug=True) + + @app.get("/my/path") + async def get_lambda(): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "debug") + + # WHEN calling _resolve_async + _setup_app(app, API_REST_EVENT) + asyncio.run(app._resolve_async()) + + # THEN the async middleware stack is printed + captured = capsys.readouterr() + assert "Async Middleware Stack:" in captured.out + assert "_registered_api_adapter_async" in captured.out + + +class TestResolveAsyncExceptionNoHandler: + def test_unhandled_exception_reraises(self): + # GIVEN an async handler that raises with no matching exception handler + app = APIGatewayRestResolver() + + @app.get("/my/path") + async def get_lambda(): + await asyncio.sleep(0) + raise RuntimeError("unhandled") + + # WHEN calling _resolve_async + _setup_app(app, API_REST_EVENT) + + # THEN the exception propagates + with pytest.raises(RuntimeError, match="unhandled"): + asyncio.run(app._resolve_async()) + + def test_unhandled_exception_with_debug_returns_traceback(self): + # GIVEN a resolver with debug=True and no exception handler + app = APIGatewayRestResolver(debug=True) + + @app.get("/my/path") + async def get_lambda(): + await asyncio.sleep(0) + raise RuntimeError("debug error") + + # WHEN calling _resolve_async + _setup_app(app, API_REST_EVENT) + result = asyncio.run(app._resolve_async()) + + # THEN a 500 response with traceback is returned + response = result.build(app.current_event, app._cors) + assert response["statusCode"] == 500 + assert "debug error" in response["body"] From 364747f394d49f3f779ac75a37a5094bf8cb19f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:03:42 +0100 Subject: [PATCH 59/84] chore(deps): bump gitpython from 3.1.44 to 3.1.47 in /docs (#8172) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.44 to 3.1.47. - [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.44...3.1.47) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.47 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 514279c944c..f35bb2b968e 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.44 \ - --hash=sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110 \ - --hash=sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269 +gitpython==3.1.47 \ + --hash=sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905 \ + --hash=sha256:dba27f922bd2b42cb54c87a8ab3cb6beb6bf07f3d564e21ac848913a05a8a3cd # via mkdocs-git-revision-date-plugin griffe==1.13.0 \ --hash=sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0 \ From 2ae577ca287e6cbdcfd00871921c1a0b6f8e92f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:05:45 +0100 Subject: [PATCH 60/84] chore(deps-dev): bump gitpython from 3.1.44 to 3.1.47 (#8173) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.44 to 3.1.47. - [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.44...3.1.47) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.47 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 | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0d9844350aa..eeb46da9ed6 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.2.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" @@ -325,7 +325,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"}, @@ -1837,7 +1837,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"}, @@ -1893,21 +1893,21 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.46" +version = "3.1.47" 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.46-py3-none-any.whl", hash = "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058"}, - {file = "gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f"}, + {file = "gitpython-3.1.47-py3-none-any.whl", hash = "sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905"}, + {file = "gitpython-3.1.47.tar.gz", hash = "sha256:dba27f922bd2b42cb54c87a8ab3cb6beb6bf07f3d564e21ac848913a05a8a3cd"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" [package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] +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\""] [[package]] @@ -3415,7 +3415,7 @@ files = [ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3557,7 +3557,7 @@ files = [ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -4812,7 +4812,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" @@ -5130,7 +5130,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 2e11129dd777a4d759f51fc46b1d78f389be0527 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 27 Apr 2026 14:27:09 +0100 Subject: [PATCH 61/84] feat(event_handler): adding resolve async public API (#8171) * feat: adding resolve async public API * feat: adding resolve async public API --- .../event_handler/api_gateway.py | 62 +++++- docs/core/event_handler/api_gateway.md | 108 ++++++++++ .../src/async_resolve_all_resolvers.py | 31 +++ .../src/async_resolve_async_middleware.py | 29 +++ .../src/async_resolve_concurrent.py | 28 +++ .../src/async_resolve_getting_started.py | 21 ++ .../src/async_resolve_middleware.py | 29 +++ .../src/async_resolve_testing.py | 26 +++ .../test_resolve_async.py | 193 ++++++++++++++++++ 9 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 examples/event_handler_rest/src/async_resolve_all_resolvers.py create mode 100644 examples/event_handler_rest/src/async_resolve_async_middleware.py create mode 100644 examples/event_handler_rest/src/async_resolve_concurrent.py create mode 100644 examples/event_handler_rest/src/async_resolve_getting_started.py create mode 100644 examples/event_handler_rest/src/async_resolve_middleware.py create mode 100644 examples/event_handler_rest/src/async_resolve_testing.py diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 7b2a228725a..d5d7751f043 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -663,7 +663,7 @@ async def call_async( app.append_context(_route_args=route_arguments) - # Build async chain from inside-out (not cached — avoids state conflicts with sync cache) + # Build async chain from inside-out (not cached, avoids state conflicts with sync cache) next_handler: Callable = self.func for handler in reversed(all_middlewares): next_handler = AsyncMiddlewareFrame(current_middleware=handler, next_middleware=next_handler) @@ -2566,6 +2566,66 @@ def resolve(self, event: Mapping[str, Any], context: LambdaContext) -> dict[str, return response + async def resolve_async(self, event: Mapping[str, Any], context: LambdaContext) -> dict[str, Any]: + """Async version of resolve() for native async handler support. + + Use this method when your route handlers use async/await. The resolution + pipeline supports both sync and async handlers transparently. + + Parameters + ---------- + event: dict[str, Any] + Event + context: LambdaContext + Lambda context + Returns + ------- + dict + Returns the dict response + + Example + ------- + + ```python + import asyncio + from aws_lambda_powertools.event_handler import APIGatewayHttpResolver + + app = APIGatewayHttpResolver() + + @app.get("/async") + async def async_handler(): + return {"message": "async works"} + + def lambda_handler(event, context): + return asyncio.run(app.resolve_async(event, context)) + ``` + """ + if isinstance(event, BaseProxyEvent): + warnings.warn( + "You don't need to serialize event to Event Source Data Class when using Event Handler; " + "see issue #1152", + stacklevel=2, + ) + event = event.raw_event + + if self._debug: + print(self._serializer(cast(dict, event))) + + BaseRouter.current_event = self._to_proxy_event(cast(dict, event)) + BaseRouter.lambda_context = context + + response = (await self._resolve_async()).build(self.current_event, self._cors) + + if self._debug: + print("\nProcessed Middlewares:") + print("======================") + print("\n".join(self.processed_stack_frames)) + print("======================") + + self.clear_context() + + return response + async def _resolve_async(self) -> ResponseBuilder: method = self.current_event.http_method.upper() path = self._remove_prefix(self.current_event.path) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 2a7955f38c0..076e2aa3c11 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -11,6 +11,7 @@ Event handler for Amazon API Gateway REST and HTTP APIs, Application Load Balanc * Support for CORS, binary and Gzip compression, Decimals JSON encoding and bring your own JSON serializer * Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"} for self-documented event schema * Works with micro function (one or a few routes) and monolithic functions (all routes) +* Native async handler support with `resolve_async()` for non-blocking I/O * Support for Middleware * Support for OpenAPI schema generation * Support data validation for requests/responses @@ -1464,6 +1465,99 @@ Use `dependency_overrides` to replace any dependency with a mock or stub during ???+ info "`append_context` vs `Depends()`" `append_context` remains available for backward compatibility. `Depends()` is recommended for new code because it provides type safety, IDE autocomplete, composable dependency trees, and `dependency_overrides` for testing. +### Async support + +Use `resolve_async()` to natively support async route handlers with `async/await`. This enables non-blocking I/O operations like concurrent HTTP calls, database queries, and parallel processing within your Lambda function. + +Both sync and async handlers can coexist in the same resolver. Async handlers are automatically detected and awaited. + +=== "Getting started" + + ```python hl_lines="9 22" title="async_resolve_getting_started.py" + --8<-- "examples/event_handler_rest/src/async_resolve_getting_started.py" + ``` + + 1. Define your route handler as `async def` to use `await` + 2. Sync handlers continue to work as before, no changes needed + 3. Use `resolve_async()` instead of `resolve()` and wrap with `asyncio.run()` + +=== "Concurrent I/O with gather" + + ```python hl_lines="21-24" title="async_resolve_concurrent.py" + --8<-- "examples/event_handler_rest/src/async_resolve_concurrent.py" + ``` + + 1. `asyncio.gather()` runs multiple I/O operations concurrently, reducing total latency + +=== "All resolvers" + + ```python hl_lines="1 10-12" title="async_resolve_all_resolvers.py" + --8<-- "examples/event_handler_rest/src/async_resolve_all_resolvers.py" + ``` + + 1. API Gateway REST API + 2. API Gateway HTTP API + 3. Application Load Balancer + +#### Middlewares + +Both sync and async middlewares work in the async chain. Sync middlewares are executed in a background thread so the event loop is never blocked. + +=== "Sync middleware" + + ```python hl_lines="11 24" title="async_resolve_middleware.py" + --8<-- "examples/event_handler_rest/src/async_resolve_middleware.py" + ``` + + 1. Sync middleware works as-is, no changes needed + 2. Async handler is awaited natively in the async chain + +=== "Async middleware" + + ```python hl_lines="11 16" title="async_resolve_async_middleware.py" + --8<-- "examples/event_handler_rest/src/async_resolve_async_middleware.py" + ``` + + 1. Define your middleware as `async def` to use `await` + 2. Use `await next_middleware(app)` instead of `next_middleware(app)` + +#### Async with data validation + +Data validation with Pydantic works with async handlers. Use `enable_validation=True` as you would with sync handlers. + +```python hl_lines="1 3 7" +app = APIGatewayHttpResolver(enable_validation=True) + +@app.get("/todos/") +async def get_todo(todo_id: int) -> dict: + return {"todo_id": todo_id} + +def lambda_handler(event, context): + return asyncio.run(app.resolve_async(event, context)) +``` + +#### Operations that remain synchronous + +These operations run synchronously on the event loop. They are CPU-bound and complete in microseconds, so they do not benefit from async. + +| Operation | Why it stays synchronous | +| ----------------------------- | --------------------------------------------------------------- | +| **Route matching** | Regex matching and string comparison against registered routes | +| **Event deserialization** | Converting the raw event dict into a proxy event data class | +| **Response serialization** | JSON encoding, base64 encoding, header assembly | +| **Response validation** | Pydantic model validation is CPU-bound | +| **Request validation** | Pydantic model validation is CPU-bound | +| **Compression** | Gzip compression of response body | +| **CORS header injection** | Building Access-Control headers from config | +| **Dependency resolution** | `Depends()` tree is resolved synchronously | + +#### Known limitations + +| Limitation | Detail | +| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | +| **AWS X-Ray with `asyncio.gather`** | X-Ray SDK does not propagate trace context across `asyncio.gather` tasks. Use individual `await` calls if you need per-call tracing. | +| **Sync middlewares use thread pool** | Sync middlewares run in the default `ThreadPoolExecutor`. Avoid long blocking I/O inside sync middlewares when using `resolve_async()`. | + ### Considerations This utility is optimized for fast startup, minimal feature set, and to quickly on-board customers familiar with frameworks like Flask — it's not meant to be a fully fledged framework. @@ -1546,6 +1640,20 @@ Each endpoint will be it's own Lambda function that is configured as a [Lambda i ## Testing your code +### Testing async handlers + +You can test async handlers by calling `resolve_async()` with `asyncio.run()`. + +```python hl_lines="24 26" title="async_resolve_testing.py" +--8<-- "examples/event_handler_rest/src/async_resolve_testing.py" +``` + +1. Import your app as usual +2. Use `asyncio.run(app.resolve_async(...))` instead of `app.resolve(...)` +3. Assert on the response dict as you would with sync handlers + +### Testing sync handlers + You can test your routes by passing a proxy event request with required params. ???+ info diff --git a/examples/event_handler_rest/src/async_resolve_all_resolvers.py b/examples/event_handler_rest/src/async_resolve_all_resolvers.py new file mode 100644 index 00000000000..92149e1dc3c --- /dev/null +++ b/examples/event_handler_rest/src/async_resolve_all_resolvers.py @@ -0,0 +1,31 @@ +import asyncio + +from aws_lambda_powertools.event_handler import ( + ALBResolver, + APIGatewayHttpResolver, + APIGatewayRestResolver, +) + +rest_app = APIGatewayRestResolver() # (1)! +http_app = APIGatewayHttpResolver() # (2)! +alb_app = ALBResolver() # (3)! + + +@rest_app.get("/hello") +@http_app.get("/hello") +@alb_app.get("/hello") +async def hello(): + await asyncio.sleep(0) + return {"message": "hello from async"} + + +def rest_handler(event, context): + return asyncio.run(rest_app.resolve_async(event, context)) + + +def http_handler(event, context): + return asyncio.run(http_app.resolve_async(event, context)) + + +def alb_handler(event, context): + return asyncio.run(alb_app.resolve_async(event, context)) diff --git a/examples/event_handler_rest/src/async_resolve_async_middleware.py b/examples/event_handler_rest/src/async_resolve_async_middleware.py new file mode 100644 index 00000000000..e801a58b1f6 --- /dev/null +++ b/examples/event_handler_rest/src/async_resolve_async_middleware.py @@ -0,0 +1,29 @@ +import asyncio +from collections.abc import Callable + +from aws_lambda_powertools import Logger +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response + +app = APIGatewayRestResolver() +logger = Logger() + + +async def async_inject_correlation_id(app: APIGatewayRestResolver, next_middleware: Callable) -> Response: # (1)! + request_id = app.current_event.request_context.request_id + app.append_context(correlation_id=request_id) + logger.set_correlation_id(request_id) + + result = await next_middleware(app) # (2)! + + result.headers["x-correlation-id"] = request_id + return result + + +@app.get("/todos", middlewares=[async_inject_correlation_id]) +async def get_todos(): + await asyncio.sleep(0) + return {"todos": []} + + +def lambda_handler(event, context): + return asyncio.run(app.resolve_async(event, context)) diff --git a/examples/event_handler_rest/src/async_resolve_concurrent.py b/examples/event_handler_rest/src/async_resolve_concurrent.py new file mode 100644 index 00000000000..868954d51c7 --- /dev/null +++ b/examples/event_handler_rest/src/async_resolve_concurrent.py @@ -0,0 +1,28 @@ +import asyncio + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver + +app = APIGatewayHttpResolver() + + +async def fetch_profile(user_id: str) -> dict: + await asyncio.sleep(0) # simulate async I/O (e.g., DynamoDB, HTTP call) + return {"user_id": user_id, "name": "John"} + + +async def fetch_orders(user_id: str) -> list: + await asyncio.sleep(0) + return [{"order_id": "123", "total": 99.99}] + + +@app.get("/dashboard/") +async def get_dashboard(user_id: str): + profile, orders = await asyncio.gather( # (1)! + fetch_profile(user_id), + fetch_orders(user_id), + ) + return {"profile": profile, "orders": orders} + + +def lambda_handler(event, context): + return asyncio.run(app.resolve_async(event, context)) diff --git a/examples/event_handler_rest/src/async_resolve_getting_started.py b/examples/event_handler_rest/src/async_resolve_getting_started.py new file mode 100644 index 00000000000..40d9c2b9bec --- /dev/null +++ b/examples/event_handler_rest/src/async_resolve_getting_started.py @@ -0,0 +1,21 @@ +import asyncio + +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver + +app = APIGatewayHttpResolver() + + +@app.get("/todos/") +async def get_todo(todo_id: str): # (1)! + # Async handlers can use await for non-blocking I/O + await asyncio.sleep(0) # simulate async I/O + return {"todo_id": todo_id, "completed": False} + + +@app.get("/health") +def health(): # (2)! + return {"status": "ok"} + + +def lambda_handler(event, context): + return asyncio.run(app.resolve_async(event, context)) # (3)! diff --git a/examples/event_handler_rest/src/async_resolve_middleware.py b/examples/event_handler_rest/src/async_resolve_middleware.py new file mode 100644 index 00000000000..7ace8762ff8 --- /dev/null +++ b/examples/event_handler_rest/src/async_resolve_middleware.py @@ -0,0 +1,29 @@ +import asyncio + +from aws_lambda_powertools import Logger +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response +from aws_lambda_powertools.event_handler.middlewares import NextMiddleware + +app = APIGatewayRestResolver() +logger = Logger() + + +def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response: # (1)! + request_id = app.current_event.request_context.request_id + app.append_context(correlation_id=request_id) + logger.set_correlation_id(request_id) + + result = next_middleware(app) + + result.headers["x-correlation-id"] = request_id + return result + + +@app.get("/todos", middlewares=[inject_correlation_id]) +async def get_todos(): # (2)! + await asyncio.sleep(0) + return {"todos": []} + + +def lambda_handler(event, context): + return asyncio.run(app.resolve_async(event, context)) diff --git a/examples/event_handler_rest/src/async_resolve_testing.py b/examples/event_handler_rest/src/async_resolve_testing.py new file mode 100644 index 00000000000..8ce0aadeb13 --- /dev/null +++ b/examples/event_handler_rest/src/async_resolve_testing.py @@ -0,0 +1,26 @@ +import asyncio +import json + + +def test_async_handler(): + from async_resolve_getting_started import app # (1)! + + event = { + "httpMethod": "GET", + "path": "/todos/1", + "headers": {}, + "queryStringParameters": None, + "pathParameters": {"todo_id": "1"}, + "body": None, + "isBase64Encoded": False, + "requestContext": {"stage": "dev", "requestId": "test-id", "http": {"method": "GET", "path": "/todos/1"}}, + "rawPath": "/todos/1", + "rawQueryString": "", + "routeKey": "GET /todos/{todo_id}", + "version": "2.0", + } + + response = asyncio.run(app.resolve_async(event, {})) # (2)! + + assert response["statusCode"] == 200 # (3)! + assert json.loads(response["body"]) == {"todo_id": "1", "completed": False} diff --git a/tests/functional/event_handler/required_dependencies/test_resolve_async.py b/tests/functional/event_handler/required_dependencies/test_resolve_async.py index 4726db89d2a..e9b12ce2a2d 100644 --- a/tests/functional/event_handler/required_dependencies/test_resolve_async.py +++ b/tests/functional/event_handler/required_dependencies/test_resolve_async.py @@ -1,4 +1,5 @@ import asyncio +import json import pytest @@ -370,3 +371,195 @@ async def get_lambda(): response = result.build(app.current_event, app._cors) assert response["statusCode"] == 500 assert "debug error" in response["body"] + + +# ============================================================================ +# Public resolve_async() tests +# ============================================================================ + + +class MockLambdaContext: + function_name = "test-func" + memory_limit_in_mb = 128 + invoked_function_arn = "arn:aws:lambda:eu-west-1:123456789012:function:test-func" + aws_request_id = "52fdfc07-2182-154f-163f-5f0f9a621d72" + + def get_remaining_time_in_millis(self) -> int: + return 1000 + + +RESOLVE_ASYNC_IDS = ["APIGatewayRestResolver", "APIGatewayHttpResolver", "ALBResolver"] + + +@pytest.fixture( + params=[ + ("apigw_rest", API_REST_EVENT, "/my/path"), + ("apigw_v2", API_RESTV2_EVENT, "/my/path"), + ("alb", ALB_EVENT, "/lambda"), + ], + ids=RESOLVE_ASYNC_IDS, +) +def public_resolver_and_event(request): + key, event, path = request.param + resolvers = { + "apigw_rest": APIGatewayRestResolver(), + "apigw_v2": APIGatewayHttpResolver(), + "alb": ALBResolver(), + } + return resolvers[key], event, path + + +class TestResolveAsyncPublic: + def test_resolve_async_returns_dict_response(self, public_resolver_and_event): + # GIVEN an async handler + app, event, path = public_resolver_and_event + + @app.get(path) + async def get_lambda(): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "async public") + + # WHEN calling resolve_async with event and context + response = asyncio.run(app.resolve_async(event, MockLambdaContext())) + + # THEN a dict response is returned directly (no need to call .build()) + assert response["statusCode"] == 200 + assert response["body"] == "async public" + + def test_resolve_async_with_sync_handler(self, public_resolver_and_event): + # GIVEN a sync handler + app, event, path = public_resolver_and_event + + @app.get(path) + def get_lambda(): + return Response(200, content_types.TEXT_HTML, "sync via public async") + + # WHEN calling resolve_async + response = asyncio.run(app.resolve_async(event, MockLambdaContext())) + + # THEN sync handlers work through the async chain + assert response["statusCode"] == 200 + assert response["body"] == "sync via public async" + + def test_resolve_async_clears_context(self, public_resolver_and_event): + # GIVEN an async handler + app, event, path = public_resolver_and_event + + @app.get(path) + async def get_lambda(): + app.append_context(custom_key="value") + return Response(200, content_types.TEXT_HTML, "ok") + + # WHEN calling resolve_async + asyncio.run(app.resolve_async(event, MockLambdaContext())) + + # THEN the context is cleared after resolution + assert app.context == {} + + def test_resolve_async_not_found(self, public_resolver_and_event): + # GIVEN no matching route + app, event, _path = public_resolver_and_event + + @app.get("/non/existent/path") + async def get_lambda(): + return Response(200, content_types.TEXT_HTML, "unreachable") + + # WHEN calling resolve_async + response = asyncio.run(app.resolve_async(event, MockLambdaContext())) + + # THEN a 404 response is returned + assert response["statusCode"] == 404 + + def test_resolve_async_with_cors(self): + # GIVEN a resolver with CORS and an async handler + app = APIGatewayRestResolver(cors=CORSConfig()) + + @app.get("/my/path") + async def get_lambda(): + return Response(200, content_types.TEXT_HTML, "cors") + + # WHEN calling resolve_async + response = asyncio.run(app.resolve_async(API_REST_EVENT, MockLambdaContext())) + + # THEN CORS headers are included + assert response["statusCode"] == 200 + assert "Access-Control-Allow-Origin" in response.get("multiValueHeaders", response.get("headers", {})) + + def test_resolve_async_with_middleware(self): + # GIVEN a resolver with a middleware + app = APIGatewayRestResolver() + middleware_order = [] + + def tracking_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + middleware_order.append("before") + result = next_middleware(app) + middleware_order.append("after") + return result + + @app.get("/my/path", middlewares=[tracking_middleware]) + async def get_lambda(): + middleware_order.append("handler") + return Response(200, content_types.TEXT_HTML, "ok") + + # WHEN calling resolve_async + response = asyncio.run(app.resolve_async(API_REST_EVENT, MockLambdaContext())) + + # THEN middleware runs in correct order around the handler + assert response["statusCode"] == 200 + assert middleware_order == ["before", "handler", "after"] + + def test_resolve_async_exception_handler(self): + # GIVEN an async handler that raises with an exception handler registered + app = APIGatewayRestResolver() + + @app.exception_handler(ValueError) + def handle_value_error(exc): + return Response(422, content_types.APPLICATION_JSON, json.dumps({"error": str(exc)})) + + @app.get("/my/path") + async def get_lambda(): + raise ValueError("invalid input") + + # WHEN calling resolve_async + response = asyncio.run(app.resolve_async(API_REST_EVENT, MockLambdaContext())) + + # THEN the exception handler catches the error + assert response["statusCode"] == 422 + assert "invalid input" in response["body"] + + def test_resolve_async_debug_mode(self, capsys): + # GIVEN a resolver with debug=True + app = APIGatewayRestResolver(debug=True) + + @app.get("/my/path") + async def get_lambda(): + return Response(200, content_types.TEXT_HTML, "debug") + + # WHEN calling resolve_async + response = asyncio.run(app.resolve_async(API_REST_EVENT, MockLambdaContext())) + + # THEN debug output includes raw event and middleware stack + captured = capsys.readouterr() + assert response["statusCode"] == 200 + assert "Processed Middlewares:" in captured.out + assert "httpMethod" in captured.out + + def test_resolve_async_with_base_proxy_event(self): + # GIVEN a resolver and a BaseProxyEvent passed directly + from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent + + app = APIGatewayRestResolver() + + @app.get("/my/path") + async def get_lambda(): + return Response(200, content_types.TEXT_HTML, "from proxy event") + + # WHEN calling resolve_async with a data class instead of raw dict + proxy_event = APIGatewayProxyEvent(API_REST_EVENT) + + with pytest.warns(UserWarning, match="You don't need to serialize event"): + response = asyncio.run(app.resolve_async(proxy_event, MockLambdaContext())) + + # THEN it still works after extracting raw_event + assert response["statusCode"] == 200 + assert response["body"] == "from proxy event" From 1585b66926ec4ce8309d543ffbed3093979aeae5 Mon Sep 17 00:00:00 2001 From: Catarina Silva Date: Mon, 27 Apr 2026 13:25:06 -0300 Subject: [PATCH 62/84] fix(parser): type hints should reflect primitive types support (#8175) * fix: parser type hints should reflect primitive types As per #4502, primitive types are supported by the `parser` utility. However, the type hints utilized in the functions and envelopes there do not reflect that at the moment, making type checkers lack when inferring the return types, for example. This aims to improve this situation by adjusting the type hints there. * fix: small changes --------- Co-authored-by: Leandro Damascena --- .../utilities/parser/envelopes/apigw.py | 8 ++++---- .../utilities/parser/envelopes/apigw_websocket.py | 8 ++++---- .../utilities/parser/envelopes/apigwv2.py | 8 ++++---- .../utilities/parser/envelopes/base.py | 6 +++++- .../utilities/parser/envelopes/bedrock_agent.py | 14 +++++++------- .../utilities/parser/envelopes/cloudwatch.py | 8 ++++---- .../utilities/parser/envelopes/dynamodb.py | 8 ++++---- .../utilities/parser/envelopes/event_bridge.py | 8 ++++---- .../utilities/parser/envelopes/kafka.py | 8 ++++---- .../utilities/parser/envelopes/kinesis.py | 8 ++++---- .../utilities/parser/envelopes/kinesis_firehose.py | 8 ++++---- .../parser/envelopes/lambda_function_url.py | 8 ++++---- .../utilities/parser/envelopes/sns.py | 14 +++++++------- .../utilities/parser/envelopes/sqs.py | 8 ++++---- .../utilities/parser/envelopes/vpc_lattice.py | 8 ++++---- .../utilities/parser/envelopes/vpc_latticev2.py | 8 ++++---- .../utilities/parser/functions.py | 4 ++-- aws_lambda_powertools/utilities/parser/parser.py | 6 +++++- examples/parser/src/bring_your_own_envelope.py | 8 +++++--- 19 files changed, 83 insertions(+), 73 deletions(-) diff --git a/aws_lambda_powertools/utilities/parser/envelopes/apigw.py b/aws_lambda_powertools/utilities/parser/envelopes/apigw.py index 1a81124cf09..2a7b0c75bd0 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/apigw.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/apigw.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -15,19 +15,19 @@ class ApiGatewayEnvelope(BaseEnvelope): """API Gateway envelope to extract data within body key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Any + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with Api Gateway model {APIGatewayProxyEventModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/apigw_websocket.py b/aws_lambda_powertools/utilities/parser/envelopes/apigw_websocket.py index 37d08dec180..3f5adcde040 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/apigw_websocket.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/apigw_websocket.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import APIGatewayWebSocketMessageEventModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -16,19 +16,19 @@ class ApiGatewayWebSocketEnvelope(BaseEnvelope): """API Gateway WebSockets envelope to extract data within body key of messages routes (not disconnect or connect)""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Any + T | None Parsed detail payload with model provided """ logger.debug( diff --git a/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py b/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py index cb0c6b980d1..760f9aad15e 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/apigwv2.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventV2Model if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -15,19 +15,19 @@ class ApiGatewayV2Envelope(BaseEnvelope): """API Gateway V2 envelope to extract data within body key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Any + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with Api Gateway model V2 {APIGatewayProxyEventV2Model}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/base.py b/aws_lambda_powertools/utilities/parser/envelopes/base.py index dbd76eafe7d..83209422e55 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/base.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/base.py @@ -44,7 +44,11 @@ def _parse(data: dict[str, Any] | Any | None, model: type[T]) -> T | None: return _parse_and_validate_event(data=data, adapter=adapter) @abstractmethod - def parse(self, data: dict[str, Any] | Any | None, model: type[T]): + def parse( + self, + data: dict[str, Any] | Any | None, + model: type[T], + ) -> T | list[T | None] | list[dict[str, T | None]] | None: """Implementation to parse data against envelope model, then against the data model NOTE: Call `_parse` method to fully parse data with model provided. diff --git a/aws_lambda_powertools/utilities/parser/envelopes/bedrock_agent.py b/aws_lambda_powertools/utilities/parser/envelopes/bedrock_agent.py index 392c17cc425..61745f34edd 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/bedrock_agent.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/bedrock_agent.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import BedrockAgentEventModel, BedrockAgentFunctionEventModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -15,19 +15,19 @@ class BedrockAgentEnvelope(BaseEnvelope): """Bedrock Agent envelope to extract data within input_text key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Model | None + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with Bedrock Agent model {BedrockAgentEventModel}") @@ -39,19 +39,19 @@ def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model class BedrockAgentFunctionEnvelope(BaseEnvelope): """Bedrock Agent Function envelope to extract data within input_text key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Model | None + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with Bedrock Agent Function model {BedrockAgentFunctionEventModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py b/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py index 0cfe151b789..a6dac2c5859 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/cloudwatch.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import CloudWatchLogsModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -22,19 +22,19 @@ class CloudWatchLogsEnvelope(BaseEnvelope): Note: The record will be parsed the same way so if model is str """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[Model | None]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[T | None]: """Parses records found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of records parsed with model provided """ logger.debug(f"Parsing incoming data with SNS model {CloudWatchLogsModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py b/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py index a7d56abdb11..4458a1553ea 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import DynamoDBStreamModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -19,19 +19,19 @@ class DynamoDBStreamEnvelope(BaseEnvelope): length of the list is the record's amount in the original event. """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[dict[str, Model | None]]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[dict[str, T | None]]: """Parses DynamoDB Stream records found in either NewImage and OldImage with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of dictionaries with NewImage and OldImage records parsed with model provided """ logger.debug(f"Parsing incoming data with DynamoDB Stream model {DynamoDBStreamModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py b/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py index c123319ca7d..ea972452564 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import EventBridgeModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -15,19 +15,19 @@ class EventBridgeEnvelope(BaseEnvelope): """EventBridge envelope to extract data within detail key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Any + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with EventBridge model {EventBridgeModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/kafka.py b/aws_lambda_powertools/utilities/parser/envelopes/kafka.py index cba374730c6..da08f19b863 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/kafka.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/kafka.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import KafkaMskEventModel, KafkaSelfManagedEventModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -21,19 +21,19 @@ class KafkaEnvelope(BaseEnvelope): all items in the list will be parsed as str and npt as JSON (and vice versa) """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[Model | None]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[T | None]: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of records parsed with model provided """ event_source = cast(dict, data).get("eventSource") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py b/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py index 41527e03930..0085dade352 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/kinesis.py @@ -8,7 +8,7 @@ from aws_lambda_powertools.utilities.parser.models import KinesisDataStreamModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -24,19 +24,19 @@ class KinesisDataStreamEnvelope(BaseEnvelope): all items in the list will be parsed as str and not as JSON (and vice versa) """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[Model | None]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[T | None]: """Parses records found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of records parsed with model provided """ logger.debug(f"Parsing incoming data with Kinesis model {KinesisDataStreamModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py b/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py index e816ac877e9..d478421633d 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/kinesis_firehose.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import KinesisFirehoseModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -25,19 +25,19 @@ class KinesisFirehoseEnvelope(BaseEnvelope): https://docs.aws.amazon.com/lambda/latest/dg/services-kinesisfirehose.html """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[Model | None]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[T | None]: """Parses records found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of records parsed with model provided """ logger.debug(f"Parsing incoming data with Kinesis Firehose model {KinesisFirehoseModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py b/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py index 123cfd514b7..80aeb24930c 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/lambda_function_url.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import LambdaFunctionUrlModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -15,19 +15,19 @@ class LambdaFunctionUrlEnvelope(BaseEnvelope): """Lambda function URL envelope to extract data within body key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Any + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with Lambda function URL model {LambdaFunctionUrlModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/sns.py b/aws_lambda_powertools/utilities/parser/envelopes/sns.py index 98e198c898d..c6d21231e60 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/sns.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/sns.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import SnsModel, SnsNotificationModel, SqsModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -22,19 +22,19 @@ class SnsEnvelope(BaseEnvelope): all items in the list will be parsed as str and npt as JSON (and vice versa) """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[Model | None]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[T | None]: """Parses records found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of records parsed with model provided """ logger.debug(f"Parsing incoming data with SNS model {SnsModel}") @@ -54,19 +54,19 @@ class SnsSqsEnvelope(BaseEnvelope): 3. Finally, parse provided model against payload extracted """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[Model | None]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[T | None]: """Parses records found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of records parsed with model provided """ logger.debug(f"Parsing incoming data with SQS model {SqsModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/sqs.py b/aws_lambda_powertools/utilities/parser/envelopes/sqs.py index 9c64808d3ca..9fe42aed4da 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/sqs.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/sqs.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import SqsModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -22,19 +22,19 @@ class SqsEnvelope(BaseEnvelope): all items in the list will be parsed as str and not as JSON (and vice versa) """ - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> list[Model | None]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> list[T | None]: """Parses records found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - list + list[T | None] List of records parsed with model provided """ logger.debug(f"Parsing incoming data with SQS model {SqsModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/vpc_lattice.py b/aws_lambda_powertools/utilities/parser/envelopes/vpc_lattice.py index 42facf8d279..38c454b9bd8 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/vpc_lattice.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/vpc_lattice.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import VpcLatticeModel if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -15,19 +15,19 @@ class VpcLatticeEnvelope(BaseEnvelope): """Amazon VPC Lattice envelope to extract data within body key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Model | None + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with VPC Lattice model {VpcLatticeModel}") diff --git a/aws_lambda_powertools/utilities/parser/envelopes/vpc_latticev2.py b/aws_lambda_powertools/utilities/parser/envelopes/vpc_latticev2.py index d70a68296a0..f1a218b46a4 100644 --- a/aws_lambda_powertools/utilities/parser/envelopes/vpc_latticev2.py +++ b/aws_lambda_powertools/utilities/parser/envelopes/vpc_latticev2.py @@ -7,7 +7,7 @@ from aws_lambda_powertools.utilities.parser.models import VpcLatticeV2Model if TYPE_CHECKING: - from aws_lambda_powertools.utilities.parser.types import Model + from aws_lambda_powertools.utilities.parser.types import T logger = logging.getLogger(__name__) @@ -15,19 +15,19 @@ class VpcLatticeV2Envelope(BaseEnvelope): """Amazon VPC Lattice envelope to extract data within body key""" - def parse(self, data: dict[str, Any] | Any | None, model: type[Model]) -> Model | None: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: """Parses data found with model provided Parameters ---------- data : dict Lambda event to be parsed - model : type[Model] + model : type[T] Data model provided to parse after extracting data using envelope Returns ------- - Model | None + T | None Parsed detail payload with model provided """ logger.debug(f"Parsing incoming data with VPC Lattice V2 model {VpcLatticeV2Model}") diff --git a/aws_lambda_powertools/utilities/parser/functions.py b/aws_lambda_powertools/utilities/parser/functions.py index 72dde64f12f..d2acb9a7965 100644 --- a/aws_lambda_powertools/utilities/parser/functions.py +++ b/aws_lambda_powertools/utilities/parser/functions.py @@ -16,7 +16,7 @@ logger = logging.getLogger(__name__) -def _retrieve_or_set_model_from_cache(model: type[T]) -> TypeAdapter: +def _retrieve_or_set_model_from_cache(model: type[T]) -> TypeAdapter[T]: """ Retrieves or sets a TypeAdapter instance from the cache for the given model. @@ -49,7 +49,7 @@ def _retrieve_or_set_model_from_cache(model: type[T]) -> TypeAdapter: return CACHE_TYPE_ADAPTER[id_model] -def _parse_and_validate_event(data: dict[str, Any] | Any, adapter: TypeAdapter): +def _parse_and_validate_event(data: dict[str, Any] | Any, adapter: TypeAdapter[T]): """ Parse and validate the event data using the provided adapter. diff --git a/aws_lambda_powertools/utilities/parser/parser.py b/aws_lambda_powertools/utilities/parser/parser.py index 3afad192a01..652cc1ebf1e 100644 --- a/aws_lambda_powertools/utilities/parser/parser.py +++ b/aws_lambda_powertools/utilities/parser/parser.py @@ -124,7 +124,11 @@ def parse(event: dict[str, Any], model: type[T]) -> T: ... # pragma: no cover @overload -def parse(event: dict[str, Any], model: type[T], envelope: type[Envelope]) -> T: ... # pragma: no cover +def parse( # pragma: no cover + event: dict[str, Any], + model: type[T], + envelope: type[Envelope], +) -> T | list[T | None] | list[dict[str, T | None]] | None: ... def parse(event: dict[str, Any], model: type[T], envelope: type[Envelope] | None = None): diff --git a/examples/parser/src/bring_your_own_envelope.py b/examples/parser/src/bring_your_own_envelope.py index 1fb5dea0045..ae60ac58ee3 100644 --- a/examples/parser/src/bring_your_own_envelope.py +++ b/examples/parser/src/bring_your_own_envelope.py @@ -1,5 +1,7 @@ +from __future__ import annotations + import json -from typing import Any, Dict, Optional, Type, TypeVar, Union +from typing import Any, TypeVar from pydantic import BaseModel @@ -7,11 +9,11 @@ from aws_lambda_powertools.utilities.parser.models import EventBridgeModel from aws_lambda_powertools.utilities.typing import LambdaContext -Model = TypeVar("Model", bound=BaseModel) +T = TypeVar("T") class EventBridgeEnvelope(BaseEnvelope): - def parse(self, data: Optional[Union[Dict[str, Any], Any]], model: Type[Model]) -> Optional[Model]: + def parse(self, data: dict[str, Any] | Any | None, model: type[T]) -> T | None: if data is None: return None From 0834363e7da6da3354aa5af4965d1ee3658e1cfa Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 28 Apr 2026 09:43:59 +0100 Subject: [PATCH 63/84] chore(deps): batch dependency updates (#8184) * 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.1118.4 to 2.1119.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1119.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1119.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump the dev-dependencies group with 2 updates Bumps the dev-dependencies group with 2 updates: [mypy](https://github.com/python/mypy) and [ruff](https://github.com/astral-sh/ruff). Updates `mypy` from 1.20.1 to 1.20.2 - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.20.1...v1.20.2) Updates `ruff` from 0.15.11 to 0.15.12 - [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.11...0.15.12) --- updated-dependencies: - dependency-name: mypy dependency-version: 1.20.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: ruff dependency-version: 0.15.12 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump types-protobuf Bumps [types-protobuf](https://github.com/python/typeshed) from 7.34.1.20260403 to 7.34.1.20260408. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-protobuf dependency-version: 7.34.1.20260408 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * 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.250.0a0 to 2.251.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.251.0a0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps): bump redis from 7.3.0 to 7.4.0 Bumps [redis](https://github.com/redis/redis-py) from 7.3.0 to 7.4.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/v7.3.0...v7.4.0) --- updated-dependencies: - dependency-name: redis dependency-version: 7.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps): bump pydantic-settings from 2.13.1 to 2.14.0 Bumps [pydantic-settings](https://github.com/pydantic/pydantic-settings) from 2.13.1 to 2.14.0. - [Release notes](https://github.com/pydantic/pydantic-settings/releases) - [Commits](https://github.com/pydantic/pydantic-settings/compare/v2.13.1...v2.14.0) --- updated-dependencies: - dependency-name: pydantic-settings dependency-version: 2.14.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 8 +- package.json | 2 +- poetry.lock | 189 +++++++++++++++++++++++----------------------- pyproject.toml | 2 +- 4 files changed, 102 insertions(+), 99 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc967b5af6e..19f3361ab9e 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.1118.4" + "aws-cdk": "^2.1119.0" } }, "node_modules/aws-cdk": { - "version": "2.1118.4", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1118.4.tgz", - "integrity": "sha512-wJfRQdvb+FJ2cni059mYdmjhfwhMskP+PAB59BL9jhon+jYtjy8X3pbj3uzHgAOJwNhh6jGkP8xq36Cffccbbw==", + "version": "2.1119.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1119.0.tgz", + "integrity": "sha512-XBxZEKH3BY4M1EX6x0qBkmOAj8viErjpww14iH6Z3z6nI0YzjZeJ05eEl7eJwzUgv7NTGagWBS9m/eDJW5+dAg==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 93ad13c3b51..25ee230447c 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.1118.4" + "aws-cdk": "^2.1119.0" } } diff --git a/poetry.lock b/poetry.lock index eeb46da9ed6..227b6768dab 100644 --- a/poetry.lock +++ b/poetry.lock @@ -205,18 +205,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-lambda-python-alpha" -version = "2.250.0a0" +version = "2.251.0a0" description = "The CDK Construct Library for AWS Lambda in Python" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_aws_lambda_python_alpha-2.250.0a0-py3-none-any.whl", hash = "sha256:792b8d64fca6089908f9d3462a9dd81a32493fd1422d50d0fd73592590b83c0b"}, - {file = "aws_cdk_aws_lambda_python_alpha-2.250.0a0.tar.gz", hash = "sha256:55b09a9f31a7267c5ec10f1f64e8e1d3709eaad4738fd49e170671d1fa984f60"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.251.0a0-py3-none-any.whl", hash = "sha256:c5780e06890582166932269ef594f4f2050961c2a1431429821ea45ea7a338fc"}, + {file = "aws_cdk_aws_lambda_python_alpha-2.251.0a0.tar.gz", hash = "sha256:04f2b8edb36cb2eb3494169100d3eaad54f7acb577bd870a5343f6d95a5480da"}, ] [package.dependencies] -aws-cdk-lib = ">=2.250.0,<3.0.0" +aws-cdk-lib = ">=2.251.0,<3.0.0" constructs = ">=10.5.0,<11.0.0" jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" @@ -224,37 +224,37 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-cloud-assembly-schema" -version = "53.13.0" +version = "53.18.0" description = "Schema for the protocol between CDK framework and CDK CLI" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_cloud_assembly_schema-53.13.0-py3-none-any.whl", hash = "sha256:b6612da9451a23e1f1ddacfe94dc5359b5ca42bad91a923b04a3d12e14078016"}, - {file = "aws_cdk_cloud_assembly_schema-53.13.0.tar.gz", hash = "sha256:d0f4ed7f8122f57d62983c0274d10480909e4b15362d28ff1f9b505e2bd92a72"}, + {file = "aws_cdk_cloud_assembly_schema-53.18.0-py3-none-any.whl", hash = "sha256:291a9645d70bb1e2fd73fb8e58fd48503353751b8330d8f2d72dafc13bdf84ac"}, + {file = "aws_cdk_cloud_assembly_schema-53.18.0.tar.gz", hash = "sha256:bb377de485f5214a47c78268b2a985332c83d7fd5c06922d1a9538ba31320afc"}, ] [package.dependencies] -jsii = ">=1.127.0,<2.0.0" +jsii = ">=1.128.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.250.0" +version = "2.251.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.250.0-py3-none-any.whl", hash = "sha256:427c9a062f350c16e301326fd6ca0440428f9cc0e85421aaa69a9afa57228acc"}, - {file = "aws_cdk_lib-2.250.0.tar.gz", hash = "sha256:6e5cb8def9208a45cede1376a81d7508b3889879ccc7e9cddaa4fd807da0b144"}, + {file = "aws_cdk_lib-2.251.0-py3-none-any.whl", hash = "sha256:a684f3461d096443ac688adbf559abe1af2d50dd5c8e0fa7dbf4a5f361702db8"}, + {file = "aws_cdk_lib-2.251.0.tar.gz", hash = "sha256:ed69e7ea6896c62ac2ce01857083601baf541d5d875370bee6d213d641e8921e"}, ] [package.dependencies] "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.0.0,<54.0.0" +"aws-cdk.cloud-assembly-schema" = ">=53.18.0,<54.0.0" constructs = ">=10.5.0,<11.0.0" jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" @@ -2276,14 +2276,14 @@ files = [ [[package]] name = "jsii" -version = "1.127.0" +version = "1.128.0" description = "Python client for jsii runtime" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "jsii-1.127.0-py3-none-any.whl", hash = "sha256:92a11f39e461f5168e2467efd53351cc32b118314b95cc6323c2d044eb299eaf"}, - {file = "jsii-1.127.0.tar.gz", hash = "sha256:631a13d73265eaa22c0c0804e77fe59c8fcc3af3a94de9923af65380b6ad267a"}, + {file = "jsii-1.128.0-py3-none-any.whl", hash = "sha256:25912f66516c08c21dfcd350c9efd4c71548a98fd1af61ed08e73d99a73e0af0"}, + {file = "jsii-1.128.0.tar.gz", hash = "sha256:05f21e1c16e899cd65db27e54c9379b561cf368c6d670b60ea012bffa801b6d7"}, ] [package.dependencies] @@ -2918,56 +2918,56 @@ dill = ">=0.4.1" [[package]] name = "mypy" -version = "1.20.1" +version = "1.20.2" description = "Optional static typing for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mypy-1.20.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3ba5d1e712ada9c3b6223dcbc5a31dac334ed62991e5caa17bcf5a4ddc349af0"}, - {file = "mypy-1.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e731284c117b0987fb1e6c5013a56f33e7faa1fce594066ab83876183ce1c66"}, - {file = "mypy-1.20.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f8e945b872a05f4fbefabe2249c0b07b6b194e5e11a86ebee9edf855de09806c"}, - {file = "mypy-1.20.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fc88acef0dc9b15246502b418980478c1bfc9702057a0e1e7598d01a7af8937"}, - {file = "mypy-1.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:14911a115c73608f155f648b978c5055d16ff974e6b1b5512d7fedf4fa8b15c6"}, - {file = "mypy-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:76d9b4c992cca3331d9793ef197ae360ea44953cf35beb2526e95b9e074f2866"}, - {file = "mypy-1.20.1-cp310-cp310-win_arm64.whl", hash = "sha256:b408722f80be44845da555671a5ef3a0c63f51ca5752b0c20e992dc9c0fbd3cd"}, - {file = "mypy-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c01eb9bac2c6a962d00f9d23421cd2913840e65bba365167d057bd0b4171a92e"}, - {file = "mypy-1.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55d12ddbd8a9cac5b276878bd534fa39fff5bf543dc6ae18f25d30c8d7d27fca"}, - {file = "mypy-1.20.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0aa322c1468b6cdfc927a44ce130f79bb44bcd34eb4a009eb9f96571fd80955"}, - {file = "mypy-1.20.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3f8bc95899cf676b6e2285779a08a998cc3a7b26f1026752df9d2741df3c79e8"}, - {file = "mypy-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:47c2b90191a870a04041e910277494b0d92f0711be9e524d45c074fe60c00b65"}, - {file = "mypy-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:9857dc8d2ec1a392ffbda518075beb00ac58859979c79f9e6bdcb7277082c2f2"}, - {file = "mypy-1.20.1-cp311-cp311-win_arm64.whl", hash = "sha256:09d8df92bb25b6065ab91b178da843dda67b33eb819321679a6e98a907ce0e10"}, - {file = "mypy-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:36ee2b9c6599c230fea89bbd79f401f9f9f8e9fcf0c777827789b19b7da90f51"}, - {file = "mypy-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fba3fb0968a7b48806b0c90f38d39296f10766885a94c83bd21399de1e14eb28"}, - {file = "mypy-1.20.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef1415a637cd3627d6304dfbeddbadd21079dafc2a8a753c477ce4fc0c2af54f"}, - {file = "mypy-1.20.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef3461b1ad5cd446e540016e90b5984657edda39f982f4cc45ca317b628f5a37"}, - {file = "mypy-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:542dd63c9e1339b6092eb25bd515f3a32a1453aee8c9521d2ddb17dacd840237"}, - {file = "mypy-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:1d55c7cd8ca22e31f93af2a01160a9e95465b5878de23dba7e48116052f20a8d"}, - {file = "mypy-1.20.1-cp312-cp312-win_arm64.whl", hash = "sha256:f5b84a79070586e0d353ee07b719d9d0a4aa7c8ee90c0ea97747e98cbe193019"}, - {file = "mypy-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f3886c03e40afefd327bd70b3f634b39ea82e87f314edaa4d0cce4b927ddcc1"}, - {file = "mypy-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e860eb3904f9764e83bafd70c8250bdffdc7dde6b82f486e8156348bf7ceb184"}, - {file = "mypy-1.20.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4b5aac6e785719da51a84f5d09e9e843d473170a9045b1ea7ea1af86225df4b"}, - {file = "mypy-1.20.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f37b6cd0fe2ad3a20f05ace48ca3523fc52ff86940e34937b439613b6854472e"}, - {file = "mypy-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4bbb0f6b54ce7cc350ef4a770650d15fa70edd99ad5267e227133eda9c94218"}, - {file = "mypy-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:c3dc20f8ec76eecd77148cdd2f1542ed496e51e185713bf488a414f862deb8f2"}, - {file = "mypy-1.20.1-cp313-cp313-win_arm64.whl", hash = "sha256:a9d62bbac5d6d46718e2b0330b25e6264463ed832722b8f7d4440ff1be3ca895"}, - {file = "mypy-1.20.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:12927b9c0ed794daedcf1dab055b6c613d9d5659ac511e8d936d96f19c087d12"}, - {file = "mypy-1.20.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:752507dd481e958b2c08fc966d3806c962af5a9433b5bf8f3bdd7175c20e34fe"}, - {file = "mypy-1.20.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c614655b5a065e56274c6cbbe405f7cf7e96c0654db7ba39bc680238837f7b08"}, - {file = "mypy-1.20.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2c3f6221a76f34d5100c6d35b3ef6b947054123c3f8d6938a4ba00b1308aa572"}, - {file = "mypy-1.20.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4bdfc06303ac06500af71ea0cdbe995c502b3c9ba32f3f8313523c137a25d1b6"}, - {file = "mypy-1.20.1-cp314-cp314-win_amd64.whl", hash = "sha256:0131edd7eba289973d1ba1003d1a37c426b85cdef76650cd02da6420898a5eb3"}, - {file = "mypy-1.20.1-cp314-cp314-win_arm64.whl", hash = "sha256:33f02904feb2c07e1fdf7909026206396c9deeb9e6f34d466b4cfedb0aadbbe4"}, - {file = "mypy-1.20.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:168472149dd8cc505c98cefd21ad77e4257ed6022cd5ed2fe2999bed56977a5a"}, - {file = "mypy-1.20.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:eb674600309a8f22790cca883a97c90299f948183ebb210fbef6bcee07cb1986"}, - {file = "mypy-1.20.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef2b2e4cc464ba9795459f2586923abd58a0055487cbe558cb538ea6e6bc142a"}, - {file = "mypy-1.20.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dee461d396dd46b3f0ed5a098dbc9b8860c81c46ad44fa071afcfbc149f167c9"}, - {file = "mypy-1.20.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e364926308b3e66f1361f81a566fc1b2f8cd47fc8525e8136d4058a65a4b4f02"}, - {file = "mypy-1.20.1-cp314-cp314t-win_amd64.whl", hash = "sha256:a0c17fbd746d38c70cbc42647cfd884f845a9708a4b160a8b4f7e70d41f4d7fa"}, - {file = "mypy-1.20.1-cp314-cp314t-win_arm64.whl", hash = "sha256:db2cb89654626a912efda69c0d5c1d22d948265e2069010d3dde3abf751c7d08"}, - {file = "mypy-1.20.1-py3-none-any.whl", hash = "sha256:1aae28507f253fe82d883790d1c0a0d35798a810117c88184097fe8881052f06"}, - {file = "mypy-1.20.1.tar.gz", hash = "sha256:6fc3f4ecd52de81648fed1945498bf42fa2993ddfad67c9056df36ae5757f804"}, + {file = "mypy-1.20.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cf5a4db6dca263010e2c7bff081c89383c72d187ba2cf4c44759aac970e2f0c4"}, + {file = "mypy-1.20.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b0e817b518bff7facd7f85ea05b643ad8bdcce684cf29784987b0a7c8e1f997"}, + {file = "mypy-1.20.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97d7b9a485b40f8ca425460e89bf1da2814625b2da627c0dcc6aa46c92631d14"}, + {file = "mypy-1.20.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e1c12f6d2db3d78b909b5f77513c11eb7f2dd2782b96a3ab6dffc7d44575c99"}, + {file = "mypy-1.20.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:89dce27e142d25ffbc154c1819383b69f2e9234dc4ed4766f42e0e8cb264ab5c"}, + {file = "mypy-1.20.2-cp310-cp310-win_amd64.whl", hash = "sha256:f376e37f9bf2a946872fc5fd1199c99310748e3c26c7a26683f13f8bdb756cbd"}, + {file = "mypy-1.20.2-cp310-cp310-win_arm64.whl", hash = "sha256:6e2b469efd811707bc530fd1effef0f5d6eebcb7fe376affae69025da4b979a2"}, + {file = "mypy-1.20.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4077797a273e56e8843d001e9dfe4ba10e33323d6ade647ff260e5cd97d9758c"}, + {file = "mypy-1.20.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cdecf62abcc4292500d7858aeae87a1f8f1150f4c4dd08fb0b336ee79b2a6df3"}, + {file = "mypy-1.20.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c566c3a88b6ece59b3d70f65bedef17304f48eb52ff040a6a18214e1917b3254"}, + {file = "mypy-1.20.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0deb80d062b2479f2c87ae568f89845afc71d11bc41b04179e58165fd9f31e98"}, + {file = "mypy-1.20.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bba9ad231e92a3e424b3e56b65aa17704993425bba97e302c832f9466bb85bac"}, + {file = "mypy-1.20.2-cp311-cp311-win_amd64.whl", hash = "sha256:baf593f2765fa3a6b1ef95807dbaa3d25b594f6a52adcc506a6b9cb115e1be67"}, + {file = "mypy-1.20.2-cp311-cp311-win_arm64.whl", hash = "sha256:20175a1c0f49863946ec20b7f63255768058ac4f07d2b9ded6a6b46cfb5a9100"}, + {file = "mypy-1.20.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4dbfcf869f6b0517f70cf0030ba6ea1d6645e132337a7d5204a18d8d5636c02b"}, + {file = "mypy-1.20.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b6481b228d072315b053210b01ac320e1be243dc17f9e5887ef167f23f5fae4"}, + {file = "mypy-1.20.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34397cdced6b90b836e38182076049fdb41424322e0b0728c946b0939ebdf9f6"}, + {file = "mypy-1.20.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5da6976f20cae27059ea8d0c86e7cef3de720e04c4bb9ee18e3690fdb792066"}, + {file = "mypy-1.20.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:56908d7e08318d39f85b1f0c6cfd47b0cac1a130da677630dac0de3e0623e102"}, + {file = "mypy-1.20.2-cp312-cp312-win_amd64.whl", hash = "sha256:d52ad8d78522da1d308789df651ee5379088e77c76cb1994858d40a426b343b9"}, + {file = "mypy-1.20.2-cp312-cp312-win_arm64.whl", hash = "sha256:785b08db19c9f214dc37d65f7c165d19a30fcecb48abfa30f31b01b5acaabb58"}, + {file = "mypy-1.20.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:edfbfca868cdd6bd8d974a60f8a3682f5565d3f5c99b327640cedd24c4264026"}, + {file = "mypy-1.20.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e2877a02380adfcdbc69071a0f74d6e9dbbf593c0dc9d174e1f223ffd5281943"}, + {file = "mypy-1.20.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7488448de6007cd5177c6cea0517ac33b4c0f5ee9b5e9f2be51ce75511a85517"}, + {file = "mypy-1.20.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb9c2fa06887e21d6a3a868762acb82aec34e2c6fd0174064f27c93ede68ad15"}, + {file = "mypy-1.20.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d56a78b646f2e3daa865bc70cd5ec5a46c50045801ca8ff17a0c43abc97e3ee"}, + {file = "mypy-1.20.2-cp313-cp313-win_amd64.whl", hash = "sha256:2a4102b03bb7481d9a91a6da8d174740c9c8c4401024684b9ca3b7cc5e49852f"}, + {file = "mypy-1.20.2-cp313-cp313-win_arm64.whl", hash = "sha256:a95a9248b0c6fd933a442c03c3b113c3b61320086b88e2c444676d3fd1ca3330"}, + {file = "mypy-1.20.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:419413398fe250aae057fd2fe50166b61077083c9b82754c341cf4fd73038f30"}, + {file = "mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e73c07f23009962885c197ccb9b41356a30cc0e5a1d0c2ea8fd8fb1362d7f924"}, + {file = "mypy-1.20.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c64e5973df366b747646fc98da921f9d6eba9716d57d1db94a83c026a08e0fb"}, + {file = "mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a65aa591af023864fd08a97da9974e919452cfe19cb146c8a5dc692626445dc"}, + {file = "mypy-1.20.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4fef51b01e638974a6e69885687e9bd40c8d1e09a6cd291cca0619625cf1f558"}, + {file = "mypy-1.20.2-cp314-cp314-win_amd64.whl", hash = "sha256:913485a03f1bcf5d279409a9d2b9ed565c151f61c09f29991e5faa14033da4c8"}, + {file = "mypy-1.20.2-cp314-cp314-win_arm64.whl", hash = "sha256:c3bae4f855d965b5453784300c12ffc63a548304ac7f99e55d4dc7c898673aa3"}, + {file = "mypy-1.20.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2de3dcea53babc1c3237a19002bc3d228ce1833278f093b8d619e06e7cc79609"}, + {file = "mypy-1.20.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:52b176444e2e5054dfcbcb8c75b0b719865c96247b37407184bbfca5c353f2c2"}, + {file = "mypy-1.20.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:688c3312e5dadb573a2c69c82af3a298d43ecf9e6d264e0f95df960b5f6ac19c"}, + {file = "mypy-1.20.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29752dbbf8cc53f89f6ac096d363314333045c257c9c75cbd189ca2de0455744"}, + {file = "mypy-1.20.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:803203d2b6ea644982c644895c2f78b28d0e208bba7b27d9b921e0ec5eb207c6"}, + {file = "mypy-1.20.2-cp314-cp314t-win_amd64.whl", hash = "sha256:9bcb8aa397ff0093c824182fd76a935a9ba7ad097fcbef80ae89bf6c1731d8ec"}, + {file = "mypy-1.20.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e061b58443f1736f8a37c48978d7ab581636d6ab03e3d4f99e3fa90463bb9382"}, + {file = "mypy-1.20.2-py3-none-any.whl", hash = "sha256:a94c5a76ab46c5e6257c7972b6c8cff0574201ca7dc05647e33e795d78680563"}, + {file = "mypy-1.20.2.tar.gz", hash = "sha256:e8222c26daaafd9e8626dec58ae36029f82585890589576f769a650dd20fd665"}, ] [package.dependencies] @@ -2975,7 +2975,10 @@ librt = {version = ">=0.8.0", markers = "platform_python_implementation != \"PyP mypy_extensions = ">=1.0.0" pathspec = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing_extensions = ">=4.6.0" +typing_extensions = [ + {version = ">=4.6.0", markers = "python_version < \"3.15\""}, + {version = ">=4.14.0", markers = "python_version >= \"3.15\""}, +] [package.extras] dmypy = ["psutil (>=4.0)"] @@ -3190,7 +3193,7 @@ description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = ">=3.11" groups = ["dev"] -markers = "python_version >= \"3.14.0\"" +markers = "python_version >= \"3.14.0\" and python_version < \"3.15\"" files = [ {file = "networkx-3.6-py3-none-any.whl", hash = "sha256:cdb395b105806062473d3be36458d8f1459a4e4b98e236a66c3a48996e07684f"}, {file = "networkx-3.6.tar.gz", hash = "sha256:285276002ad1f7f7da0f7b42f004bcba70d381e936559166363707fdad3d72ad"}, @@ -3214,7 +3217,7 @@ description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = "!=3.14.1,>=3.11" groups = ["dev"] -markers = "python_version >= \"3.11.0\" and python_version < \"3.14.0\"" +markers = "python_version >= \"3.11.0\" and python_version < \"3.14.0\" or python_version >= \"3.15\"" files = [ {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, {file = "networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509"}, @@ -3564,15 +3567,15 @@ typing-extensions = ">=4.14.1" [[package]] name = "pydantic-settings" -version = "2.13.1" +version = "2.14.0" description = "Settings management using Pydantic" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"all\"" files = [ - {file = "pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237"}, - {file = "pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025"}, + {file = "pydantic_settings-2.14.0-py3-none-any.whl", hash = "sha256:fc8d5d692eb7092e43c8647c1c35a3ecd00e040fcf02ed86f4cb5458ca62182e"}, + {file = "pydantic_settings-2.14.0.tar.gz", hash = "sha256:24285fd4b0e0c06507dd9fdfd331ee23794305352aaec8fc4eb92d4047aeb67d"}, ] [package.dependencies] @@ -3581,7 +3584,7 @@ python-dotenv = ">=0.21.0" typing-inspection = ">=0.4.0" [package.extras] -aws-secrets-manager = ["boto3 (>=1.35.0)", "boto3-stubs[secretsmanager]"] +aws-secrets-manager = ["boto3 (>=1.35.0)", "types-boto3[secretsmanager]"] azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] gcp-secret-manager = ["google-cloud-secret-manager (>=2.23.1)"] toml = ["tomli (>=2.0.1)"] @@ -3962,14 +3965,14 @@ toml = ["tomli (>=2.0.1)"] [[package]] name = "redis" -version = "7.3.0" +version = "7.4.0" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "redis-7.3.0-py3-none-any.whl", hash = "sha256:9d4fcb002a12a5e3c3fbe005d59c48a2cc231f87fbb2f6b70c2d89bb64fec364"}, - {file = "redis-7.3.0.tar.gz", hash = "sha256:4d1b768aafcf41b01022410b3cc4f15a07d9b3d6fe0c66fc967da2c88e551034"}, + {file = "redis-7.4.0-py3-none-any.whl", hash = "sha256:a9c74a5c893a5ef8455a5adb793a31bb70feb821c86eccb62eebef5a19c429ec"}, + {file = "redis-7.4.0.tar.gz", hash = "sha256:64a6ea7bf567ad43c964d2c30d82853f8df927c5c9017766c55a1d1ed95d18ad"}, ] markers = {main = "extra == \"redis\""} @@ -4307,30 +4310,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.11" +version = "0.15.12" 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.11-py3-none-linux_armv6l.whl", hash = "sha256:e927cfff503135c558eb581a0c9792264aae9507904eb27809cdcff2f2c847b7"}, - {file = "ruff-0.15.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7a1b5b2938d8f890b76084d4fa843604d787a912541eae85fd7e233398bbb73e"}, - {file = "ruff-0.15.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d4176f3d194afbdaee6e41b9ccb1a2c287dba8700047df474abfbe773825d1cb"}, - {file = "ruff-0.15.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b17c886fb88203ced3afe7f14e8d5ae96e9d2f4ccc0ee66aa19f2c2675a27e4"}, - {file = "ruff-0.15.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:49fafa220220afe7758a487b048de4c8f9f767f37dfefad46b9dd06759d003eb"}, - {file = "ruff-0.15.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2ab8427e74a00d93b8bda1307b1e60970d40f304af38bccb218e056c220120d"}, - {file = "ruff-0.15.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:195072c0c8e1fc8f940652073df082e37a5d9cb43b4ab1e4d0566ab8977a13b7"}, - {file = "ruff-0.15.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a0996d486af3920dec930a2e7daed4847dfc12649b537a9335585ada163e9e"}, - {file = "ruff-0.15.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bef2cb556d509259f1fe440bb9cd33c756222cf0a7afe90d15edf0866702431"}, - {file = "ruff-0.15.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:030d921a836d7d4a12cf6e8d984a88b66094ccb0e0f17ddd55067c331191bf19"}, - {file = "ruff-0.15.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0e783b599b4577788dbbb66b9addcef87e9a8832f4ce0c19e34bf55543a2f890"}, - {file = "ruff-0.15.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ae90592246625ba4a34349d68ec28d4400d75182b71baa196ddb9f82db025ef5"}, - {file = "ruff-0.15.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1f111d62e3c983ed20e0ca2e800f8d77433a5b1161947df99a5c2a3fb60514f0"}, - {file = "ruff-0.15.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:06f483d6646f59eaffba9ae30956370d3a886625f511a3108994000480621d1c"}, - {file = "ruff-0.15.11-py3-none-win32.whl", hash = "sha256:476a2aa56b7da0b73a3ee80b6b2f0e19cce544245479adde7baa65466664d5f3"}, - {file = "ruff-0.15.11-py3-none-win_amd64.whl", hash = "sha256:8b6756d88d7e234fb0c98c91511aae3cd519d5e3ed271cae31b20f39cb2a12a3"}, - {file = "ruff-0.15.11-py3-none-win_arm64.whl", hash = "sha256:063fed18cc1bbe0ee7393957284a6fe8b588c6a406a285af3ee3f46da2391ee4"}, - {file = "ruff-0.15.11.tar.gz", hash = "sha256:f092b21708bf0e7437ce9ada249dfe688ff9a0954fc94abab05dcea7dcd29c33"}, + {file = "ruff-0.15.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c"}, + {file = "ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c"}, + {file = "ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5"}, + {file = "ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002"}, + {file = "ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5"}, + {file = "ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6"}, + {file = "ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33"}, + {file = "ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847"}, + {file = "ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0"}, + {file = "ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339"}, + {file = "ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5"}, + {file = "ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd"}, + {file = "ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b"}, + {file = "ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e"}, + {file = "ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20"}, + {file = "ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d"}, + {file = "ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f"}, + {file = "ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6"}, ] [[package]] @@ -4696,14 +4699,14 @@ types-setuptools = "*" [[package]] name = "types-protobuf" -version = "7.34.1.20260403" +version = "7.34.1.20260408" description = "Typing stubs for protobuf" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_protobuf-7.34.1.20260403-py3-none-any.whl", hash = "sha256:16d9bbca52ab0f306279958878567df2520f3f5579059419b0ce149a0ad1e332"}, - {file = "types_protobuf-7.34.1.20260403.tar.gz", hash = "sha256:8d7881867888e667eb9563c08a916fccdc12bdb5f9f34c31d217cce876e36765"}, + {file = "types_protobuf-7.34.1.20260408-py3-none-any.whl", hash = "sha256:ebbcd4e27b145aef6a59bc0cb6c013b3528151c1ba5e7f7337aeee355d276a5e"}, + {file = "types_protobuf-7.34.1.20260408.tar.gz", hash = "sha256:e2c0a0430e08c75b52671a6f0035abfdcc791aad12af16274282de1b721758ab"}, ] [[package]] @@ -5186,4 +5189,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "1f2cdd13aaff7bb08f2b86bb460b8f9688597ad0819225c0f4af051f10077590" +content-hash = "9522eab0cc391eb22adcd6241427c14efac426740e443c47806b93d96d42fb0d" diff --git a/pyproject.toml b/pyproject.toml index 46835912a74..ed343e04f8f 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.12" +ruff = ">=0.5.1,<0.15.13" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.8" types-redis = "^4.6.0.7" From 08c99219e000738c7be3e5b22338566dcb76b987 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 30 Apr 2026 04:08:57 -0400 Subject: [PATCH 64/84] fix(idempotency): resolve tech debt issues with falsy responses and Redis persistency (#8176) * fix(idempotency): fix str(None) producing "None" string in Redis persistence Replace str(item.get(...)) with item.get(...) to avoid storing the string "None" when a value is missing from Redis hash map. When data_attr or validation_key_attr is missing from Redis, item.get() returns None. Wrapping with str() converts it to the string "None" which is incorrect. Now correctly returns None. Part of #8090 Signed-off-by: hirenkumar-n-dholariya * refactor(idempotency): extract duplicated idempotency key null-check into helper method Replace 4 identical null-check blocks across save_success, save_inprogress, delete_record, and get_record with a single helper method _get_idempotency_key_or_return_none() to reduce code duplication. The helper encapsulates the pattern of calling _get_hashed_idempotency_key() and returning None early if the key is None, keeping each method cleaner and easier to read. Part of #8090 Signed-off-by: hirenkumar-n-dholariya * test(idempotency): add unit tests for tech debt fixes in issue #8090 Fix 1 - str(None) in Redis _item_to_data_record: - Missing data_attr returns None not string "None" - Existing data_attr returns value correctly - Demonstrates old bug vs new correct behavior Fix 2 - _get_idempotency_key_or_return_none helper: - Returns None when key is None - Returns key string when key exists - Correctly used in save_success, save_inprogress, delete_record, and get_record (all return None early) Part of #8090 Signed-off-by: hirenkumar-n-dholariya * fix(idempotency): fix falsy response handling and inconsistent status constant Fix 1 - Falsy response handling in _get_function_response(): Replace `if response else None` with `if response is not None else None`. So valid falsy return values (0, False, {}, [], "") are correctly serialized and stored instead of being silently discarded. Fix 2 - Inconsistent status constant in _process_idempotency(): Replace string literal "INPROGRESS" with STATUS_CONSTANTS["INPROGRESS"] for consistency with the rest of the codebase. Part of #8090 Signed-off-by: hirenkumar-n-dholariya * refactor(idempotency): revert helper method - restore original inline null-check pattern Per Leandro Damascena's feedback: _get_idempotency_key_or_return_none() helper added indirection without reducing duplication since the if None: return None check remained in all 4 callers anyway. Restored original inline 3-line pattern in save_success, save_inprogress, delete_record, and get_record which is clearer and instantly readable. Part of #8090 Signed-off-by: hirenkumar-n-dholariya * test(idempotency): remove standalone test file per maintainer feedback Tests should be added to existing test files following established patterns, not in new standalone files. The Redis fix will be tested in _redis/test_redis_layer.py next to the existing test_item_to_datarecord_conversion. Part of #8090 Signed-off-by: hirenkumar-n-dholariya * test(idempotency): add regression test for str(None) fix in _item_to_data_record Added single test next to existing test_item_to_datarecord_conversion to verify missing Redis attributes return None instead of string "None". Follows existing test patterns using fixtures instead of MagicMock. Part of #8090 Signed-off-by: hirenkumar-n-dholariya * fix(idempotency): fix ruff formatting - remove trailing whitespace in base.py Remove trailing whitespace on blank line between is_missing_idempotency_key and _get_hashed_payload methods to pass ruff format check. Part of #8090 Signed-off-by: hirenkumar-n-dholariya * fix(idempotency): fix test fixture name and trailing whitespace in test_redis_layer.py - Fix fixture name from persistence_store_redis to persistence_store_standalone_redis to match existing fixture defined in the test file - Remove trailing whitespace on blank line after test function to pass ruff format check Part of #8090 Signed-off-by: hirenkumar-n-dholariya * fix: small changes --------- Signed-off-by: hirenkumar-n-dholariya Co-authored-by: Leandro Damascena --- .../utilities/idempotency/base.py | 4 ++-- .../idempotency/persistence/redis.py | 4 ++-- .../idempotency/_redis/test_redis_layer.py | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/base.py b/aws_lambda_powertools/utilities/idempotency/base.py index f6a3563c103..bee109ef842 100644 --- a/aws_lambda_powertools/utilities/idempotency/base.py +++ b/aws_lambda_powertools/utilities/idempotency/base.py @@ -167,7 +167,7 @@ def _process_idempotency(self, is_replay: bool): # We give preference to ReturnValuesOnConditionCheckFailure because it is a faster and more cost-effective # way of retrieving the existing record after a failed conditional write operation. record = exc.old_data_record or self._get_idempotency_record() - if is_replay and record is not None and record.status == "INPROGRESS": + if is_replay and record is not None and record.status == STATUS_CONSTANTS["INPROGRESS"]: return self._get_function_response() # If a record is found, handle it for status if record: @@ -296,7 +296,7 @@ def _get_function_response(self): else: try: - serialized_response: dict = self.output_serializer.to_dict(response) if response else None + serialized_response: dict = self.output_serializer.to_dict(response) if response is not None else None self.persistence_store.save_success(data=self.data, result=serialized_response) except Exception as save_exception: raise IdempotencyPersistenceLayerError( diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py index d1c490ee0f3..9327c33bda7 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py @@ -332,8 +332,8 @@ def _item_to_data_record(self, idempotency_key: str, item: dict[str, Any]) -> Da idempotency_key=idempotency_key, status=item[self.status_attr], in_progress_expiry_timestamp=in_progress_expiry_timestamp, - response_data=str(item.get(self.data_attr)), - payload_hash=str(item.get(self.validation_key_attr)), + response_data=item.get(self.data_attr, ""), + payload_hash=item.get(self.validation_key_attr, ""), expiry_timestamp=item.get("expiration"), ) diff --git a/tests/functional/idempotency/_redis/test_redis_layer.py b/tests/functional/idempotency/_redis/test_redis_layer.py index c2a0976b0ab..22c3b9a6d83 100644 --- a/tests/functional/idempotency/_redis/test_redis_layer.py +++ b/tests/functional/idempotency/_redis/test_redis_layer.py @@ -330,6 +330,25 @@ def test_item_to_datarecord_conversion(valid_record): assert record.in_progress_expiry_timestamp == item[layer.in_progress_expiry_attr] +def test_item_to_datarecord_conversion_missing_optional_attributes(persistence_store_standalone_redis): + """ + When data_attr or validation_key_attr is missing from Redis, + response_data and payload_hash should be empty string, not the string "None". + Regression test for: https://github.com/aws-powertools/powertools-lambda-python/issues/8090 + """ + idempotency_key = "test-func#abc123" + item = { + persistence_store_standalone_redis.status_attr: "COMPLETED", + persistence_store_standalone_redis.expiry_attr: 9999999999, + # data_attr and validation_key_attr intentionally absent + } + + record = persistence_store_standalone_redis._item_to_data_record(idempotency_key, item) + + assert record.response_data == "" + assert record.payload_hash == "" + + def test_idempotent_function_and_lambda_handler_redis_basic( persistence_store_standalone_redis: RedisCachePersistenceLayer, lambda_context, From 10ffef1760ec298f8cfe6892379bab08bcf2f50f Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Fri, 1 May 2026 16:51:35 +0100 Subject: [PATCH 65/84] feat(openapi): add compute_field support (#8188) feat: add compute_field support --- .../event_handler/openapi/params.py | 4 +- .../test_openapi_schema_pydantic_v2.py | 78 ++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/params.py b/aws_lambda_powertools/event_handler/openapi/params.py index 1ade081959f..468e2253b39 100644 --- a/aws_lambda_powertools/event_handler/openapi/params.py +++ b/aws_lambda_powertools/event_handler/openapi/params.py @@ -901,7 +901,7 @@ def analyze_param( if is_response_param: field_info.default = Required - field = _create_model_field(field_info, type_annotation, param_name, is_path_param) + field = _create_model_field(field_info, type_annotation, param_name, is_path_param, is_response_param) return field @@ -1138,6 +1138,7 @@ def _create_model_field( type_annotation: Any, param_name: str, is_path_param: bool, + is_response_param: bool = False, ) -> ModelField | None: """ Create a new ModelField from a FieldInfo and type annotation. @@ -1164,4 +1165,5 @@ def _create_model_field( alias=field_info.alias, required=field_info.default in (Required, Undefined), field_info=field_info, + mode="serialization" if is_response_param else "validation", ) 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 0df8f6a22c5..d25811d24ae 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 @@ -3,7 +3,7 @@ from typing import Literal, Optional import pytest -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, computed_field from typing_extensions import Annotated from aws_lambda_powertools.event_handler import APIGatewayRestResolver @@ -110,3 +110,79 @@ def create_todo(todo: TodoEnvelope): ... # THEN the schema should be valid assert openapi31_schema(schema) + + +@pytest.mark.usefixtures("pydanticv2_only") +def test_openapi_schema_includes_computed_field(): + # GIVEN a model with a computed_field + class User(BaseModel): + first_name: str + last_name: str + + @computed_field + @property + def full_name(self) -> str: + return f"{self.first_name} {self.last_name}" + + # GIVEN APIGatewayRestResolver with a handler returning that model + app = APIGatewayRestResolver(enable_validation=True) + + @app.get("/user") + def get_user() -> User: + return User(first_name="John", last_name="Doe") + + # WHEN we get the schema + schema = json.loads(app.get_openapi_json_schema()) + + # THEN the computed_field should appear in the response schema + user_schema = schema["components"]["schemas"]["User"] + assert "full_name" in user_schema["properties"] + assert user_schema["properties"]["full_name"]["type"] == "string" + assert user_schema["properties"]["full_name"].get("readOnly") is True + + +@pytest.mark.usefixtures("pydanticv2_only") +def test_openapi_schema_computed_field_not_in_request_body(): + # GIVEN a model with a computed_field used as both request and response + class Item(BaseModel): + price: float + quantity: int + + @computed_field + @property + def total(self) -> float: + return self.price * self.quantity + + # GIVEN APIGatewayRestResolver with handlers using the model + app = APIGatewayRestResolver(enable_validation=True) + + @app.post("/items") + def create_item(item: Item) -> Item: + return item + + # WHEN we get the schema + schema = json.loads(app.get_openapi_json_schema()) + + # THEN the request body schema should NOT include computed_field + request_body = schema["paths"]["/items"]["post"]["requestBody"] + request_ref = request_body["content"]["application/json"]["schema"]["$ref"] + request_schema_name = request_ref.split("/")[-1] + + # THEN the response schema SHOULD include computed_field + response_ref = schema["paths"]["/items"]["post"]["responses"]["200"]["content"]["application/json"]["schema"][ + "$ref" + ] + response_schema_name = response_ref.split("/")[-1] + + # When input/output schemas are separate, we expect different schema names + # When they share a schema, computed_field should be present + if request_schema_name == response_schema_name: + # Shared schema - computed_field should be present (serialization mode wins) + item_schema = schema["components"]["schemas"][response_schema_name] + assert "total" in item_schema["properties"] + else: + # Separate schemas + input_schema = schema["components"]["schemas"][request_schema_name] + output_schema = schema["components"]["schemas"][response_schema_name] + assert "total" not in input_schema["properties"] + assert "total" in output_schema["properties"] From f83e141fa16396098f564672b2074b97d81883bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 14:49:15 +0100 Subject: [PATCH 66/84] chore(deps): update requests requirement from >=2.32.0 to >=2.33.1 in /examples/event_handler_graphql/src (#8189) chore(deps): update requests requirement Updates the requirements on [requests](https://github.com/psf/requests) to permit the latest version. - [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.32.0...v2.33.1) --- updated-dependencies: - dependency-name: requests dependency-version: 2.33.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/event_handler_graphql/src/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/event_handler_graphql/src/requirements.txt b/examples/event_handler_graphql/src/requirements.txt index 785ab54fc57..67f59e04d75 100644 --- a/examples/event_handler_graphql/src/requirements.txt +++ b/examples/event_handler_graphql/src/requirements.txt @@ -1,2 +1,2 @@ aws-lambda-powertools[tracer] -requests>=2.32.0 +requests>=2.33.1 From 5b8ba36e2ccfa7b37f503a0f10b9c5c2a4965ad0 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 4 May 2026 10:20:02 +0100 Subject: [PATCH 67/84] chore: update aws-encryption-sdk allowed versions (#8191) * chore: update aws-encryption-sdk allowed versions * chore: update aws-encryption-sdk allowed versions --- poetry.lock | 24 +++++++++---------- pyproject.toml | 2 +- .../function_1024/requirements.txt | 2 +- .../function_128/requirements.txt | 2 +- .../function_1769/requirements.txt | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index 227b6768dab..14db31a31be 100644 --- a/poetry.lock +++ b/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.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" @@ -262,15 +262,15 @@ typeguard = "2.13.3" [[package]] name = "aws-encryption-sdk" -version = "4.0.4" +version = "4.0.5" 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.4-py2.py3-none-any.whl", hash = "sha256:29e7ec00aa6f27bb6e4f4f17e51abf3fc58a7fc17882c0e375ee09c97ab84585"}, - {file = "aws_encryption_sdk-4.0.4.tar.gz", hash = "sha256:60b69f19f72fa568d7e69e9d3966fe10e541c9c83b1af5a83724f8a1fe184d43"}, + {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"}, ] [package.dependencies] @@ -325,7 +325,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"}, @@ -1837,7 +1837,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"}, @@ -3418,7 +3418,7 @@ files = [ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3560,7 +3560,7 @@ files = [ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] -markers = {main = "extra == \"all\" or extra == \"parser\""} +markers = {main = "extra == \"parser\" or extra == \"all\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -4815,7 +4815,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" @@ -5133,7 +5133,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" @@ -5189,4 +5189,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "9522eab0cc391eb22adcd6241427c14efac426740e443c47806b93d96d42fb0d" +content-hash = "7b5ee713f6904edb56fda6f83eaf2a0e34373f685e19a94d76b985dad427c81b" diff --git a/pyproject.toml b/pyproject.toml index ed343e04f8f..5d7d5294cd9 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,<8.0", optional = true } valkey-glide = { version = ">=1.3.5,<3.0", optional = true } -aws-encryption-sdk = { version = ">=3.1.1,<5.0.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 } 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 1c37b95e202..397c11ba436 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.1.1 +aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4 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 1c37b95e202..397c11ba436 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.1.1 +aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4 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 1c37b95e202..397c11ba436 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.1.1 +aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4 From 53678cf534ac69b2121ef3f040d8012e49cc470f Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 4 May 2026 10:22:29 +0100 Subject: [PATCH 68/84] fix(event_handler): fix ALB resolver returns when response body is None (#8194) * fix(event_handler): handle ALB response when it's None * fix(event_handler): handle ALB response when it's None --- .../event_handler/api_gateway.py | 11 +----- .../middlewares/openapi_validation.py | 6 +++- .../test_openapi_validation_middleware.py | 36 +++++++++++++++++++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index d5d7751f043..a323cf67d56 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -3343,22 +3343,13 @@ def _get_base_path(self) -> str: # ALB doesn't have a stage variable, so we just return an empty string return "" - # BedrockResponse is not used here but adding the same signature to keep strong typing @override def _to_response(self, result: dict | tuple | Response | BedrockResponse) -> Response | BedrockResponse: """Convert the route's result to a Response ALB requires a non-null body otherwise it converts as HTTP 5xx - - 3 main result types are supported: - - - Dict[str, Any]: Rest api response with just the Dict to json stringify and content-type is set to - application/json - - Tuple[dict, int]: Same dict handling as above but with the option of including a status code - - Response: returned as is, and allows for more flexibility """ - - # NOTE: Minor override for early return on Response with null body for ALB + # ALB doesn't support null body - convert before building the final response if isinstance(result, Response) and result.body is None: logger.debug("ALB doesn't allow None responses; converting to empty string") result.body = "" diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py index 05306b5ca8b..470a19e6c54 100644 --- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py @@ -296,9 +296,13 @@ def _handle_response(self, *, route: Route, response: Response): # JSON serialize the body without validation response.body = jsonable_encoder(response.body, custom_serializer=self._validation_serializer) else: + # ALB resolver converts None body to "" to prevent ALB 5xx errors, + # but the validation should still see it as None. + response_content = None if response.body == "" and field.type_ in (None, type(None)) else response.body + response.body = self._serialize_response_with_validation( field=field, - response_content=response.body, + response_content=response_content, has_route_custom_response_validation=route.custom_response_validation_http_code is not None, ) 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 e7199adc9c5..0da092f8aea 100644 --- a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py @@ -4227,3 +4227,39 @@ def handler(session_id: Annotated[str, Cookie()]): assert result["statusCode"] == 200 body = json.loads(result["body"]) assert body["session_id"] == "lattice_v1_abc" + + +def test_alb_response_none_body_with_validation(gw_event_alb): + # GIVEN an ALBResolver with validation enabled + app = ALBResolver(enable_validation=True) + + gw_event_alb["path"] = "/no-content" + gw_event_alb["httpMethod"] = "DELETE" + + # WHEN a handler returns Response with body=None and return type is None + @app.delete("/no-content") + def handler() -> None: + return Response(status_code=204, body=None) + + # THEN the response should be 204 with empty body (not 422 validation error) + result = app(gw_event_alb, {}) + assert result["statusCode"] == 204 + assert result["body"] == "" + + +def test_alb_response_typed_none_body_with_validation(gw_event_alb): + # GIVEN an ALBResolver with validation enabled + app = ALBResolver(enable_validation=True) + + gw_event_alb["path"] = "/no-content" + gw_event_alb["httpMethod"] = "DELETE" + + # WHEN a handler returns Response[None] with body=None + @app.delete("/no-content") + def handler() -> Response[None]: + return Response(status_code=204, body=None) + + # THEN the response should be 204 with empty body (not 422 validation error) + result = app(gw_event_alb, {}) + assert result["statusCode"] == 204 + assert result["body"] == "" From f4644f7d88b31c7a8f2aa1b0615d11ad0d45ff67 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Mon, 4 May 2026 10:38:56 +0100 Subject: [PATCH 69/84] fix(event_handler): prevent deadlock when async middleware raises before calling next() (#8196) * fix(event_handler): avoid deadlock in async resolver * fix(event_handler): avoid deadlock in async resolver --- .../event_handler/middlewares/async_utils.py | 9 +- .../test_async_middleware_frame.py | 221 ++++-------------- 2 files changed, 56 insertions(+), 174 deletions(-) diff --git a/aws_lambda_powertools/event_handler/middlewares/async_utils.py b/aws_lambda_powertools/event_handler/middlewares/async_utils.py index d372790fbcf..4f375bc9b0b 100644 --- a/aws_lambda_powertools/event_handler/middlewares/async_utils.py +++ b/aws_lambda_powertools/event_handler/middlewares/async_utils.py @@ -86,13 +86,20 @@ def run_middleware() -> None: middleware_result_holder.append(result) except Exception as e: middleware_error_holder.append(e) + finally: + middleware_called_next.set() thread = threading.Thread(target=run_middleware, daemon=True) thread.start() - # Wait for the middleware to call next() + # Wait for the middleware to call next() or raise await middleware_called_next.wait() + # If middleware raised before calling next, propagate immediately + if not next_app_holder: + thread.join() + raise middleware_error_holder[0] + # Resolve the async next_handler on the event-loop real_response = await next_handler(next_app_holder[0]) real_response_holder.append(real_response) diff --git a/tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py b/tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py index b833ee19fae..6154820454d 100644 --- a/tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py +++ b/tests/functional/event_handler/required_dependencies/test_async_middleware_frame.py @@ -1,5 +1,7 @@ import asyncio +import pytest + from aws_lambda_powertools.event_handler import content_types from aws_lambda_powertools.event_handler.api_gateway import ( ApiGatewayResolver, @@ -7,7 +9,7 @@ Response, ) from aws_lambda_powertools.event_handler.middlewares import NextMiddleware -from aws_lambda_powertools.event_handler.middlewares.async_utils import AsyncMiddlewareFrame +from aws_lambda_powertools.event_handler.middlewares.async_utils import AsyncMiddlewareFrame, wrap_middleware_async from tests.functional.utils import load_event API_REST_EVENT = load_event("apiGatewayProxyEvent.json") @@ -20,195 +22,68 @@ def _make_app() -> ApiGatewayResolver: return app -class TestAsyncMiddlewareFrameWithAsyncMiddleware: - def test_async_middleware_is_awaited(self): - # GIVEN an async middleware and an async next handler - app = _make_app() - - async def my_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): - app.append_context(middleware_called=True) - return await next_middleware(app) - - async def next_handler(app: ApiGatewayResolver): - await asyncio.sleep(0) - return Response(200, content_types.TEXT_HTML, "from handler") - - frame = AsyncMiddlewareFrame(current_middleware=my_middleware, next_middleware=next_handler) - - # WHEN calling the frame - result = asyncio.run(frame(app)) - - # THEN the async middleware is invoked and the chain proceeds - assert result.status_code == 200 - assert result.body == "from handler" - assert app.context.get("middleware_called") is True - - def test_async_middleware_can_short_circuit(self): - # GIVEN an async middleware that returns early without calling next - app = _make_app() - - async def blocking_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): - await asyncio.sleep(0) - return Response(403, content_types.TEXT_PLAIN, "forbidden") - - async def next_handler(app: ApiGatewayResolver): - await asyncio.sleep(0) - return Response(200, content_types.TEXT_HTML, "should not reach") - - frame = AsyncMiddlewareFrame(current_middleware=blocking_middleware, next_middleware=next_handler) - - # WHEN calling the frame - result = asyncio.run(frame(app)) - - # THEN the middleware short-circuits the chain - assert result.status_code == 403 - assert result.body == "forbidden" - - def test_multiple_async_middlewares_chained(self): - # GIVEN two async middlewares chained together - app = _make_app() - - async def first_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): - app.append_context(first=True) - return await next_middleware(app) - - async def second_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): - app.append_context(second=True) - return await next_middleware(app) - - async def final_handler(app: ApiGatewayResolver): - await asyncio.sleep(0) - return Response(200, content_types.TEXT_HTML, "done") - - # WHEN building a chain: first -> second -> handler - inner_frame = AsyncMiddlewareFrame(current_middleware=second_middleware, next_middleware=final_handler) - outer_frame = AsyncMiddlewareFrame(current_middleware=first_middleware, next_middleware=inner_frame) - - result = asyncio.run(outer_frame(app)) - - # THEN both middlewares run in order - assert result.status_code == 200 - assert app.context.get("first") is True - assert app.context.get("second") is True +def test_sync_middleware_raising_before_next_does_not_deadlock(): + # GIVEN a sync middleware that raises before calling next() + # This previously caused a deadlock because middleware_called_next was never set + app = _make_app() + class AuthError(Exception): + pass -class TestAsyncMiddlewareFrameWithSyncMiddleware: - def test_sync_middleware_is_bridged(self): - # GIVEN a sync middleware and an async next handler - app = _make_app() + def failing_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + raise AuthError("denied") - def sync_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): - app.append_context(sync_called=True) - return next_middleware(app) + async def next_handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "should not reach") - async def next_handler(app: ApiGatewayResolver): - await asyncio.sleep(0) - return Response(200, content_types.TEXT_HTML, "async handler") + frame = AsyncMiddlewareFrame(current_middleware=failing_middleware, next_middleware=next_handler) - frame = AsyncMiddlewareFrame(current_middleware=sync_middleware, next_middleware=next_handler) - - # WHEN calling the frame - result = asyncio.run(frame(app)) - - # THEN the sync middleware is bridged via wrap_middleware_async - assert result.status_code == 200 - assert result.body == "async handler" - assert app.context.get("sync_called") is True - - def test_sync_middleware_can_short_circuit(self): - # GIVEN a sync middleware that returns early - app = _make_app() - - def sync_blocking(app: ApiGatewayResolver, next_middleware: NextMiddleware): - return Response(401, content_types.TEXT_PLAIN, "unauthorized") - - async def next_handler(app: ApiGatewayResolver): - await asyncio.sleep(0) - return Response(200, content_types.TEXT_HTML, "should not reach") - - frame = AsyncMiddlewareFrame(current_middleware=sync_blocking, next_middleware=next_handler) - - # WHEN calling the frame - result = asyncio.run(frame(app)) - - # THEN the sync middleware short-circuits - assert result.status_code == 401 - assert result.body == "unauthorized" - - -class TestAsyncMiddlewareFrameMixedChain: - def test_sync_then_async_middleware(self): - # GIVEN a chain with sync middleware followed by async middleware - app = _make_app() - - def sync_mw(app: ApiGatewayResolver, next_middleware: NextMiddleware): - app.append_context(sync_ran=True) - return next_middleware(app) - - async def async_mw(app: ApiGatewayResolver, next_middleware: NextMiddleware): - app.append_context(async_ran=True) - return await next_middleware(app) - - async def handler(app: ApiGatewayResolver): - await asyncio.sleep(0) - return Response(200, content_types.TEXT_HTML, "mixed chain") - - inner = AsyncMiddlewareFrame(current_middleware=async_mw, next_middleware=handler) - outer = AsyncMiddlewareFrame(current_middleware=sync_mw, next_middleware=inner) - - # WHEN calling the chain - result = asyncio.run(outer(app)) - - # THEN both middlewares execute in order - assert result.status_code == 200 - assert app.context.get("sync_ran") is True - assert app.context.get("async_ran") is True + # WHEN calling the frame + # THEN the exception propagates without deadlocking + with pytest.raises(AuthError, match="denied"): + asyncio.run(frame(app)) -class TestAsyncMiddlewareFrameProperties: - def test_name_property(self): - # GIVEN a middleware with a known name - def my_named_middleware(app, next_mw): - return next_mw(app) +def test_wrap_middleware_async_sync_raising_before_next_does_not_deadlock(): + # GIVEN a sync middleware that raises before calling next(), using wrap_middleware_async + # This exercises _run_sync_middleware_in_thread directly + app = _make_app() - def next_handler(app): - return Response(200, content_types.TEXT_HTML, "ok") + class AuthError(Exception): + pass - frame = AsyncMiddlewareFrame(current_middleware=my_named_middleware, next_middleware=next_handler) + def failing_middleware(app, next_middleware): + raise AuthError("denied") - # THEN __name__ returns the current middleware name - assert frame.__name__ == "my_named_middleware" + async def next_handler(app): + return Response(200, content_types.TEXT_HTML, "should not reach") - def test_str_representation(self): - # GIVEN a frame with named middleware and next handler - def auth_middleware(app, next_mw): - return next_mw(app) + wrapped = wrap_middleware_async(failing_middleware, next_handler) - def logging_middleware(app): - return Response(200, content_types.TEXT_HTML, "ok") + # WHEN calling the wrapped middleware + # THEN the exception propagates without deadlocking + with pytest.raises(AuthError, match="denied"): + asyncio.run(wrapped(app)) - frame = AsyncMiddlewareFrame(current_middleware=auth_middleware, next_middleware=logging_middleware) - # THEN str() shows the call chain - assert str(frame) == "[auth_middleware] next call chain is auth_middleware -> logging_middleware" +def test_async_middleware_raising_before_next_propagates(): + # GIVEN an async middleware that raises before calling next() + app = _make_app() - def test_pushes_processed_stack_frame(self): - # GIVEN a frame - app = _make_app() + class ValidationError(Exception): + pass - async def my_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): - return await next_middleware(app) + async def failing_middleware(app: ApiGatewayResolver, next_middleware: NextMiddleware): + raise ValidationError("invalid request") - async def handler(app: ApiGatewayResolver): - await asyncio.sleep(0) - return Response(200, content_types.TEXT_HTML, "ok") + async def next_handler(app: ApiGatewayResolver): + await asyncio.sleep(0) + return Response(200, content_types.TEXT_HTML, "should not reach") - frame = AsyncMiddlewareFrame(current_middleware=my_middleware, next_middleware=handler) - app._reset_processed_stack() + frame = AsyncMiddlewareFrame(current_middleware=failing_middleware, next_middleware=next_handler) - # WHEN calling the frame + # WHEN calling the frame + # THEN the exception propagates + with pytest.raises(ValidationError, match="invalid request"): asyncio.run(frame(app)) - - # THEN the processed stack frame is recorded for debugging - assert len(app.processed_stack_frames) > 0 - assert "my_middleware" in app.processed_stack_frames[0] From 2186d430fc20fb7fc54d7a8de9e4d45ee834243b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 11:12:32 +0100 Subject: [PATCH 70/84] chore(ci): bump version to 3.29.0 (#8197) 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 067def9eece..242e0b4ae14 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.28.0" +VERSION = "3.29.0" diff --git a/pyproject.toml b/pyproject.toml index 5d7d5294cd9..c6a990aa246 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "3.28.0" +version = "3.29.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 861db70559b1fcdf53fabb12671b6446ccf16f37 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 11:14:31 +0100 Subject: [PATCH 71/84] chore(ci): layer docs update (#8198) Co-authored-by: Powertools for AWS Lambda (Python) bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Leandro Damascena --- CHANGELOG.md | 43 ++- 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, 360 insertions(+), 319 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ef5c4b5674..f2dc360bea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,55 @@ # Unreleased + +## [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)) + +## Maintenance + +* version bump + + ## [v3.28.0] - 2026-04-14 ## Bug Fixes * **data_class:** merge querystring parameters in ALB/APIGW classes ([#8154](https://github.com/aws-powertools/powertools-lambda-python/issues/8154)) +* **event_handler:** read swagger files with UTF-8 encoding ([#8131](https://github.com/aws-powertools/powertools-lambda-python/issues/8131)) + +## Code Refactoring + +* **event_handler:** refactoring encoder file ([#8126](https://github.com/aws-powertools/powertools-lambda-python/issues/8126)) +* **event_handler:** refactoring proxy events ([#8125](https://github.com/aws-powertools/powertools-lambda-python/issues/8125)) +* **event_handler:** refactoring params to reduce code ([#8124](https://github.com/aws-powertools/powertools-lambda-python/issues/8124)) +* **event_handler:** extract OpenAPI schema generation from Route class ([#8098](https://github.com/aws-powertools/powertools-lambda-python/issues/8098)) +* **event_handlers:** remove unnecessary init methods ([#8127](https://github.com/aws-powertools/powertools-lambda-python/issues/8127)) + +## Documentation + +* adding new Lambda features ([#7917](https://github.com/aws-powertools/powertools-lambda-python/issues/7917)) +* add openapi docs ([#7939](https://github.com/aws-powertools/powertools-lambda-python/issues/7939)) + +## Features + +* **event_handler:** enrich request object ([#8153](https://github.com/aws-powertools/powertools-lambda-python/issues/8153)) +* **event_handler:** adding status_code OpenAPI field ([#8130](https://github.com/aws-powertools/powertools-lambda-python/issues/8130)) +* **event_handler:** add Dependency injection with Depends() ([#8128](https://github.com/aws-powertools/powertools-lambda-python/issues/8128)) ## Maintenance * version bump +* bump dependabot dependencies. ([#8152](https://github.com/aws-powertools/powertools-lambda-python/issues/8152)) +* **deps:** bump cryptography from 46.0.6 to 46.0.7 ([#8132](https://github.com/aws-powertools/powertools-lambda-python/issues/8132)) +* **deps-dev:** bump aws-cdk from 2.1117.0 to 2.1118.0 in the aws-cdk group ([#8142](https://github.com/aws-powertools/powertools-lambda-python/issues/8142)) +* **deps-dev:** bump types-python-dateutil from 2.9.0.20260305 to 2.9.0.20260402 ([#8114](https://github.com/aws-powertools/powertools-lambda-python/issues/8114)) +* **deps-dev:** bump aws-cdk from 2.1115.0 to 2.1117.0 in the aws-cdk group ([#8111](https://github.com/aws-powertools/powertools-lambda-python/issues/8111)) +* **deps-dev:** bump boto3-stubs from 1.42.74 to 1.42.84 ([#8115](https://github.com/aws-powertools/powertools-lambda-python/issues/8115)) +* **deps-dev:** bump types-protobuf from 6.32.1.20260221 to 7.34.1.20260403 ([#8117](https://github.com/aws-powertools/powertools-lambda-python/issues/8117)) +* **deps-dev:** bump testcontainers from 4.14.1 to 4.14.2 ([#8116](https://github.com/aws-powertools/powertools-lambda-python/issues/8116)) +* **deps-dev:** bump cfn-lint from 1.46.0 to 1.48.1 ([#8113](https://github.com/aws-powertools/powertools-lambda-python/issues/8113)) @@ -7626,7 +7666,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.28.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.29.0...HEAD +[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 [v3.26.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v3.25.0...v3.26.0 diff --git a/docs/includes/_layer_homepage_arm64.md b/docs/includes/_layer_homepage_arm64.md index eb5391393bf..e40a04078ec 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:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-arm64:32**{: .copyMe} | + | **`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} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-arm64:32**{: .copyMe} | + | **`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} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:32**{: .copyMe} | + | **`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} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:32**{: .copyMe} | + | **`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} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-arm64:32**{: .copyMe} | + | **`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} | diff --git a/docs/includes/_layer_homepage_x86.md b/docs/includes/_layer_homepage_x86.md index 8e88de48908..907788332f7 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:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python310-x86_64:32**{: .copyMe} | + | **`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} | === "Python 3.11" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python311-x86_64:32**{: .copyMe} | + | **`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} | === "Python 3.12" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:32**{: .copyMe} | + | **`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} | === "Python 3.13" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:32**{: .copyMe} | + | **`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} | === "Python 3.14" | Region | Layer ARN | | -------------------- | --------------------------------------------------------------------------------------------------------- | - | **`af-south-1`** | **arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-east-1`** | **arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-northeast-1`** | **arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-northeast-2`** | **arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-northeast-3`** | **arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-south-1`** | **arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-south-2`** | **arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-southeast-1`** | **arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-southeast-2`** | **arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-southeast-3`** | **arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-southeast-4`** | **arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-southeast-5`** | **arn:aws:lambda:ap-southeast-5:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ap-southeast-7`** | **arn:aws:lambda:ap-southeast-7:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ca-central-1`** | **arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`ca-west-1`** | **arn:aws:lambda:ca-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-central-1`** | **arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-central-2`** | **arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-north-1`** | **arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-south-1`** | **arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-south-2`** | **arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-west-1`** | **arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-west-2`** | **arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`eu-west-3`** | **arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`il-central-1`** | **arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`mx-central-1`** | **arn:aws:lambda:mx-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`sa-east-1`** | **arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`us-east-1`** | **arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`us-east-2`** | **arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`us-west-1`** | **arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | - | **`us-west-2`** | **arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV3-python314-x86_64:32**{: .copyMe} | + | **`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} | diff --git a/examples/build_recipes/cdk/basic/app.py b/examples/build_recipes/cdk/basic/app.py index d8509e7a1ce..6268d8e49c0 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:32", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33", ) # 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 b526e04cc2b..3c7a480adbe 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:32", + layer_version_arn="arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33", ) 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 37b9103eda3..8babe94f382 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:32 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33 - !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 c9aef4c6bcb..fc9803b5a8a 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:32 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33 - !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:32 + - arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-x86_64:33 - !Ref DependenciesLayer Events: SQSEvent: diff --git a/examples/homepage/install/arm64/amplify.txt b/examples/homepage/install/arm64/amplify.txt index 78dee0ac047..8aadd5ecbba 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:32 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 ❯ 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:32 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 ? 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 eb6685b800a..2b7d084a199 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:32", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33", ) aws_lambda.Function( self, diff --git a/examples/homepage/install/arm64/pulumi_arm64.py b/examples/homepage/install/arm64/pulumi_arm64.py index b7577b5509e..1659d2362ad 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:32", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/arm64/sam.yaml b/examples/homepage/install/arm64/sam.yaml index 73d023bfc33..8d77abd0e02 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:32 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 diff --git a/examples/homepage/install/arm64/serverless.yml b/examples/homepage/install/arm64/serverless.yml index e6f8f335f77..c3812016a42 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:32 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33 diff --git a/examples/homepage/install/arm64/terraform.tf b/examples/homepage/install/arm64/terraform.tf index aa986baa2ad..dc46db6df87 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:32"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-arm64:33"] 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 24d0108a4a8..9a1223e9280 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:32 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 ❯ 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:32 +? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 ? 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 cf774cba370..30d82a497dd 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:32", + layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33", ) 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 d9aeef246f9..1130c67b644 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:32", + ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33", ), ], tracing_config={"mode": "Active"}, diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml index ac3d7545b46..d6beb66ea52 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:32 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml index 23573959df0..56deaf1b0fa 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:32 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf index 8db1d6ae3ff..56e73fe45b6 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:32"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 2bb425009cb..092fb4166d3 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:32 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index 2369678e037..dc7d0258fee 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:32 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 Resources: CaptureLambdaHandlerExample: diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml index 6420c4331bf..d43669484f8 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:32 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 # 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 7ce2bc40715..465ac3e2507 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:32 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33 Resources: CaptureLambdaHandlerExample: From 4a5d8959c7a9cc4f2ea9c4f88e82c46fee53f2dd Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 5 May 2026 10:14:12 +0100 Subject: [PATCH 72/84] chore(deps): batch dependency updates (#8207) - release-drafter/release-drafter 7.2.0 -> 7.2.1 - aws-cdk 2.1119.0 -> 2.1120.0 - aws-cdk-lib 2.251.0 -> 2.252.0 - filelock 3.25.2 -> 3.29.0 - boto3-stubs 1.42.92 -> 1.43.3 - mypy-boto3-appconfigdata 1.42.3 -> 1.43.0 - ty 0.0.32 -> 0.0.34 (added parameters/** to ty exclusions) Co-authored-by: Claude Opus 4.6 --- .github/workflows/release-drafter.yml | 2 +- package-lock.json | 8 +- package.json | 2 +- poetry.lock | 1024 ++++++++++++------------- pyproject.toml | 3 +- 5 files changed, 520 insertions(+), 519 deletions(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index c6b23774277..60d41a2a0ca 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@5de93583980a40bd78603b6dfdcda5b4df377b32 # v7.2.0 + - uses: release-drafter/release-drafter@563bf132657a13ded0b01fcb723c5a58cdd824e2 # v7.2.1 diff --git a/package-lock.json b/package-lock.json index 19f3361ab9e..4ba9e2b2226 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.1119.0" + "aws-cdk": "^2.1120.0" } }, "node_modules/aws-cdk": { - "version": "2.1119.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1119.0.tgz", - "integrity": "sha512-XBxZEKH3BY4M1EX6x0qBkmOAj8viErjpww14iH6Z3z6nI0YzjZeJ05eEl7eJwzUgv7NTGagWBS9m/eDJW5+dAg==", + "version": "2.1120.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1120.0.tgz", + "integrity": "sha512-vDVa0IX0FhizARdY/GLSParFglKbdHCIhM8IDmynrAv9w8uLLljzWMeLUOhC1XpMErDZ/npYEihAOjfKxTaMIw==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 25ee230447c..18d4fae537a 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.1119.0" + "aws-cdk": "^2.1120.0" } } diff --git a/poetry.lock b/poetry.lock index 14db31a31be..c9d611fad2d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -241,14 +241,14 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.251.0" +version = "2.252.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.251.0-py3-none-any.whl", hash = "sha256:a684f3461d096443ac688adbf559abe1af2d50dd5c8e0fa7dbf4a5f361702db8"}, - {file = "aws_cdk_lib-2.251.0.tar.gz", hash = "sha256:ed69e7ea6896c62ac2ce01857083601baf541d5d875370bee6d213d641e8921e"}, + {file = "aws_cdk_lib-2.252.0-py3-none-any.whl", hash = "sha256:c96d02582d344ee81ea2ef8a5e22b6e680789973804720ec9f0e95a050257db1"}, + {file = "aws_cdk_lib-2.252.0.tar.gz", hash = "sha256:2498d771ab141599c48494bd2564ee9a4fbaade54befa9356811e9454616d0a0"}, ] [package.dependencies] @@ -256,7 +256,7 @@ files = [ "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.127.0,<2.0.0" +jsii = ">=1.128.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" @@ -453,460 +453,460 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "boto3-stubs" -version = "1.42.92" -description = "Type annotations for boto3 1.42.92 generated with mypy-boto3-builder 8.12.0" +version = "1.43.3" +description = "Type annotations for boto3 1.43.3 generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "boto3_stubs-1.42.92-py3-none-any.whl", hash = "sha256:b3994e60f0133b2dd3d9a88ceaeef48fa6367d9a9429426e919575768a1ad9c6"}, - {file = "boto3_stubs-1.42.92.tar.gz", hash = "sha256:4bc934069c5e8c7b3cdd2442569dae14e8272fe207d445bd38aa578b8463638f"}, + {file = "boto3_stubs-1.43.3-py3-none-any.whl", hash = "sha256:dd43fb68fe1d6db450588609a96013a9baf86d1cfc45bbbee7fd97bac971a3c0"}, + {file = "boto3_stubs-1.43.3.tar.gz", hash = "sha256:1c17fb4003c8d3ac324385f1d7a366721436eab3b6dc7838239dea53137ba9de"}, ] [package.dependencies] botocore-stubs = "*" -mypy-boto3-appconfig = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"appconfig\""} -mypy-boto3-appconfigdata = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"appconfigdata\""} -mypy-boto3-cloudformation = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"cloudformation\""} -mypy-boto3-cloudwatch = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"cloudwatch\""} -mypy-boto3-dynamodb = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"dynamodb\""} -mypy-boto3-lambda = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"lambda\""} -mypy-boto3-logs = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"logs\""} -mypy-boto3-s3 = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"s3\""} -mypy-boto3-secretsmanager = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"secretsmanager\""} -mypy-boto3-ssm = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"ssm\""} -mypy-boto3-xray = {version = ">=1.42.0,<1.43.0", optional = true, markers = "extra == \"xray\""} +mypy-boto3-appconfig = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"appconfig\""} +mypy-boto3-appconfigdata = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"appconfigdata\""} +mypy-boto3-cloudformation = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"cloudformation\""} +mypy-boto3-cloudwatch = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"cloudwatch\""} +mypy-boto3-dynamodb = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"dynamodb\""} +mypy-boto3-lambda = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"lambda\""} +mypy-boto3-logs = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"logs\""} +mypy-boto3-s3 = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"s3\""} +mypy-boto3-secretsmanager = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"secretsmanager\""} +mypy-boto3-ssm = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"ssm\""} +mypy-boto3-xray = {version = ">=1.43.0,<1.44.0", optional = true, markers = "extra == \"xray\""} types-s3transfer = "*" typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} [package.extras] -accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.42.0,<1.43.0)"] -account = ["mypy-boto3-account (>=1.42.0,<1.43.0)"] -acm = ["mypy-boto3-acm (>=1.42.0,<1.43.0)"] -acm-pca = ["mypy-boto3-acm-pca (>=1.42.0,<1.43.0)"] -aiops = ["mypy-boto3-aiops (>=1.42.0,<1.43.0)"] -all = ["mypy-boto3-accessanalyzer (>=1.42.0,<1.43.0)", "mypy-boto3-account (>=1.42.0,<1.43.0)", "mypy-boto3-acm (>=1.42.0,<1.43.0)", "mypy-boto3-acm-pca (>=1.42.0,<1.43.0)", "mypy-boto3-aiops (>=1.42.0,<1.43.0)", "mypy-boto3-amp (>=1.42.0,<1.43.0)", "mypy-boto3-amplify (>=1.42.0,<1.43.0)", "mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)", "mypy-boto3-amplifyuibuilder (>=1.42.0,<1.43.0)", "mypy-boto3-apigateway (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewaymanagementapi (>=1.42.0,<1.43.0)", "mypy-boto3-apigatewayv2 (>=1.42.0,<1.43.0)", "mypy-boto3-appconfig (>=1.42.0,<1.43.0)", "mypy-boto3-appconfigdata (>=1.42.0,<1.43.0)", "mypy-boto3-appfabric (>=1.42.0,<1.43.0)", "mypy-boto3-appflow (>=1.42.0,<1.43.0)", "mypy-boto3-appintegrations (>=1.42.0,<1.43.0)", "mypy-boto3-application-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-application-insights (>=1.42.0,<1.43.0)", "mypy-boto3-application-signals (>=1.42.0,<1.43.0)", "mypy-boto3-applicationcostprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-appmesh (>=1.42.0,<1.43.0)", "mypy-boto3-apprunner (>=1.42.0,<1.43.0)", "mypy-boto3-appstream (>=1.42.0,<1.43.0)", "mypy-boto3-appsync (>=1.42.0,<1.43.0)", "mypy-boto3-arc-region-switch (>=1.42.0,<1.43.0)", "mypy-boto3-arc-zonal-shift (>=1.42.0,<1.43.0)", "mypy-boto3-artifact (>=1.42.0,<1.43.0)", "mypy-boto3-athena (>=1.42.0,<1.43.0)", "mypy-boto3-auditmanager (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling (>=1.42.0,<1.43.0)", "mypy-boto3-autoscaling-plans (>=1.42.0,<1.43.0)", "mypy-boto3-b2bi (>=1.42.0,<1.43.0)", "mypy-boto3-backup (>=1.42.0,<1.43.0)", "mypy-boto3-backup-gateway (>=1.42.0,<1.43.0)", "mypy-boto3-backupsearch (>=1.42.0,<1.43.0)", "mypy-boto3-batch (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-dashboards (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-data-exports (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-pricing-calculator (>=1.42.0,<1.43.0)", "mypy-boto3-bcm-recommended-actions (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agent-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-agentcore-control (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-billing (>=1.42.0,<1.43.0)", "mypy-boto3-billingconductor (>=1.42.0,<1.43.0)", "mypy-boto3-braket (>=1.42.0,<1.43.0)", "mypy-boto3-budgets (>=1.42.0,<1.43.0)", "mypy-boto3-ce (>=1.42.0,<1.43.0)", "mypy-boto3-chatbot (>=1.42.0,<1.43.0)", "mypy-boto3-chime (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-identity (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-meetings (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-messaging (>=1.42.0,<1.43.0)", "mypy-boto3-chime-sdk-voice (>=1.42.0,<1.43.0)", "mypy-boto3-cleanrooms (>=1.42.0,<1.43.0)", "mypy-boto3-cleanroomsml (>=1.42.0,<1.43.0)", "mypy-boto3-cloud9 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudcontrol (>=1.42.0,<1.43.0)", "mypy-boto3-clouddirectory (>=1.42.0,<1.43.0)", "mypy-boto3-cloudformation (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront (>=1.42.0,<1.43.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsm (>=1.42.0,<1.43.0)", "mypy-boto3-cloudhsmv2 (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearch (>=1.42.0,<1.43.0)", "mypy-boto3-cloudsearchdomain (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail (>=1.42.0,<1.43.0)", "mypy-boto3-cloudtrail-data (>=1.42.0,<1.43.0)", "mypy-boto3-cloudwatch (>=1.42.0,<1.43.0)", "mypy-boto3-codeartifact (>=1.42.0,<1.43.0)", "mypy-boto3-codebuild (>=1.42.0,<1.43.0)", "mypy-boto3-codecatalyst (>=1.42.0,<1.43.0)", "mypy-boto3-codecommit (>=1.42.0,<1.43.0)", "mypy-boto3-codeconnections (>=1.42.0,<1.43.0)", "mypy-boto3-codedeploy (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-reviewer (>=1.42.0,<1.43.0)", "mypy-boto3-codeguru-security (>=1.42.0,<1.43.0)", "mypy-boto3-codeguruprofiler (>=1.42.0,<1.43.0)", "mypy-boto3-codepipeline (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-connections (>=1.42.0,<1.43.0)", "mypy-boto3-codestar-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-identity (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-idp (>=1.42.0,<1.43.0)", "mypy-boto3-cognito-sync (>=1.42.0,<1.43.0)", "mypy-boto3-comprehend (>=1.42.0,<1.43.0)", "mypy-boto3-comprehendmedical (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer (>=1.42.0,<1.43.0)", "mypy-boto3-compute-optimizer-automation (>=1.42.0,<1.43.0)", "mypy-boto3-config (>=1.42.0,<1.43.0)", "mypy-boto3-connect (>=1.42.0,<1.43.0)", "mypy-boto3-connect-contact-lens (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaigns (>=1.42.0,<1.43.0)", "mypy-boto3-connectcampaignsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-connectcases (>=1.42.0,<1.43.0)", "mypy-boto3-connecthealth (>=1.42.0,<1.43.0)", "mypy-boto3-connectparticipant (>=1.42.0,<1.43.0)", "mypy-boto3-controlcatalog (>=1.42.0,<1.43.0)", "mypy-boto3-controltower (>=1.42.0,<1.43.0)", "mypy-boto3-cost-optimization-hub (>=1.42.0,<1.43.0)", "mypy-boto3-cur (>=1.42.0,<1.43.0)", "mypy-boto3-customer-profiles (>=1.42.0,<1.43.0)", "mypy-boto3-databrew (>=1.42.0,<1.43.0)", "mypy-boto3-dataexchange (>=1.42.0,<1.43.0)", "mypy-boto3-datapipeline (>=1.42.0,<1.43.0)", "mypy-boto3-datasync (>=1.42.0,<1.43.0)", "mypy-boto3-datazone (>=1.42.0,<1.43.0)", "mypy-boto3-dax (>=1.42.0,<1.43.0)", "mypy-boto3-deadline (>=1.42.0,<1.43.0)", "mypy-boto3-detective (>=1.42.0,<1.43.0)", "mypy-boto3-devicefarm (>=1.42.0,<1.43.0)", "mypy-boto3-devops-agent (>=1.42.0,<1.43.0)", "mypy-boto3-devops-guru (>=1.42.0,<1.43.0)", "mypy-boto3-directconnect (>=1.42.0,<1.43.0)", "mypy-boto3-discovery (>=1.42.0,<1.43.0)", "mypy-boto3-dlm (>=1.42.0,<1.43.0)", "mypy-boto3-dms (>=1.42.0,<1.43.0)", "mypy-boto3-docdb (>=1.42.0,<1.43.0)", "mypy-boto3-docdb-elastic (>=1.42.0,<1.43.0)", "mypy-boto3-drs (>=1.42.0,<1.43.0)", "mypy-boto3-ds (>=1.42.0,<1.43.0)", "mypy-boto3-ds-data (>=1.42.0,<1.43.0)", "mypy-boto3-dsql (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodb (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodbstreams (>=1.42.0,<1.43.0)", "mypy-boto3-ebs (>=1.42.0,<1.43.0)", "mypy-boto3-ec2 (>=1.42.0,<1.43.0)", "mypy-boto3-ec2-instance-connect (>=1.42.0,<1.43.0)", "mypy-boto3-ecr (>=1.42.0,<1.43.0)", "mypy-boto3-ecr-public (>=1.42.0,<1.43.0)", "mypy-boto3-ecs (>=1.42.0,<1.43.0)", "mypy-boto3-efs (>=1.42.0,<1.43.0)", "mypy-boto3-eks (>=1.42.0,<1.43.0)", "mypy-boto3-eks-auth (>=1.42.0,<1.43.0)", "mypy-boto3-elasticache (>=1.42.0,<1.43.0)", "mypy-boto3-elasticbeanstalk (>=1.42.0,<1.43.0)", "mypy-boto3-elb (>=1.42.0,<1.43.0)", "mypy-boto3-elbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-elementalinference (>=1.42.0,<1.43.0)", "mypy-boto3-emr (>=1.42.0,<1.43.0)", "mypy-boto3-emr-containers (>=1.42.0,<1.43.0)", "mypy-boto3-emr-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-entityresolution (>=1.42.0,<1.43.0)", "mypy-boto3-es (>=1.42.0,<1.43.0)", "mypy-boto3-events (>=1.42.0,<1.43.0)", "mypy-boto3-evs (>=1.42.0,<1.43.0)", "mypy-boto3-finspace (>=1.42.0,<1.43.0)", "mypy-boto3-finspace-data (>=1.42.0,<1.43.0)", "mypy-boto3-firehose (>=1.42.0,<1.43.0)", "mypy-boto3-fis (>=1.42.0,<1.43.0)", "mypy-boto3-fms (>=1.42.0,<1.43.0)", "mypy-boto3-forecast (>=1.42.0,<1.43.0)", "mypy-boto3-forecastquery (>=1.42.0,<1.43.0)", "mypy-boto3-frauddetector (>=1.42.0,<1.43.0)", "mypy-boto3-freetier (>=1.42.0,<1.43.0)", "mypy-boto3-fsx (>=1.42.0,<1.43.0)", "mypy-boto3-gamelift (>=1.42.0,<1.43.0)", "mypy-boto3-gameliftstreams (>=1.42.0,<1.43.0)", "mypy-boto3-geo-maps (>=1.42.0,<1.43.0)", "mypy-boto3-geo-places (>=1.42.0,<1.43.0)", "mypy-boto3-geo-routes (>=1.42.0,<1.43.0)", "mypy-boto3-glacier (>=1.42.0,<1.43.0)", "mypy-boto3-globalaccelerator (>=1.42.0,<1.43.0)", "mypy-boto3-glue (>=1.42.0,<1.43.0)", "mypy-boto3-grafana (>=1.42.0,<1.43.0)", "mypy-boto3-greengrass (>=1.42.0,<1.43.0)", "mypy-boto3-greengrassv2 (>=1.42.0,<1.43.0)", "mypy-boto3-groundstation (>=1.42.0,<1.43.0)", "mypy-boto3-guardduty (>=1.42.0,<1.43.0)", "mypy-boto3-health (>=1.42.0,<1.43.0)", "mypy-boto3-healthlake (>=1.42.0,<1.43.0)", "mypy-boto3-iam (>=1.42.0,<1.43.0)", "mypy-boto3-identitystore (>=1.42.0,<1.43.0)", "mypy-boto3-imagebuilder (>=1.42.0,<1.43.0)", "mypy-boto3-importexport (>=1.42.0,<1.43.0)", "mypy-boto3-inspector (>=1.42.0,<1.43.0)", "mypy-boto3-inspector-scan (>=1.42.0,<1.43.0)", "mypy-boto3-inspector2 (>=1.42.0,<1.43.0)", "mypy-boto3-interconnect (>=1.42.0,<1.43.0)", "mypy-boto3-internetmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-invoicing (>=1.42.0,<1.43.0)", "mypy-boto3-iot (>=1.42.0,<1.43.0)", "mypy-boto3-iot-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-jobs-data (>=1.42.0,<1.43.0)", "mypy-boto3-iot-managed-integrations (>=1.42.0,<1.43.0)", "mypy-boto3-iotdeviceadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents (>=1.42.0,<1.43.0)", "mypy-boto3-iotevents-data (>=1.42.0,<1.43.0)", "mypy-boto3-iotfleetwise (>=1.42.0,<1.43.0)", "mypy-boto3-iotsecuretunneling (>=1.42.0,<1.43.0)", "mypy-boto3-iotsitewise (>=1.42.0,<1.43.0)", "mypy-boto3-iotthingsgraph (>=1.42.0,<1.43.0)", "mypy-boto3-iottwinmaker (>=1.42.0,<1.43.0)", "mypy-boto3-iotwireless (>=1.42.0,<1.43.0)", "mypy-boto3-ivs (>=1.42.0,<1.43.0)", "mypy-boto3-ivs-realtime (>=1.42.0,<1.43.0)", "mypy-boto3-ivschat (>=1.42.0,<1.43.0)", "mypy-boto3-kafka (>=1.42.0,<1.43.0)", "mypy-boto3-kafkaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-kendra (>=1.42.0,<1.43.0)", "mypy-boto3-kendra-ranking (>=1.42.0,<1.43.0)", "mypy-boto3-keyspaces (>=1.42.0,<1.43.0)", "mypy-boto3-keyspacesstreams (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-archived-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-media (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-signaling (>=1.42.0,<1.43.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.42.0,<1.43.0)", "mypy-boto3-kinesisvideo (>=1.42.0,<1.43.0)", "mypy-boto3-kms (>=1.42.0,<1.43.0)", "mypy-boto3-lakeformation (>=1.42.0,<1.43.0)", "mypy-boto3-lambda (>=1.42.0,<1.43.0)", "mypy-boto3-launch-wizard (>=1.42.0,<1.43.0)", "mypy-boto3-lex-models (>=1.42.0,<1.43.0)", "mypy-boto3-lex-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-models (>=1.42.0,<1.43.0)", "mypy-boto3-lexv2-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.42.0,<1.43.0)", "mypy-boto3-lightsail (>=1.42.0,<1.43.0)", "mypy-boto3-location (>=1.42.0,<1.43.0)", "mypy-boto3-logs (>=1.42.0,<1.43.0)", "mypy-boto3-lookoutequipment (>=1.42.0,<1.43.0)", "mypy-boto3-m2 (>=1.42.0,<1.43.0)", "mypy-boto3-machinelearning (>=1.42.0,<1.43.0)", "mypy-boto3-macie2 (>=1.42.0,<1.43.0)", "mypy-boto3-mailmanager (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain (>=1.42.0,<1.43.0)", "mypy-boto3-managedblockchain-query (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-agreement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-catalog (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-deployment (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-discovery (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-entitlement (>=1.42.0,<1.43.0)", "mypy-boto3-marketplace-reporting (>=1.42.0,<1.43.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconnect (>=1.42.0,<1.43.0)", "mypy-boto3-mediaconvert (>=1.42.0,<1.43.0)", "mypy-boto3-medialive (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackage-vod (>=1.42.0,<1.43.0)", "mypy-boto3-mediapackagev2 (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore (>=1.42.0,<1.43.0)", "mypy-boto3-mediastore-data (>=1.42.0,<1.43.0)", "mypy-boto3-mediatailor (>=1.42.0,<1.43.0)", "mypy-boto3-medical-imaging (>=1.42.0,<1.43.0)", "mypy-boto3-memorydb (>=1.42.0,<1.43.0)", "mypy-boto3-meteringmarketplace (>=1.42.0,<1.43.0)", "mypy-boto3-mgh (>=1.42.0,<1.43.0)", "mypy-boto3-mgn (>=1.42.0,<1.43.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhub-config (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhuborchestrator (>=1.42.0,<1.43.0)", "mypy-boto3-migrationhubstrategy (>=1.42.0,<1.43.0)", "mypy-boto3-mpa (>=1.42.0,<1.43.0)", "mypy-boto3-mq (>=1.42.0,<1.43.0)", "mypy-boto3-mturk (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa (>=1.42.0,<1.43.0)", "mypy-boto3-mwaa-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-neptune (>=1.42.0,<1.43.0)", "mypy-boto3-neptune-graph (>=1.42.0,<1.43.0)", "mypy-boto3-neptunedata (>=1.42.0,<1.43.0)", "mypy-boto3-network-firewall (>=1.42.0,<1.43.0)", "mypy-boto3-networkflowmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-networkmanager (>=1.42.0,<1.43.0)", "mypy-boto3-networkmonitor (>=1.42.0,<1.43.0)", "mypy-boto3-notifications (>=1.42.0,<1.43.0)", "mypy-boto3-notificationscontacts (>=1.42.0,<1.43.0)", "mypy-boto3-nova-act (>=1.42.0,<1.43.0)", "mypy-boto3-oam (>=1.42.0,<1.43.0)", "mypy-boto3-observabilityadmin (>=1.42.0,<1.43.0)", "mypy-boto3-odb (>=1.42.0,<1.43.0)", "mypy-boto3-omics (>=1.42.0,<1.43.0)", "mypy-boto3-opensearch (>=1.42.0,<1.43.0)", "mypy-boto3-opensearchserverless (>=1.42.0,<1.43.0)", "mypy-boto3-organizations (>=1.42.0,<1.43.0)", "mypy-boto3-osis (>=1.42.0,<1.43.0)", "mypy-boto3-outposts (>=1.42.0,<1.43.0)", "mypy-boto3-panorama (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-account (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-benefits (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-channel (>=1.42.0,<1.43.0)", "mypy-boto3-partnercentral-selling (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography (>=1.42.0,<1.43.0)", "mypy-boto3-payment-cryptography-data (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-ad (>=1.42.0,<1.43.0)", "mypy-boto3-pca-connector-scep (>=1.42.0,<1.43.0)", "mypy-boto3-pcs (>=1.42.0,<1.43.0)", "mypy-boto3-personalize (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-events (>=1.42.0,<1.43.0)", "mypy-boto3-personalize-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-pi (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-email (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice (>=1.42.0,<1.43.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.42.0,<1.43.0)", "mypy-boto3-pipes (>=1.42.0,<1.43.0)", "mypy-boto3-polly (>=1.42.0,<1.43.0)", "mypy-boto3-pricing (>=1.42.0,<1.43.0)", "mypy-boto3-proton (>=1.42.0,<1.43.0)", "mypy-boto3-qapps (>=1.42.0,<1.43.0)", "mypy-boto3-qbusiness (>=1.42.0,<1.43.0)", "mypy-boto3-qconnect (>=1.42.0,<1.43.0)", "mypy-boto3-quicksight (>=1.42.0,<1.43.0)", "mypy-boto3-ram (>=1.42.0,<1.43.0)", "mypy-boto3-rbin (>=1.42.0,<1.43.0)", "mypy-boto3-rds (>=1.42.0,<1.43.0)", "mypy-boto3-rds-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-data (>=1.42.0,<1.43.0)", "mypy-boto3-redshift-serverless (>=1.42.0,<1.43.0)", "mypy-boto3-rekognition (>=1.42.0,<1.43.0)", "mypy-boto3-repostspace (>=1.42.0,<1.43.0)", "mypy-boto3-resiliencehub (>=1.42.0,<1.43.0)", "mypy-boto3-resource-explorer-2 (>=1.42.0,<1.43.0)", "mypy-boto3-resource-groups (>=1.42.0,<1.43.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.42.0,<1.43.0)", "mypy-boto3-rolesanywhere (>=1.42.0,<1.43.0)", "mypy-boto3-route53 (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-cluster (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-control-config (>=1.42.0,<1.43.0)", "mypy-boto3-route53-recovery-readiness (>=1.42.0,<1.43.0)", "mypy-boto3-route53domains (>=1.42.0,<1.43.0)", "mypy-boto3-route53globalresolver (>=1.42.0,<1.43.0)", "mypy-boto3-route53profiles (>=1.42.0,<1.43.0)", "mypy-boto3-route53resolver (>=1.42.0,<1.43.0)", "mypy-boto3-rtbfabric (>=1.42.0,<1.43.0)", "mypy-boto3-rum (>=1.42.0,<1.43.0)", "mypy-boto3-s3 (>=1.42.0,<1.43.0)", "mypy-boto3-s3control (>=1.42.0,<1.43.0)", "mypy-boto3-s3files (>=1.42.0,<1.43.0)", "mypy-boto3-s3outposts (>=1.42.0,<1.43.0)", "mypy-boto3-s3tables (>=1.42.0,<1.43.0)", "mypy-boto3-s3vectors (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-edge (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-geospatial (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-metrics (>=1.42.0,<1.43.0)", "mypy-boto3-sagemaker-runtime (>=1.42.0,<1.43.0)", "mypy-boto3-savingsplans (>=1.42.0,<1.43.0)", "mypy-boto3-scheduler (>=1.42.0,<1.43.0)", "mypy-boto3-schemas (>=1.42.0,<1.43.0)", "mypy-boto3-sdb (>=1.42.0,<1.43.0)", "mypy-boto3-secretsmanager (>=1.42.0,<1.43.0)", "mypy-boto3-security-ir (>=1.42.0,<1.43.0)", "mypy-boto3-securityagent (>=1.42.0,<1.43.0)", "mypy-boto3-securityhub (>=1.42.0,<1.43.0)", "mypy-boto3-securitylake (>=1.42.0,<1.43.0)", "mypy-boto3-serverlessrepo (>=1.42.0,<1.43.0)", "mypy-boto3-service-quotas (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog (>=1.42.0,<1.43.0)", "mypy-boto3-servicecatalog-appregistry (>=1.42.0,<1.43.0)", "mypy-boto3-servicediscovery (>=1.42.0,<1.43.0)", "mypy-boto3-ses (>=1.42.0,<1.43.0)", "mypy-boto3-sesv2 (>=1.42.0,<1.43.0)", "mypy-boto3-shield (>=1.42.0,<1.43.0)", "mypy-boto3-signer (>=1.42.0,<1.43.0)", "mypy-boto3-signer-data (>=1.42.0,<1.43.0)", "mypy-boto3-signin (>=1.42.0,<1.43.0)", "mypy-boto3-simpledbv2 (>=1.42.0,<1.43.0)", "mypy-boto3-simspaceweaver (>=1.42.0,<1.43.0)", "mypy-boto3-snow-device-management (>=1.42.0,<1.43.0)", "mypy-boto3-snowball (>=1.42.0,<1.43.0)", "mypy-boto3-sns (>=1.42.0,<1.43.0)", "mypy-boto3-socialmessaging (>=1.42.0,<1.43.0)", "mypy-boto3-sqs (>=1.42.0,<1.43.0)", "mypy-boto3-ssm (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-contacts (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-guiconnect (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-incidents (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-quicksetup (>=1.42.0,<1.43.0)", "mypy-boto3-ssm-sap (>=1.42.0,<1.43.0)", "mypy-boto3-sso (>=1.42.0,<1.43.0)", "mypy-boto3-sso-admin (>=1.42.0,<1.43.0)", "mypy-boto3-sso-oidc (>=1.42.0,<1.43.0)", "mypy-boto3-stepfunctions (>=1.42.0,<1.43.0)", "mypy-boto3-storagegateway (>=1.42.0,<1.43.0)", "mypy-boto3-sts (>=1.42.0,<1.43.0)", "mypy-boto3-supplychain (>=1.42.0,<1.43.0)", "mypy-boto3-support (>=1.42.0,<1.43.0)", "mypy-boto3-support-app (>=1.42.0,<1.43.0)", "mypy-boto3-sustainability (>=1.42.0,<1.43.0)", "mypy-boto3-swf (>=1.42.0,<1.43.0)", "mypy-boto3-synthetics (>=1.42.0,<1.43.0)", "mypy-boto3-taxsettings (>=1.42.0,<1.43.0)", "mypy-boto3-textract (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-influxdb (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-query (>=1.42.0,<1.43.0)", "mypy-boto3-timestream-write (>=1.42.0,<1.43.0)", "mypy-boto3-tnb (>=1.42.0,<1.43.0)", "mypy-boto3-transcribe (>=1.42.0,<1.43.0)", "mypy-boto3-transfer (>=1.42.0,<1.43.0)", "mypy-boto3-translate (>=1.42.0,<1.43.0)", "mypy-boto3-trustedadvisor (>=1.42.0,<1.43.0)", "mypy-boto3-uxc (>=1.42.0,<1.43.0)", "mypy-boto3-verifiedpermissions (>=1.42.0,<1.43.0)", "mypy-boto3-voice-id (>=1.42.0,<1.43.0)", "mypy-boto3-vpc-lattice (>=1.42.0,<1.43.0)", "mypy-boto3-waf (>=1.42.0,<1.43.0)", "mypy-boto3-waf-regional (>=1.42.0,<1.43.0)", "mypy-boto3-wafv2 (>=1.42.0,<1.43.0)", "mypy-boto3-wellarchitected (>=1.42.0,<1.43.0)", "mypy-boto3-wickr (>=1.42.0,<1.43.0)", "mypy-boto3-wisdom (>=1.42.0,<1.43.0)", "mypy-boto3-workdocs (>=1.42.0,<1.43.0)", "mypy-boto3-workmail (>=1.42.0,<1.43.0)", "mypy-boto3-workmailmessageflow (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-instances (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-thin-client (>=1.42.0,<1.43.0)", "mypy-boto3-workspaces-web (>=1.42.0,<1.43.0)", "mypy-boto3-xray (>=1.42.0,<1.43.0)"] -amp = ["mypy-boto3-amp (>=1.42.0,<1.43.0)"] -amplify = ["mypy-boto3-amplify (>=1.42.0,<1.43.0)"] -amplifybackend = ["mypy-boto3-amplifybackend (>=1.42.0,<1.43.0)"] -amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.42.0,<1.43.0)"] -apigateway = ["mypy-boto3-apigateway (>=1.42.0,<1.43.0)"] -apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.42.0,<1.43.0)"] -apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.42.0,<1.43.0)"] -appconfig = ["mypy-boto3-appconfig (>=1.42.0,<1.43.0)"] -appconfigdata = ["mypy-boto3-appconfigdata (>=1.42.0,<1.43.0)"] -appfabric = ["mypy-boto3-appfabric (>=1.42.0,<1.43.0)"] -appflow = ["mypy-boto3-appflow (>=1.42.0,<1.43.0)"] -appintegrations = ["mypy-boto3-appintegrations (>=1.42.0,<1.43.0)"] -application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.42.0,<1.43.0)"] -application-insights = ["mypy-boto3-application-insights (>=1.42.0,<1.43.0)"] -application-signals = ["mypy-boto3-application-signals (>=1.42.0,<1.43.0)"] -applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.42.0,<1.43.0)"] -appmesh = ["mypy-boto3-appmesh (>=1.42.0,<1.43.0)"] -apprunner = ["mypy-boto3-apprunner (>=1.42.0,<1.43.0)"] -appstream = ["mypy-boto3-appstream (>=1.42.0,<1.43.0)"] -appsync = ["mypy-boto3-appsync (>=1.42.0,<1.43.0)"] -arc-region-switch = ["mypy-boto3-arc-region-switch (>=1.42.0,<1.43.0)"] -arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.42.0,<1.43.0)"] -artifact = ["mypy-boto3-artifact (>=1.42.0,<1.43.0)"] -athena = ["mypy-boto3-athena (>=1.42.0,<1.43.0)"] -auditmanager = ["mypy-boto3-auditmanager (>=1.42.0,<1.43.0)"] -autoscaling = ["mypy-boto3-autoscaling (>=1.42.0,<1.43.0)"] -autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.42.0,<1.43.0)"] -b2bi = ["mypy-boto3-b2bi (>=1.42.0,<1.43.0)"] -backup = ["mypy-boto3-backup (>=1.42.0,<1.43.0)"] -backup-gateway = ["mypy-boto3-backup-gateway (>=1.42.0,<1.43.0)"] -backupsearch = ["mypy-boto3-backupsearch (>=1.42.0,<1.43.0)"] -batch = ["mypy-boto3-batch (>=1.42.0,<1.43.0)"] -bcm-dashboards = ["mypy-boto3-bcm-dashboards (>=1.42.0,<1.43.0)"] -bcm-data-exports = ["mypy-boto3-bcm-data-exports (>=1.42.0,<1.43.0)"] -bcm-pricing-calculator = ["mypy-boto3-bcm-pricing-calculator (>=1.42.0,<1.43.0)"] -bcm-recommended-actions = ["mypy-boto3-bcm-recommended-actions (>=1.42.0,<1.43.0)"] -bedrock = ["mypy-boto3-bedrock (>=1.42.0,<1.43.0)"] -bedrock-agent = ["mypy-boto3-bedrock-agent (>=1.42.0,<1.43.0)"] -bedrock-agent-runtime = ["mypy-boto3-bedrock-agent-runtime (>=1.42.0,<1.43.0)"] -bedrock-agentcore = ["mypy-boto3-bedrock-agentcore (>=1.42.0,<1.43.0)"] -bedrock-agentcore-control = ["mypy-boto3-bedrock-agentcore-control (>=1.42.0,<1.43.0)"] -bedrock-data-automation = ["mypy-boto3-bedrock-data-automation (>=1.42.0,<1.43.0)"] -bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime (>=1.42.0,<1.43.0)"] -bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.42.0,<1.43.0)"] -billing = ["mypy-boto3-billing (>=1.42.0,<1.43.0)"] -billingconductor = ["mypy-boto3-billingconductor (>=1.42.0,<1.43.0)"] -boto3 = ["boto3 (==1.42.92)"] -braket = ["mypy-boto3-braket (>=1.42.0,<1.43.0)"] -budgets = ["mypy-boto3-budgets (>=1.42.0,<1.43.0)"] -ce = ["mypy-boto3-ce (>=1.42.0,<1.43.0)"] -chatbot = ["mypy-boto3-chatbot (>=1.42.0,<1.43.0)"] -chime = ["mypy-boto3-chime (>=1.42.0,<1.43.0)"] -chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.42.0,<1.43.0)"] -chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.42.0,<1.43.0)"] -chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.42.0,<1.43.0)"] -chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.42.0,<1.43.0)"] -chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.42.0,<1.43.0)"] -cleanrooms = ["mypy-boto3-cleanrooms (>=1.42.0,<1.43.0)"] -cleanroomsml = ["mypy-boto3-cleanroomsml (>=1.42.0,<1.43.0)"] -cloud9 = ["mypy-boto3-cloud9 (>=1.42.0,<1.43.0)"] -cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.42.0,<1.43.0)"] -clouddirectory = ["mypy-boto3-clouddirectory (>=1.42.0,<1.43.0)"] -cloudformation = ["mypy-boto3-cloudformation (>=1.42.0,<1.43.0)"] -cloudfront = ["mypy-boto3-cloudfront (>=1.42.0,<1.43.0)"] -cloudfront-keyvaluestore = ["mypy-boto3-cloudfront-keyvaluestore (>=1.42.0,<1.43.0)"] -cloudhsm = ["mypy-boto3-cloudhsm (>=1.42.0,<1.43.0)"] -cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.42.0,<1.43.0)"] -cloudsearch = ["mypy-boto3-cloudsearch (>=1.42.0,<1.43.0)"] -cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.42.0,<1.43.0)"] -cloudtrail = ["mypy-boto3-cloudtrail (>=1.42.0,<1.43.0)"] -cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.42.0,<1.43.0)"] -cloudwatch = ["mypy-boto3-cloudwatch (>=1.42.0,<1.43.0)"] -codeartifact = ["mypy-boto3-codeartifact (>=1.42.0,<1.43.0)"] -codebuild = ["mypy-boto3-codebuild (>=1.42.0,<1.43.0)"] -codecatalyst = ["mypy-boto3-codecatalyst (>=1.42.0,<1.43.0)"] -codecommit = ["mypy-boto3-codecommit (>=1.42.0,<1.43.0)"] -codeconnections = ["mypy-boto3-codeconnections (>=1.42.0,<1.43.0)"] -codedeploy = ["mypy-boto3-codedeploy (>=1.42.0,<1.43.0)"] -codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.42.0,<1.43.0)"] -codeguru-security = ["mypy-boto3-codeguru-security (>=1.42.0,<1.43.0)"] -codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.42.0,<1.43.0)"] -codepipeline = ["mypy-boto3-codepipeline (>=1.42.0,<1.43.0)"] -codestar-connections = ["mypy-boto3-codestar-connections (>=1.42.0,<1.43.0)"] -codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.42.0,<1.43.0)"] -cognito-identity = ["mypy-boto3-cognito-identity (>=1.42.0,<1.43.0)"] -cognito-idp = ["mypy-boto3-cognito-idp (>=1.42.0,<1.43.0)"] -cognito-sync = ["mypy-boto3-cognito-sync (>=1.42.0,<1.43.0)"] -comprehend = ["mypy-boto3-comprehend (>=1.42.0,<1.43.0)"] -comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.42.0,<1.43.0)"] -compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.42.0,<1.43.0)"] -compute-optimizer-automation = ["mypy-boto3-compute-optimizer-automation (>=1.42.0,<1.43.0)"] -config = ["mypy-boto3-config (>=1.42.0,<1.43.0)"] -connect = ["mypy-boto3-connect (>=1.42.0,<1.43.0)"] -connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.42.0,<1.43.0)"] -connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.42.0,<1.43.0)"] -connectcampaignsv2 = ["mypy-boto3-connectcampaignsv2 (>=1.42.0,<1.43.0)"] -connectcases = ["mypy-boto3-connectcases (>=1.42.0,<1.43.0)"] -connecthealth = ["mypy-boto3-connecthealth (>=1.42.0,<1.43.0)"] -connectparticipant = ["mypy-boto3-connectparticipant (>=1.42.0,<1.43.0)"] -controlcatalog = ["mypy-boto3-controlcatalog (>=1.42.0,<1.43.0)"] -controltower = ["mypy-boto3-controltower (>=1.42.0,<1.43.0)"] -cost-optimization-hub = ["mypy-boto3-cost-optimization-hub (>=1.42.0,<1.43.0)"] -cur = ["mypy-boto3-cur (>=1.42.0,<1.43.0)"] -customer-profiles = ["mypy-boto3-customer-profiles (>=1.42.0,<1.43.0)"] -databrew = ["mypy-boto3-databrew (>=1.42.0,<1.43.0)"] -dataexchange = ["mypy-boto3-dataexchange (>=1.42.0,<1.43.0)"] -datapipeline = ["mypy-boto3-datapipeline (>=1.42.0,<1.43.0)"] -datasync = ["mypy-boto3-datasync (>=1.42.0,<1.43.0)"] -datazone = ["mypy-boto3-datazone (>=1.42.0,<1.43.0)"] -dax = ["mypy-boto3-dax (>=1.42.0,<1.43.0)"] -deadline = ["mypy-boto3-deadline (>=1.42.0,<1.43.0)"] -detective = ["mypy-boto3-detective (>=1.42.0,<1.43.0)"] -devicefarm = ["mypy-boto3-devicefarm (>=1.42.0,<1.43.0)"] -devops-agent = ["mypy-boto3-devops-agent (>=1.42.0,<1.43.0)"] -devops-guru = ["mypy-boto3-devops-guru (>=1.42.0,<1.43.0)"] -directconnect = ["mypy-boto3-directconnect (>=1.42.0,<1.43.0)"] -discovery = ["mypy-boto3-discovery (>=1.42.0,<1.43.0)"] -dlm = ["mypy-boto3-dlm (>=1.42.0,<1.43.0)"] -dms = ["mypy-boto3-dms (>=1.42.0,<1.43.0)"] -docdb = ["mypy-boto3-docdb (>=1.42.0,<1.43.0)"] -docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.42.0,<1.43.0)"] -drs = ["mypy-boto3-drs (>=1.42.0,<1.43.0)"] -ds = ["mypy-boto3-ds (>=1.42.0,<1.43.0)"] -ds-data = ["mypy-boto3-ds-data (>=1.42.0,<1.43.0)"] -dsql = ["mypy-boto3-dsql (>=1.42.0,<1.43.0)"] -dynamodb = ["mypy-boto3-dynamodb (>=1.42.0,<1.43.0)"] -dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.42.0,<1.43.0)"] -ebs = ["mypy-boto3-ebs (>=1.42.0,<1.43.0)"] -ec2 = ["mypy-boto3-ec2 (>=1.42.0,<1.43.0)"] -ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.42.0,<1.43.0)"] -ecr = ["mypy-boto3-ecr (>=1.42.0,<1.43.0)"] -ecr-public = ["mypy-boto3-ecr-public (>=1.42.0,<1.43.0)"] -ecs = ["mypy-boto3-ecs (>=1.42.0,<1.43.0)"] -efs = ["mypy-boto3-efs (>=1.42.0,<1.43.0)"] -eks = ["mypy-boto3-eks (>=1.42.0,<1.43.0)"] -eks-auth = ["mypy-boto3-eks-auth (>=1.42.0,<1.43.0)"] -elasticache = ["mypy-boto3-elasticache (>=1.42.0,<1.43.0)"] -elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.42.0,<1.43.0)"] -elb = ["mypy-boto3-elb (>=1.42.0,<1.43.0)"] -elbv2 = ["mypy-boto3-elbv2 (>=1.42.0,<1.43.0)"] -elementalinference = ["mypy-boto3-elementalinference (>=1.42.0,<1.43.0)"] -emr = ["mypy-boto3-emr (>=1.42.0,<1.43.0)"] -emr-containers = ["mypy-boto3-emr-containers (>=1.42.0,<1.43.0)"] -emr-serverless = ["mypy-boto3-emr-serverless (>=1.42.0,<1.43.0)"] -entityresolution = ["mypy-boto3-entityresolution (>=1.42.0,<1.43.0)"] -es = ["mypy-boto3-es (>=1.42.0,<1.43.0)"] -essential = ["mypy-boto3-cloudformation (>=1.42.0,<1.43.0)", "mypy-boto3-dynamodb (>=1.42.0,<1.43.0)", "mypy-boto3-ec2 (>=1.42.0,<1.43.0)", "mypy-boto3-lambda (>=1.42.0,<1.43.0)", "mypy-boto3-rds (>=1.42.0,<1.43.0)", "mypy-boto3-s3 (>=1.42.0,<1.43.0)", "mypy-boto3-sqs (>=1.42.0,<1.43.0)"] -events = ["mypy-boto3-events (>=1.42.0,<1.43.0)"] -evs = ["mypy-boto3-evs (>=1.42.0,<1.43.0)"] -finspace = ["mypy-boto3-finspace (>=1.42.0,<1.43.0)"] -finspace-data = ["mypy-boto3-finspace-data (>=1.42.0,<1.43.0)"] -firehose = ["mypy-boto3-firehose (>=1.42.0,<1.43.0)"] -fis = ["mypy-boto3-fis (>=1.42.0,<1.43.0)"] -fms = ["mypy-boto3-fms (>=1.42.0,<1.43.0)"] -forecast = ["mypy-boto3-forecast (>=1.42.0,<1.43.0)"] -forecastquery = ["mypy-boto3-forecastquery (>=1.42.0,<1.43.0)"] -frauddetector = ["mypy-boto3-frauddetector (>=1.42.0,<1.43.0)"] -freetier = ["mypy-boto3-freetier (>=1.42.0,<1.43.0)"] -fsx = ["mypy-boto3-fsx (>=1.42.0,<1.43.0)"] -full = ["boto3-stubs-full (>=1.42.0,<1.43.0)"] -gamelift = ["mypy-boto3-gamelift (>=1.42.0,<1.43.0)"] -gameliftstreams = ["mypy-boto3-gameliftstreams (>=1.42.0,<1.43.0)"] -geo-maps = ["mypy-boto3-geo-maps (>=1.42.0,<1.43.0)"] -geo-places = ["mypy-boto3-geo-places (>=1.42.0,<1.43.0)"] -geo-routes = ["mypy-boto3-geo-routes (>=1.42.0,<1.43.0)"] -glacier = ["mypy-boto3-glacier (>=1.42.0,<1.43.0)"] -globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.42.0,<1.43.0)"] -glue = ["mypy-boto3-glue (>=1.42.0,<1.43.0)"] -grafana = ["mypy-boto3-grafana (>=1.42.0,<1.43.0)"] -greengrass = ["mypy-boto3-greengrass (>=1.42.0,<1.43.0)"] -greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.42.0,<1.43.0)"] -groundstation = ["mypy-boto3-groundstation (>=1.42.0,<1.43.0)"] -guardduty = ["mypy-boto3-guardduty (>=1.42.0,<1.43.0)"] -health = ["mypy-boto3-health (>=1.42.0,<1.43.0)"] -healthlake = ["mypy-boto3-healthlake (>=1.42.0,<1.43.0)"] -iam = ["mypy-boto3-iam (>=1.42.0,<1.43.0)"] -identitystore = ["mypy-boto3-identitystore (>=1.42.0,<1.43.0)"] -imagebuilder = ["mypy-boto3-imagebuilder (>=1.42.0,<1.43.0)"] -importexport = ["mypy-boto3-importexport (>=1.42.0,<1.43.0)"] -inspector = ["mypy-boto3-inspector (>=1.42.0,<1.43.0)"] -inspector-scan = ["mypy-boto3-inspector-scan (>=1.42.0,<1.43.0)"] -inspector2 = ["mypy-boto3-inspector2 (>=1.42.0,<1.43.0)"] -interconnect = ["mypy-boto3-interconnect (>=1.42.0,<1.43.0)"] -internetmonitor = ["mypy-boto3-internetmonitor (>=1.42.0,<1.43.0)"] -invoicing = ["mypy-boto3-invoicing (>=1.42.0,<1.43.0)"] -iot = ["mypy-boto3-iot (>=1.42.0,<1.43.0)"] -iot-data = ["mypy-boto3-iot-data (>=1.42.0,<1.43.0)"] -iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.42.0,<1.43.0)"] -iot-managed-integrations = ["mypy-boto3-iot-managed-integrations (>=1.42.0,<1.43.0)"] -iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.42.0,<1.43.0)"] -iotevents = ["mypy-boto3-iotevents (>=1.42.0,<1.43.0)"] -iotevents-data = ["mypy-boto3-iotevents-data (>=1.42.0,<1.43.0)"] -iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.42.0,<1.43.0)"] -iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.42.0,<1.43.0)"] -iotsitewise = ["mypy-boto3-iotsitewise (>=1.42.0,<1.43.0)"] -iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.42.0,<1.43.0)"] -iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.42.0,<1.43.0)"] -iotwireless = ["mypy-boto3-iotwireless (>=1.42.0,<1.43.0)"] -ivs = ["mypy-boto3-ivs (>=1.42.0,<1.43.0)"] -ivs-realtime = ["mypy-boto3-ivs-realtime (>=1.42.0,<1.43.0)"] -ivschat = ["mypy-boto3-ivschat (>=1.42.0,<1.43.0)"] -kafka = ["mypy-boto3-kafka (>=1.42.0,<1.43.0)"] -kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.42.0,<1.43.0)"] -kendra = ["mypy-boto3-kendra (>=1.42.0,<1.43.0)"] -kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.42.0,<1.43.0)"] -keyspaces = ["mypy-boto3-keyspaces (>=1.42.0,<1.43.0)"] -keyspacesstreams = ["mypy-boto3-keyspacesstreams (>=1.42.0,<1.43.0)"] -kinesis = ["mypy-boto3-kinesis (>=1.42.0,<1.43.0)"] -kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.42.0,<1.43.0)"] -kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.42.0,<1.43.0)"] -kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.42.0,<1.43.0)"] -kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.42.0,<1.43.0)"] -kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.42.0,<1.43.0)"] -kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.42.0,<1.43.0)"] -kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.42.0,<1.43.0)"] -kms = ["mypy-boto3-kms (>=1.42.0,<1.43.0)"] -lakeformation = ["mypy-boto3-lakeformation (>=1.42.0,<1.43.0)"] -lambda = ["mypy-boto3-lambda (>=1.42.0,<1.43.0)"] -launch-wizard = ["mypy-boto3-launch-wizard (>=1.42.0,<1.43.0)"] -lex-models = ["mypy-boto3-lex-models (>=1.42.0,<1.43.0)"] -lex-runtime = ["mypy-boto3-lex-runtime (>=1.42.0,<1.43.0)"] -lexv2-models = ["mypy-boto3-lexv2-models (>=1.42.0,<1.43.0)"] -lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.42.0,<1.43.0)"] -license-manager = ["mypy-boto3-license-manager (>=1.42.0,<1.43.0)"] -license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.42.0,<1.43.0)"] -license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.42.0,<1.43.0)"] -lightsail = ["mypy-boto3-lightsail (>=1.42.0,<1.43.0)"] -location = ["mypy-boto3-location (>=1.42.0,<1.43.0)"] -logs = ["mypy-boto3-logs (>=1.42.0,<1.43.0)"] -lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.42.0,<1.43.0)"] -m2 = ["mypy-boto3-m2 (>=1.42.0,<1.43.0)"] -machinelearning = ["mypy-boto3-machinelearning (>=1.42.0,<1.43.0)"] -macie2 = ["mypy-boto3-macie2 (>=1.42.0,<1.43.0)"] -mailmanager = ["mypy-boto3-mailmanager (>=1.42.0,<1.43.0)"] -managedblockchain = ["mypy-boto3-managedblockchain (>=1.42.0,<1.43.0)"] -managedblockchain-query = ["mypy-boto3-managedblockchain-query (>=1.42.0,<1.43.0)"] -marketplace-agreement = ["mypy-boto3-marketplace-agreement (>=1.42.0,<1.43.0)"] -marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.42.0,<1.43.0)"] -marketplace-deployment = ["mypy-boto3-marketplace-deployment (>=1.42.0,<1.43.0)"] -marketplace-discovery = ["mypy-boto3-marketplace-discovery (>=1.42.0,<1.43.0)"] -marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.42.0,<1.43.0)"] -marketplace-reporting = ["mypy-boto3-marketplace-reporting (>=1.42.0,<1.43.0)"] -marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.42.0,<1.43.0)"] -mediaconnect = ["mypy-boto3-mediaconnect (>=1.42.0,<1.43.0)"] -mediaconvert = ["mypy-boto3-mediaconvert (>=1.42.0,<1.43.0)"] -medialive = ["mypy-boto3-medialive (>=1.42.0,<1.43.0)"] -mediapackage = ["mypy-boto3-mediapackage (>=1.42.0,<1.43.0)"] -mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.42.0,<1.43.0)"] -mediapackagev2 = ["mypy-boto3-mediapackagev2 (>=1.42.0,<1.43.0)"] -mediastore = ["mypy-boto3-mediastore (>=1.42.0,<1.43.0)"] -mediastore-data = ["mypy-boto3-mediastore-data (>=1.42.0,<1.43.0)"] -mediatailor = ["mypy-boto3-mediatailor (>=1.42.0,<1.43.0)"] -medical-imaging = ["mypy-boto3-medical-imaging (>=1.42.0,<1.43.0)"] -memorydb = ["mypy-boto3-memorydb (>=1.42.0,<1.43.0)"] -meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.42.0,<1.43.0)"] -mgh = ["mypy-boto3-mgh (>=1.42.0,<1.43.0)"] -mgn = ["mypy-boto3-mgn (>=1.42.0,<1.43.0)"] -migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.42.0,<1.43.0)"] -migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.42.0,<1.43.0)"] -migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.42.0,<1.43.0)"] -migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.42.0,<1.43.0)"] -mpa = ["mypy-boto3-mpa (>=1.42.0,<1.43.0)"] -mq = ["mypy-boto3-mq (>=1.42.0,<1.43.0)"] -mturk = ["mypy-boto3-mturk (>=1.42.0,<1.43.0)"] -mwaa = ["mypy-boto3-mwaa (>=1.42.0,<1.43.0)"] -mwaa-serverless = ["mypy-boto3-mwaa-serverless (>=1.42.0,<1.43.0)"] -neptune = ["mypy-boto3-neptune (>=1.42.0,<1.43.0)"] -neptune-graph = ["mypy-boto3-neptune-graph (>=1.42.0,<1.43.0)"] -neptunedata = ["mypy-boto3-neptunedata (>=1.42.0,<1.43.0)"] -network-firewall = ["mypy-boto3-network-firewall (>=1.42.0,<1.43.0)"] -networkflowmonitor = ["mypy-boto3-networkflowmonitor (>=1.42.0,<1.43.0)"] -networkmanager = ["mypy-boto3-networkmanager (>=1.42.0,<1.43.0)"] -networkmonitor = ["mypy-boto3-networkmonitor (>=1.42.0,<1.43.0)"] -notifications = ["mypy-boto3-notifications (>=1.42.0,<1.43.0)"] -notificationscontacts = ["mypy-boto3-notificationscontacts (>=1.42.0,<1.43.0)"] -nova-act = ["mypy-boto3-nova-act (>=1.42.0,<1.43.0)"] -oam = ["mypy-boto3-oam (>=1.42.0,<1.43.0)"] -observabilityadmin = ["mypy-boto3-observabilityadmin (>=1.42.0,<1.43.0)"] -odb = ["mypy-boto3-odb (>=1.42.0,<1.43.0)"] -omics = ["mypy-boto3-omics (>=1.42.0,<1.43.0)"] -opensearch = ["mypy-boto3-opensearch (>=1.42.0,<1.43.0)"] -opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.42.0,<1.43.0)"] -organizations = ["mypy-boto3-organizations (>=1.42.0,<1.43.0)"] -osis = ["mypy-boto3-osis (>=1.42.0,<1.43.0)"] -outposts = ["mypy-boto3-outposts (>=1.42.0,<1.43.0)"] -panorama = ["mypy-boto3-panorama (>=1.42.0,<1.43.0)"] -partnercentral-account = ["mypy-boto3-partnercentral-account (>=1.42.0,<1.43.0)"] -partnercentral-benefits = ["mypy-boto3-partnercentral-benefits (>=1.42.0,<1.43.0)"] -partnercentral-channel = ["mypy-boto3-partnercentral-channel (>=1.42.0,<1.43.0)"] -partnercentral-selling = ["mypy-boto3-partnercentral-selling (>=1.42.0,<1.43.0)"] -payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.42.0,<1.43.0)"] -payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.42.0,<1.43.0)"] -pca-connector-ad = ["mypy-boto3-pca-connector-ad (>=1.42.0,<1.43.0)"] -pca-connector-scep = ["mypy-boto3-pca-connector-scep (>=1.42.0,<1.43.0)"] -pcs = ["mypy-boto3-pcs (>=1.42.0,<1.43.0)"] -personalize = ["mypy-boto3-personalize (>=1.42.0,<1.43.0)"] -personalize-events = ["mypy-boto3-personalize-events (>=1.42.0,<1.43.0)"] -personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.42.0,<1.43.0)"] -pi = ["mypy-boto3-pi (>=1.42.0,<1.43.0)"] -pinpoint = ["mypy-boto3-pinpoint (>=1.42.0,<1.43.0)"] -pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.42.0,<1.43.0)"] -pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.42.0,<1.43.0)"] -pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.42.0,<1.43.0)"] -pipes = ["mypy-boto3-pipes (>=1.42.0,<1.43.0)"] -polly = ["mypy-boto3-polly (>=1.42.0,<1.43.0)"] -pricing = ["mypy-boto3-pricing (>=1.42.0,<1.43.0)"] -proton = ["mypy-boto3-proton (>=1.42.0,<1.43.0)"] -qapps = ["mypy-boto3-qapps (>=1.42.0,<1.43.0)"] -qbusiness = ["mypy-boto3-qbusiness (>=1.42.0,<1.43.0)"] -qconnect = ["mypy-boto3-qconnect (>=1.42.0,<1.43.0)"] -quicksight = ["mypy-boto3-quicksight (>=1.42.0,<1.43.0)"] -ram = ["mypy-boto3-ram (>=1.42.0,<1.43.0)"] -rbin = ["mypy-boto3-rbin (>=1.42.0,<1.43.0)"] -rds = ["mypy-boto3-rds (>=1.42.0,<1.43.0)"] -rds-data = ["mypy-boto3-rds-data (>=1.42.0,<1.43.0)"] -redshift = ["mypy-boto3-redshift (>=1.42.0,<1.43.0)"] -redshift-data = ["mypy-boto3-redshift-data (>=1.42.0,<1.43.0)"] -redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.42.0,<1.43.0)"] -rekognition = ["mypy-boto3-rekognition (>=1.42.0,<1.43.0)"] -repostspace = ["mypy-boto3-repostspace (>=1.42.0,<1.43.0)"] -resiliencehub = ["mypy-boto3-resiliencehub (>=1.42.0,<1.43.0)"] -resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.42.0,<1.43.0)"] -resource-groups = ["mypy-boto3-resource-groups (>=1.42.0,<1.43.0)"] -resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.42.0,<1.43.0)"] -rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.42.0,<1.43.0)"] -route53 = ["mypy-boto3-route53 (>=1.42.0,<1.43.0)"] -route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.42.0,<1.43.0)"] -route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.42.0,<1.43.0)"] -route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.42.0,<1.43.0)"] -route53domains = ["mypy-boto3-route53domains (>=1.42.0,<1.43.0)"] -route53globalresolver = ["mypy-boto3-route53globalresolver (>=1.42.0,<1.43.0)"] -route53profiles = ["mypy-boto3-route53profiles (>=1.42.0,<1.43.0)"] -route53resolver = ["mypy-boto3-route53resolver (>=1.42.0,<1.43.0)"] -rtbfabric = ["mypy-boto3-rtbfabric (>=1.42.0,<1.43.0)"] -rum = ["mypy-boto3-rum (>=1.42.0,<1.43.0)"] -s3 = ["mypy-boto3-s3 (>=1.42.0,<1.43.0)"] -s3control = ["mypy-boto3-s3control (>=1.42.0,<1.43.0)"] -s3files = ["mypy-boto3-s3files (>=1.42.0,<1.43.0)"] -s3outposts = ["mypy-boto3-s3outposts (>=1.42.0,<1.43.0)"] -s3tables = ["mypy-boto3-s3tables (>=1.42.0,<1.43.0)"] -s3vectors = ["mypy-boto3-s3vectors (>=1.42.0,<1.43.0)"] -sagemaker = ["mypy-boto3-sagemaker (>=1.42.0,<1.43.0)"] -sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.42.0,<1.43.0)"] -sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.42.0,<1.43.0)"] -sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.42.0,<1.43.0)"] -sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.42.0,<1.43.0)"] -sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.42.0,<1.43.0)"] -sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.42.0,<1.43.0)"] -savingsplans = ["mypy-boto3-savingsplans (>=1.42.0,<1.43.0)"] -scheduler = ["mypy-boto3-scheduler (>=1.42.0,<1.43.0)"] -schemas = ["mypy-boto3-schemas (>=1.42.0,<1.43.0)"] -sdb = ["mypy-boto3-sdb (>=1.42.0,<1.43.0)"] -secretsmanager = ["mypy-boto3-secretsmanager (>=1.42.0,<1.43.0)"] -security-ir = ["mypy-boto3-security-ir (>=1.42.0,<1.43.0)"] -securityagent = ["mypy-boto3-securityagent (>=1.42.0,<1.43.0)"] -securityhub = ["mypy-boto3-securityhub (>=1.42.0,<1.43.0)"] -securitylake = ["mypy-boto3-securitylake (>=1.42.0,<1.43.0)"] -serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.42.0,<1.43.0)"] -service-quotas = ["mypy-boto3-service-quotas (>=1.42.0,<1.43.0)"] -servicecatalog = ["mypy-boto3-servicecatalog (>=1.42.0,<1.43.0)"] -servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.42.0,<1.43.0)"] -servicediscovery = ["mypy-boto3-servicediscovery (>=1.42.0,<1.43.0)"] -ses = ["mypy-boto3-ses (>=1.42.0,<1.43.0)"] -sesv2 = ["mypy-boto3-sesv2 (>=1.42.0,<1.43.0)"] -shield = ["mypy-boto3-shield (>=1.42.0,<1.43.0)"] -signer = ["mypy-boto3-signer (>=1.42.0,<1.43.0)"] -signer-data = ["mypy-boto3-signer-data (>=1.42.0,<1.43.0)"] -signin = ["mypy-boto3-signin (>=1.42.0,<1.43.0)"] -simpledbv2 = ["mypy-boto3-simpledbv2 (>=1.42.0,<1.43.0)"] -simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.42.0,<1.43.0)"] -snow-device-management = ["mypy-boto3-snow-device-management (>=1.42.0,<1.43.0)"] -snowball = ["mypy-boto3-snowball (>=1.42.0,<1.43.0)"] -sns = ["mypy-boto3-sns (>=1.42.0,<1.43.0)"] -socialmessaging = ["mypy-boto3-socialmessaging (>=1.42.0,<1.43.0)"] -sqs = ["mypy-boto3-sqs (>=1.42.0,<1.43.0)"] -ssm = ["mypy-boto3-ssm (>=1.42.0,<1.43.0)"] -ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.42.0,<1.43.0)"] -ssm-guiconnect = ["mypy-boto3-ssm-guiconnect (>=1.42.0,<1.43.0)"] -ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.42.0,<1.43.0)"] -ssm-quicksetup = ["mypy-boto3-ssm-quicksetup (>=1.42.0,<1.43.0)"] -ssm-sap = ["mypy-boto3-ssm-sap (>=1.42.0,<1.43.0)"] -sso = ["mypy-boto3-sso (>=1.42.0,<1.43.0)"] -sso-admin = ["mypy-boto3-sso-admin (>=1.42.0,<1.43.0)"] -sso-oidc = ["mypy-boto3-sso-oidc (>=1.42.0,<1.43.0)"] -stepfunctions = ["mypy-boto3-stepfunctions (>=1.42.0,<1.43.0)"] -storagegateway = ["mypy-boto3-storagegateway (>=1.42.0,<1.43.0)"] -sts = ["mypy-boto3-sts (>=1.42.0,<1.43.0)"] -supplychain = ["mypy-boto3-supplychain (>=1.42.0,<1.43.0)"] -support = ["mypy-boto3-support (>=1.42.0,<1.43.0)"] -support-app = ["mypy-boto3-support-app (>=1.42.0,<1.43.0)"] -sustainability = ["mypy-boto3-sustainability (>=1.42.0,<1.43.0)"] -swf = ["mypy-boto3-swf (>=1.42.0,<1.43.0)"] -synthetics = ["mypy-boto3-synthetics (>=1.42.0,<1.43.0)"] -taxsettings = ["mypy-boto3-taxsettings (>=1.42.0,<1.43.0)"] -textract = ["mypy-boto3-textract (>=1.42.0,<1.43.0)"] -timestream-influxdb = ["mypy-boto3-timestream-influxdb (>=1.42.0,<1.43.0)"] -timestream-query = ["mypy-boto3-timestream-query (>=1.42.0,<1.43.0)"] -timestream-write = ["mypy-boto3-timestream-write (>=1.42.0,<1.43.0)"] -tnb = ["mypy-boto3-tnb (>=1.42.0,<1.43.0)"] -transcribe = ["mypy-boto3-transcribe (>=1.42.0,<1.43.0)"] -transfer = ["mypy-boto3-transfer (>=1.42.0,<1.43.0)"] -translate = ["mypy-boto3-translate (>=1.42.0,<1.43.0)"] -trustedadvisor = ["mypy-boto3-trustedadvisor (>=1.42.0,<1.43.0)"] -uxc = ["mypy-boto3-uxc (>=1.42.0,<1.43.0)"] -verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.42.0,<1.43.0)"] -voice-id = ["mypy-boto3-voice-id (>=1.42.0,<1.43.0)"] -vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.42.0,<1.43.0)"] -waf = ["mypy-boto3-waf (>=1.42.0,<1.43.0)"] -waf-regional = ["mypy-boto3-waf-regional (>=1.42.0,<1.43.0)"] -wafv2 = ["mypy-boto3-wafv2 (>=1.42.0,<1.43.0)"] -wellarchitected = ["mypy-boto3-wellarchitected (>=1.42.0,<1.43.0)"] -wickr = ["mypy-boto3-wickr (>=1.42.0,<1.43.0)"] -wisdom = ["mypy-boto3-wisdom (>=1.42.0,<1.43.0)"] -workdocs = ["mypy-boto3-workdocs (>=1.42.0,<1.43.0)"] -workmail = ["mypy-boto3-workmail (>=1.42.0,<1.43.0)"] -workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.42.0,<1.43.0)"] -workspaces = ["mypy-boto3-workspaces (>=1.42.0,<1.43.0)"] -workspaces-instances = ["mypy-boto3-workspaces-instances (>=1.42.0,<1.43.0)"] -workspaces-thin-client = ["mypy-boto3-workspaces-thin-client (>=1.42.0,<1.43.0)"] -workspaces-web = ["mypy-boto3-workspaces-web (>=1.42.0,<1.43.0)"] -xray = ["mypy-boto3-xray (>=1.42.0,<1.43.0)"] +accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)"] +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-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-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)"] +amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.43.0,<1.44.0)"] +apigateway = ["mypy-boto3-apigateway (>=1.43.0,<1.44.0)"] +apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.43.0,<1.44.0)"] +apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.43.0,<1.44.0)"] +appconfig = ["mypy-boto3-appconfig (>=1.43.0,<1.44.0)"] +appconfigdata = ["mypy-boto3-appconfigdata (>=1.43.0,<1.44.0)"] +appfabric = ["mypy-boto3-appfabric (>=1.43.0,<1.44.0)"] +appflow = ["mypy-boto3-appflow (>=1.43.0,<1.44.0)"] +appintegrations = ["mypy-boto3-appintegrations (>=1.43.0,<1.44.0)"] +application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.43.0,<1.44.0)"] +application-insights = ["mypy-boto3-application-insights (>=1.43.0,<1.44.0)"] +application-signals = ["mypy-boto3-application-signals (>=1.43.0,<1.44.0)"] +applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.43.0,<1.44.0)"] +appmesh = ["mypy-boto3-appmesh (>=1.43.0,<1.44.0)"] +apprunner = ["mypy-boto3-apprunner (>=1.43.0,<1.44.0)"] +appstream = ["mypy-boto3-appstream (>=1.43.0,<1.44.0)"] +appsync = ["mypy-boto3-appsync (>=1.43.0,<1.44.0)"] +arc-region-switch = ["mypy-boto3-arc-region-switch (>=1.43.0,<1.44.0)"] +arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.43.0,<1.44.0)"] +artifact = ["mypy-boto3-artifact (>=1.43.0,<1.44.0)"] +athena = ["mypy-boto3-athena (>=1.43.0,<1.44.0)"] +auditmanager = ["mypy-boto3-auditmanager (>=1.43.0,<1.44.0)"] +autoscaling = ["mypy-boto3-autoscaling (>=1.43.0,<1.44.0)"] +autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.43.0,<1.44.0)"] +b2bi = ["mypy-boto3-b2bi (>=1.43.0,<1.44.0)"] +backup = ["mypy-boto3-backup (>=1.43.0,<1.44.0)"] +backup-gateway = ["mypy-boto3-backup-gateway (>=1.43.0,<1.44.0)"] +backupsearch = ["mypy-boto3-backupsearch (>=1.43.0,<1.44.0)"] +batch = ["mypy-boto3-batch (>=1.43.0,<1.44.0)"] +bcm-dashboards = ["mypy-boto3-bcm-dashboards (>=1.43.0,<1.44.0)"] +bcm-data-exports = ["mypy-boto3-bcm-data-exports (>=1.43.0,<1.44.0)"] +bcm-pricing-calculator = ["mypy-boto3-bcm-pricing-calculator (>=1.43.0,<1.44.0)"] +bcm-recommended-actions = ["mypy-boto3-bcm-recommended-actions (>=1.43.0,<1.44.0)"] +bedrock = ["mypy-boto3-bedrock (>=1.43.0,<1.44.0)"] +bedrock-agent = ["mypy-boto3-bedrock-agent (>=1.43.0,<1.44.0)"] +bedrock-agent-runtime = ["mypy-boto3-bedrock-agent-runtime (>=1.43.0,<1.44.0)"] +bedrock-agentcore = ["mypy-boto3-bedrock-agentcore (>=1.43.0,<1.44.0)"] +bedrock-agentcore-control = ["mypy-boto3-bedrock-agentcore-control (>=1.43.0,<1.44.0)"] +bedrock-data-automation = ["mypy-boto3-bedrock-data-automation (>=1.43.0,<1.44.0)"] +bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime (>=1.43.0,<1.44.0)"] +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.3)"] +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)"] +chatbot = ["mypy-boto3-chatbot (>=1.43.0,<1.44.0)"] +chime = ["mypy-boto3-chime (>=1.43.0,<1.44.0)"] +chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.43.0,<1.44.0)"] +chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.43.0,<1.44.0)"] +chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.43.0,<1.44.0)"] +chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.43.0,<1.44.0)"] +chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.43.0,<1.44.0)"] +cleanrooms = ["mypy-boto3-cleanrooms (>=1.43.0,<1.44.0)"] +cleanroomsml = ["mypy-boto3-cleanroomsml (>=1.43.0,<1.44.0)"] +cloud9 = ["mypy-boto3-cloud9 (>=1.43.0,<1.44.0)"] +cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.43.0,<1.44.0)"] +clouddirectory = ["mypy-boto3-clouddirectory (>=1.43.0,<1.44.0)"] +cloudformation = ["mypy-boto3-cloudformation (>=1.43.0,<1.44.0)"] +cloudfront = ["mypy-boto3-cloudfront (>=1.43.0,<1.44.0)"] +cloudfront-keyvaluestore = ["mypy-boto3-cloudfront-keyvaluestore (>=1.43.0,<1.44.0)"] +cloudhsm = ["mypy-boto3-cloudhsm (>=1.43.0,<1.44.0)"] +cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.43.0,<1.44.0)"] +cloudsearch = ["mypy-boto3-cloudsearch (>=1.43.0,<1.44.0)"] +cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)"] +cloudtrail = ["mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)"] +cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)"] +cloudwatch = ["mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)"] +codeartifact = ["mypy-boto3-codeartifact (>=1.43.0,<1.44.0)"] +codebuild = ["mypy-boto3-codebuild (>=1.43.0,<1.44.0)"] +codecatalyst = ["mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)"] +codecommit = ["mypy-boto3-codecommit (>=1.43.0,<1.44.0)"] +codeconnections = ["mypy-boto3-codeconnections (>=1.43.0,<1.44.0)"] +codedeploy = ["mypy-boto3-codedeploy (>=1.43.0,<1.44.0)"] +codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.43.0,<1.44.0)"] +codeguru-security = ["mypy-boto3-codeguru-security (>=1.43.0,<1.44.0)"] +codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.43.0,<1.44.0)"] +codepipeline = ["mypy-boto3-codepipeline (>=1.43.0,<1.44.0)"] +codestar-connections = ["mypy-boto3-codestar-connections (>=1.43.0,<1.44.0)"] +codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.43.0,<1.44.0)"] +cognito-identity = ["mypy-boto3-cognito-identity (>=1.43.0,<1.44.0)"] +cognito-idp = ["mypy-boto3-cognito-idp (>=1.43.0,<1.44.0)"] +cognito-sync = ["mypy-boto3-cognito-sync (>=1.43.0,<1.44.0)"] +comprehend = ["mypy-boto3-comprehend (>=1.43.0,<1.44.0)"] +comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.43.0,<1.44.0)"] +compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.43.0,<1.44.0)"] +compute-optimizer-automation = ["mypy-boto3-compute-optimizer-automation (>=1.43.0,<1.44.0)"] +config = ["mypy-boto3-config (>=1.43.0,<1.44.0)"] +connect = ["mypy-boto3-connect (>=1.43.0,<1.44.0)"] +connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.43.0,<1.44.0)"] +connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.43.0,<1.44.0)"] +connectcampaignsv2 = ["mypy-boto3-connectcampaignsv2 (>=1.43.0,<1.44.0)"] +connectcases = ["mypy-boto3-connectcases (>=1.43.0,<1.44.0)"] +connecthealth = ["mypy-boto3-connecthealth (>=1.43.0,<1.44.0)"] +connectparticipant = ["mypy-boto3-connectparticipant (>=1.43.0,<1.44.0)"] +controlcatalog = ["mypy-boto3-controlcatalog (>=1.43.0,<1.44.0)"] +controltower = ["mypy-boto3-controltower (>=1.43.0,<1.44.0)"] +cost-optimization-hub = ["mypy-boto3-cost-optimization-hub (>=1.43.0,<1.44.0)"] +cur = ["mypy-boto3-cur (>=1.43.0,<1.44.0)"] +customer-profiles = ["mypy-boto3-customer-profiles (>=1.43.0,<1.44.0)"] +databrew = ["mypy-boto3-databrew (>=1.43.0,<1.44.0)"] +dataexchange = ["mypy-boto3-dataexchange (>=1.43.0,<1.44.0)"] +datapipeline = ["mypy-boto3-datapipeline (>=1.43.0,<1.44.0)"] +datasync = ["mypy-boto3-datasync (>=1.43.0,<1.44.0)"] +datazone = ["mypy-boto3-datazone (>=1.43.0,<1.44.0)"] +dax = ["mypy-boto3-dax (>=1.43.0,<1.44.0)"] +deadline = ["mypy-boto3-deadline (>=1.43.0,<1.44.0)"] +detective = ["mypy-boto3-detective (>=1.43.0,<1.44.0)"] +devicefarm = ["mypy-boto3-devicefarm (>=1.43.0,<1.44.0)"] +devops-agent = ["mypy-boto3-devops-agent (>=1.43.0,<1.44.0)"] +devops-guru = ["mypy-boto3-devops-guru (>=1.43.0,<1.44.0)"] +directconnect = ["mypy-boto3-directconnect (>=1.43.0,<1.44.0)"] +discovery = ["mypy-boto3-discovery (>=1.43.0,<1.44.0)"] +dlm = ["mypy-boto3-dlm (>=1.43.0,<1.44.0)"] +dms = ["mypy-boto3-dms (>=1.43.0,<1.44.0)"] +docdb = ["mypy-boto3-docdb (>=1.43.0,<1.44.0)"] +docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.43.0,<1.44.0)"] +drs = ["mypy-boto3-drs (>=1.43.0,<1.44.0)"] +ds = ["mypy-boto3-ds (>=1.43.0,<1.44.0)"] +ds-data = ["mypy-boto3-ds-data (>=1.43.0,<1.44.0)"] +dsql = ["mypy-boto3-dsql (>=1.43.0,<1.44.0)"] +dynamodb = ["mypy-boto3-dynamodb (>=1.43.0,<1.44.0)"] +dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.43.0,<1.44.0)"] +ebs = ["mypy-boto3-ebs (>=1.43.0,<1.44.0)"] +ec2 = ["mypy-boto3-ec2 (>=1.43.0,<1.44.0)"] +ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.43.0,<1.44.0)"] +ecr = ["mypy-boto3-ecr (>=1.43.0,<1.44.0)"] +ecr-public = ["mypy-boto3-ecr-public (>=1.43.0,<1.44.0)"] +ecs = ["mypy-boto3-ecs (>=1.43.0,<1.44.0)"] +efs = ["mypy-boto3-efs (>=1.43.0,<1.44.0)"] +eks = ["mypy-boto3-eks (>=1.43.0,<1.44.0)"] +eks-auth = ["mypy-boto3-eks-auth (>=1.43.0,<1.44.0)"] +elasticache = ["mypy-boto3-elasticache (>=1.43.0,<1.44.0)"] +elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.43.0,<1.44.0)"] +elb = ["mypy-boto3-elb (>=1.43.0,<1.44.0)"] +elbv2 = ["mypy-boto3-elbv2 (>=1.43.0,<1.44.0)"] +elementalinference = ["mypy-boto3-elementalinference (>=1.43.0,<1.44.0)"] +emr = ["mypy-boto3-emr (>=1.43.0,<1.44.0)"] +emr-containers = ["mypy-boto3-emr-containers (>=1.43.0,<1.44.0)"] +emr-serverless = ["mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)"] +entityresolution = ["mypy-boto3-entityresolution (>=1.43.0,<1.44.0)"] +es = ["mypy-boto3-es (>=1.43.0,<1.44.0)"] +essential = ["mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)"] +events = ["mypy-boto3-events (>=1.43.0,<1.44.0)"] +evs = ["mypy-boto3-evs (>=1.43.0,<1.44.0)"] +finspace = ["mypy-boto3-finspace (>=1.43.0,<1.44.0)"] +finspace-data = ["mypy-boto3-finspace-data (>=1.43.0,<1.44.0)"] +firehose = ["mypy-boto3-firehose (>=1.43.0,<1.44.0)"] +fis = ["mypy-boto3-fis (>=1.43.0,<1.44.0)"] +fms = ["mypy-boto3-fms (>=1.43.0,<1.44.0)"] +forecast = ["mypy-boto3-forecast (>=1.43.0,<1.44.0)"] +forecastquery = ["mypy-boto3-forecastquery (>=1.43.0,<1.44.0)"] +frauddetector = ["mypy-boto3-frauddetector (>=1.43.0,<1.44.0)"] +freetier = ["mypy-boto3-freetier (>=1.43.0,<1.44.0)"] +fsx = ["mypy-boto3-fsx (>=1.43.0,<1.44.0)"] +full = ["boto3-stubs-full (>=1.43.0,<1.44.0)"] +gamelift = ["mypy-boto3-gamelift (>=1.43.0,<1.44.0)"] +gameliftstreams = ["mypy-boto3-gameliftstreams (>=1.43.0,<1.44.0)"] +geo-maps = ["mypy-boto3-geo-maps (>=1.43.0,<1.44.0)"] +geo-places = ["mypy-boto3-geo-places (>=1.43.0,<1.44.0)"] +geo-routes = ["mypy-boto3-geo-routes (>=1.43.0,<1.44.0)"] +glacier = ["mypy-boto3-glacier (>=1.43.0,<1.44.0)"] +globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.43.0,<1.44.0)"] +glue = ["mypy-boto3-glue (>=1.43.0,<1.44.0)"] +grafana = ["mypy-boto3-grafana (>=1.43.0,<1.44.0)"] +greengrass = ["mypy-boto3-greengrass (>=1.43.0,<1.44.0)"] +greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.43.0,<1.44.0)"] +groundstation = ["mypy-boto3-groundstation (>=1.43.0,<1.44.0)"] +guardduty = ["mypy-boto3-guardduty (>=1.43.0,<1.44.0)"] +health = ["mypy-boto3-health (>=1.43.0,<1.44.0)"] +healthlake = ["mypy-boto3-healthlake (>=1.43.0,<1.44.0)"] +iam = ["mypy-boto3-iam (>=1.43.0,<1.44.0)"] +identitystore = ["mypy-boto3-identitystore (>=1.43.0,<1.44.0)"] +imagebuilder = ["mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)"] +importexport = ["mypy-boto3-importexport (>=1.43.0,<1.44.0)"] +inspector = ["mypy-boto3-inspector (>=1.43.0,<1.44.0)"] +inspector-scan = ["mypy-boto3-inspector-scan (>=1.43.0,<1.44.0)"] +inspector2 = ["mypy-boto3-inspector2 (>=1.43.0,<1.44.0)"] +interconnect = ["mypy-boto3-interconnect (>=1.43.0,<1.44.0)"] +internetmonitor = ["mypy-boto3-internetmonitor (>=1.43.0,<1.44.0)"] +invoicing = ["mypy-boto3-invoicing (>=1.43.0,<1.44.0)"] +iot = ["mypy-boto3-iot (>=1.43.0,<1.44.0)"] +iot-data = ["mypy-boto3-iot-data (>=1.43.0,<1.44.0)"] +iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)"] +iot-managed-integrations = ["mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)"] +iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)"] +iotevents = ["mypy-boto3-iotevents (>=1.43.0,<1.44.0)"] +iotevents-data = ["mypy-boto3-iotevents-data (>=1.43.0,<1.44.0)"] +iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)"] +iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)"] +iotsitewise = ["mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)"] +iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.43.0,<1.44.0)"] +iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.43.0,<1.44.0)"] +iotwireless = ["mypy-boto3-iotwireless (>=1.43.0,<1.44.0)"] +ivs = ["mypy-boto3-ivs (>=1.43.0,<1.44.0)"] +ivs-realtime = ["mypy-boto3-ivs-realtime (>=1.43.0,<1.44.0)"] +ivschat = ["mypy-boto3-ivschat (>=1.43.0,<1.44.0)"] +kafka = ["mypy-boto3-kafka (>=1.43.0,<1.44.0)"] +kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.43.0,<1.44.0)"] +kendra = ["mypy-boto3-kendra (>=1.43.0,<1.44.0)"] +kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.43.0,<1.44.0)"] +keyspaces = ["mypy-boto3-keyspaces (>=1.43.0,<1.44.0)"] +keyspacesstreams = ["mypy-boto3-keyspacesstreams (>=1.43.0,<1.44.0)"] +kinesis = ["mypy-boto3-kinesis (>=1.43.0,<1.44.0)"] +kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.43.0,<1.44.0)"] +kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.43.0,<1.44.0)"] +kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.43.0,<1.44.0)"] +kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.43.0,<1.44.0)"] +kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.43.0,<1.44.0)"] +kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.43.0,<1.44.0)"] +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)"] +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)"] +lexv2-models = ["mypy-boto3-lexv2-models (>=1.43.0,<1.44.0)"] +lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.43.0,<1.44.0)"] +license-manager = ["mypy-boto3-license-manager (>=1.43.0,<1.44.0)"] +license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.43.0,<1.44.0)"] +license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.43.0,<1.44.0)"] +lightsail = ["mypy-boto3-lightsail (>=1.43.0,<1.44.0)"] +location = ["mypy-boto3-location (>=1.43.0,<1.44.0)"] +logs = ["mypy-boto3-logs (>=1.43.0,<1.44.0)"] +lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.43.0,<1.44.0)"] +m2 = ["mypy-boto3-m2 (>=1.43.0,<1.44.0)"] +machinelearning = ["mypy-boto3-machinelearning (>=1.43.0,<1.44.0)"] +macie2 = ["mypy-boto3-macie2 (>=1.43.0,<1.44.0)"] +mailmanager = ["mypy-boto3-mailmanager (>=1.43.0,<1.44.0)"] +managedblockchain = ["mypy-boto3-managedblockchain (>=1.43.0,<1.44.0)"] +managedblockchain-query = ["mypy-boto3-managedblockchain-query (>=1.43.0,<1.44.0)"] +marketplace-agreement = ["mypy-boto3-marketplace-agreement (>=1.43.0,<1.44.0)"] +marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.43.0,<1.44.0)"] +marketplace-deployment = ["mypy-boto3-marketplace-deployment (>=1.43.0,<1.44.0)"] +marketplace-discovery = ["mypy-boto3-marketplace-discovery (>=1.43.0,<1.44.0)"] +marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.43.0,<1.44.0)"] +marketplace-reporting = ["mypy-boto3-marketplace-reporting (>=1.43.0,<1.44.0)"] +marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.43.0,<1.44.0)"] +mediaconnect = ["mypy-boto3-mediaconnect (>=1.43.0,<1.44.0)"] +mediaconvert = ["mypy-boto3-mediaconvert (>=1.43.0,<1.44.0)"] +medialive = ["mypy-boto3-medialive (>=1.43.0,<1.44.0)"] +mediapackage = ["mypy-boto3-mediapackage (>=1.43.0,<1.44.0)"] +mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.43.0,<1.44.0)"] +mediapackagev2 = ["mypy-boto3-mediapackagev2 (>=1.43.0,<1.44.0)"] +mediastore = ["mypy-boto3-mediastore (>=1.43.0,<1.44.0)"] +mediastore-data = ["mypy-boto3-mediastore-data (>=1.43.0,<1.44.0)"] +mediatailor = ["mypy-boto3-mediatailor (>=1.43.0,<1.44.0)"] +medical-imaging = ["mypy-boto3-medical-imaging (>=1.43.0,<1.44.0)"] +memorydb = ["mypy-boto3-memorydb (>=1.43.0,<1.44.0)"] +meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.43.0,<1.44.0)"] +mgh = ["mypy-boto3-mgh (>=1.43.0,<1.44.0)"] +mgn = ["mypy-boto3-mgn (>=1.43.0,<1.44.0)"] +migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.43.0,<1.44.0)"] +migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.43.0,<1.44.0)"] +migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.43.0,<1.44.0)"] +migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.43.0,<1.44.0)"] +mpa = ["mypy-boto3-mpa (>=1.43.0,<1.44.0)"] +mq = ["mypy-boto3-mq (>=1.43.0,<1.44.0)"] +mturk = ["mypy-boto3-mturk (>=1.43.0,<1.44.0)"] +mwaa = ["mypy-boto3-mwaa (>=1.43.0,<1.44.0)"] +mwaa-serverless = ["mypy-boto3-mwaa-serverless (>=1.43.0,<1.44.0)"] +neptune = ["mypy-boto3-neptune (>=1.43.0,<1.44.0)"] +neptune-graph = ["mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)"] +neptunedata = ["mypy-boto3-neptunedata (>=1.43.0,<1.44.0)"] +network-firewall = ["mypy-boto3-network-firewall (>=1.43.0,<1.44.0)"] +networkflowmonitor = ["mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)"] +networkmanager = ["mypy-boto3-networkmanager (>=1.43.0,<1.44.0)"] +networkmonitor = ["mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)"] +notifications = ["mypy-boto3-notifications (>=1.43.0,<1.44.0)"] +notificationscontacts = ["mypy-boto3-notificationscontacts (>=1.43.0,<1.44.0)"] +nova-act = ["mypy-boto3-nova-act (>=1.43.0,<1.44.0)"] +oam = ["mypy-boto3-oam (>=1.43.0,<1.44.0)"] +observabilityadmin = ["mypy-boto3-observabilityadmin (>=1.43.0,<1.44.0)"] +odb = ["mypy-boto3-odb (>=1.43.0,<1.44.0)"] +omics = ["mypy-boto3-omics (>=1.43.0,<1.44.0)"] +opensearch = ["mypy-boto3-opensearch (>=1.43.0,<1.44.0)"] +opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)"] +organizations = ["mypy-boto3-organizations (>=1.43.0,<1.44.0)"] +osis = ["mypy-boto3-osis (>=1.43.0,<1.44.0)"] +outposts = ["mypy-boto3-outposts (>=1.43.0,<1.44.0)"] +panorama = ["mypy-boto3-panorama (>=1.43.0,<1.44.0)"] +partnercentral-account = ["mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)"] +partnercentral-benefits = ["mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)"] +partnercentral-channel = ["mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)"] +partnercentral-selling = ["mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)"] +payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)"] +payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)"] +pca-connector-ad = ["mypy-boto3-pca-connector-ad (>=1.43.0,<1.44.0)"] +pca-connector-scep = ["mypy-boto3-pca-connector-scep (>=1.43.0,<1.44.0)"] +pcs = ["mypy-boto3-pcs (>=1.43.0,<1.44.0)"] +personalize = ["mypy-boto3-personalize (>=1.43.0,<1.44.0)"] +personalize-events = ["mypy-boto3-personalize-events (>=1.43.0,<1.44.0)"] +personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.43.0,<1.44.0)"] +pi = ["mypy-boto3-pi (>=1.43.0,<1.44.0)"] +pinpoint = ["mypy-boto3-pinpoint (>=1.43.0,<1.44.0)"] +pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.43.0,<1.44.0)"] +pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.43.0,<1.44.0)"] +pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)"] +pipes = ["mypy-boto3-pipes (>=1.43.0,<1.44.0)"] +polly = ["mypy-boto3-polly (>=1.43.0,<1.44.0)"] +pricing = ["mypy-boto3-pricing (>=1.43.0,<1.44.0)"] +proton = ["mypy-boto3-proton (>=1.43.0,<1.44.0)"] +qapps = ["mypy-boto3-qapps (>=1.43.0,<1.44.0)"] +qbusiness = ["mypy-boto3-qbusiness (>=1.43.0,<1.44.0)"] +qconnect = ["mypy-boto3-qconnect (>=1.43.0,<1.44.0)"] +quicksight = ["mypy-boto3-quicksight (>=1.43.0,<1.44.0)"] +ram = ["mypy-boto3-ram (>=1.43.0,<1.44.0)"] +rbin = ["mypy-boto3-rbin (>=1.43.0,<1.44.0)"] +rds = ["mypy-boto3-rds (>=1.43.0,<1.44.0)"] +rds-data = ["mypy-boto3-rds-data (>=1.43.0,<1.44.0)"] +redshift = ["mypy-boto3-redshift (>=1.43.0,<1.44.0)"] +redshift-data = ["mypy-boto3-redshift-data (>=1.43.0,<1.44.0)"] +redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.43.0,<1.44.0)"] +rekognition = ["mypy-boto3-rekognition (>=1.43.0,<1.44.0)"] +repostspace = ["mypy-boto3-repostspace (>=1.43.0,<1.44.0)"] +resiliencehub = ["mypy-boto3-resiliencehub (>=1.43.0,<1.44.0)"] +resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.43.0,<1.44.0)"] +resource-groups = ["mypy-boto3-resource-groups (>=1.43.0,<1.44.0)"] +resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.43.0,<1.44.0)"] +rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.43.0,<1.44.0)"] +route53 = ["mypy-boto3-route53 (>=1.43.0,<1.44.0)"] +route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.43.0,<1.44.0)"] +route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.43.0,<1.44.0)"] +route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.43.0,<1.44.0)"] +route53domains = ["mypy-boto3-route53domains (>=1.43.0,<1.44.0)"] +route53globalresolver = ["mypy-boto3-route53globalresolver (>=1.43.0,<1.44.0)"] +route53profiles = ["mypy-boto3-route53profiles (>=1.43.0,<1.44.0)"] +route53resolver = ["mypy-boto3-route53resolver (>=1.43.0,<1.44.0)"] +rtbfabric = ["mypy-boto3-rtbfabric (>=1.43.0,<1.44.0)"] +rum = ["mypy-boto3-rum (>=1.43.0,<1.44.0)"] +s3 = ["mypy-boto3-s3 (>=1.43.0,<1.44.0)"] +s3control = ["mypy-boto3-s3control (>=1.43.0,<1.44.0)"] +s3files = ["mypy-boto3-s3files (>=1.43.0,<1.44.0)"] +s3outposts = ["mypy-boto3-s3outposts (>=1.43.0,<1.44.0)"] +s3tables = ["mypy-boto3-s3tables (>=1.43.0,<1.44.0)"] +s3vectors = ["mypy-boto3-s3vectors (>=1.43.0,<1.44.0)"] +sagemaker = ["mypy-boto3-sagemaker (>=1.43.0,<1.44.0)"] +sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.43.0,<1.44.0)"] +sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.43.0,<1.44.0)"] +sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.43.0,<1.44.0)"] +sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.43.0,<1.44.0)"] +sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.43.0,<1.44.0)"] +sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.43.0,<1.44.0)"] +savingsplans = ["mypy-boto3-savingsplans (>=1.43.0,<1.44.0)"] +scheduler = ["mypy-boto3-scheduler (>=1.43.0,<1.44.0)"] +schemas = ["mypy-boto3-schemas (>=1.43.0,<1.44.0)"] +sdb = ["mypy-boto3-sdb (>=1.43.0,<1.44.0)"] +secretsmanager = ["mypy-boto3-secretsmanager (>=1.43.0,<1.44.0)"] +security-ir = ["mypy-boto3-security-ir (>=1.43.0,<1.44.0)"] +securityagent = ["mypy-boto3-securityagent (>=1.43.0,<1.44.0)"] +securityhub = ["mypy-boto3-securityhub (>=1.43.0,<1.44.0)"] +securitylake = ["mypy-boto3-securitylake (>=1.43.0,<1.44.0)"] +serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.43.0,<1.44.0)"] +service-quotas = ["mypy-boto3-service-quotas (>=1.43.0,<1.44.0)"] +servicecatalog = ["mypy-boto3-servicecatalog (>=1.43.0,<1.44.0)"] +servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.43.0,<1.44.0)"] +servicediscovery = ["mypy-boto3-servicediscovery (>=1.43.0,<1.44.0)"] +ses = ["mypy-boto3-ses (>=1.43.0,<1.44.0)"] +sesv2 = ["mypy-boto3-sesv2 (>=1.43.0,<1.44.0)"] +shield = ["mypy-boto3-shield (>=1.43.0,<1.44.0)"] +signer = ["mypy-boto3-signer (>=1.43.0,<1.44.0)"] +signer-data = ["mypy-boto3-signer-data (>=1.43.0,<1.44.0)"] +signin = ["mypy-boto3-signin (>=1.43.0,<1.44.0)"] +simpledbv2 = ["mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)"] +simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.43.0,<1.44.0)"] +snow-device-management = ["mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)"] +snowball = ["mypy-boto3-snowball (>=1.43.0,<1.44.0)"] +sns = ["mypy-boto3-sns (>=1.43.0,<1.44.0)"] +socialmessaging = ["mypy-boto3-socialmessaging (>=1.43.0,<1.44.0)"] +sqs = ["mypy-boto3-sqs (>=1.43.0,<1.44.0)"] +ssm = ["mypy-boto3-ssm (>=1.43.0,<1.44.0)"] +ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.43.0,<1.44.0)"] +ssm-guiconnect = ["mypy-boto3-ssm-guiconnect (>=1.43.0,<1.44.0)"] +ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.43.0,<1.44.0)"] +ssm-quicksetup = ["mypy-boto3-ssm-quicksetup (>=1.43.0,<1.44.0)"] +ssm-sap = ["mypy-boto3-ssm-sap (>=1.43.0,<1.44.0)"] +sso = ["mypy-boto3-sso (>=1.43.0,<1.44.0)"] +sso-admin = ["mypy-boto3-sso-admin (>=1.43.0,<1.44.0)"] +sso-oidc = ["mypy-boto3-sso-oidc (>=1.43.0,<1.44.0)"] +stepfunctions = ["mypy-boto3-stepfunctions (>=1.43.0,<1.44.0)"] +storagegateway = ["mypy-boto3-storagegateway (>=1.43.0,<1.44.0)"] +sts = ["mypy-boto3-sts (>=1.43.0,<1.44.0)"] +supplychain = ["mypy-boto3-supplychain (>=1.43.0,<1.44.0)"] +support = ["mypy-boto3-support (>=1.43.0,<1.44.0)"] +support-app = ["mypy-boto3-support-app (>=1.43.0,<1.44.0)"] +sustainability = ["mypy-boto3-sustainability (>=1.43.0,<1.44.0)"] +swf = ["mypy-boto3-swf (>=1.43.0,<1.44.0)"] +synthetics = ["mypy-boto3-synthetics (>=1.43.0,<1.44.0)"] +taxsettings = ["mypy-boto3-taxsettings (>=1.43.0,<1.44.0)"] +textract = ["mypy-boto3-textract (>=1.43.0,<1.44.0)"] +timestream-influxdb = ["mypy-boto3-timestream-influxdb (>=1.43.0,<1.44.0)"] +timestream-query = ["mypy-boto3-timestream-query (>=1.43.0,<1.44.0)"] +timestream-write = ["mypy-boto3-timestream-write (>=1.43.0,<1.44.0)"] +tnb = ["mypy-boto3-tnb (>=1.43.0,<1.44.0)"] +transcribe = ["mypy-boto3-transcribe (>=1.43.0,<1.44.0)"] +transfer = ["mypy-boto3-transfer (>=1.43.0,<1.44.0)"] +translate = ["mypy-boto3-translate (>=1.43.0,<1.44.0)"] +trustedadvisor = ["mypy-boto3-trustedadvisor (>=1.43.0,<1.44.0)"] +uxc = ["mypy-boto3-uxc (>=1.43.0,<1.44.0)"] +verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.43.0,<1.44.0)"] +voice-id = ["mypy-boto3-voice-id (>=1.43.0,<1.44.0)"] +vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.43.0,<1.44.0)"] +waf = ["mypy-boto3-waf (>=1.43.0,<1.44.0)"] +waf-regional = ["mypy-boto3-waf-regional (>=1.43.0,<1.44.0)"] +wafv2 = ["mypy-boto3-wafv2 (>=1.43.0,<1.44.0)"] +wellarchitected = ["mypy-boto3-wellarchitected (>=1.43.0,<1.44.0)"] +wickr = ["mypy-boto3-wickr (>=1.43.0,<1.44.0)"] +wisdom = ["mypy-boto3-wisdom (>=1.43.0,<1.44.0)"] +workdocs = ["mypy-boto3-workdocs (>=1.43.0,<1.44.0)"] +workmail = ["mypy-boto3-workmail (>=1.43.0,<1.44.0)"] +workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.43.0,<1.44.0)"] +workspaces = ["mypy-boto3-workspaces (>=1.43.0,<1.44.0)"] +workspaces-instances = ["mypy-boto3-workspaces-instances (>=1.43.0,<1.44.0)"] +workspaces-thin-client = ["mypy-boto3-workspaces-thin-client (>=1.43.0,<1.44.0)"] +workspaces-web = ["mypy-boto3-workspaces-web (>=1.43.0,<1.44.0)"] +xray = ["mypy-boto3-xray (>=1.43.0,<1.44.0)"] [[package]] name = "botocore" @@ -1848,14 +1848,14 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "filelock" -version = "3.25.2" +version = "3.29.0" description = "A platform independent file lock." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70"}, - {file = "filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694"}, + {file = "filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258"}, + {file = "filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90"}, ] [[package]] @@ -2990,14 +2990,14 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-appconfig" -version = "1.42.3" -description = "Type annotations for boto3 AppConfig 1.42.3 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 AppConfig 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_appconfig-1.42.3-py3-none-any.whl", hash = "sha256:88857735f2615bcad49e254c12585a29bdf4fbe348d1f72907210569ec97455e"}, - {file = "mypy_boto3_appconfig-1.42.3.tar.gz", hash = "sha256:606d37765259c854a3574eacc3fe5ca3956b5c456b12ff80c8e1cb20bdab9119"}, + {file = "mypy_boto3_appconfig-1.43.0-py3-none-any.whl", hash = "sha256:d9ce0805d58653ec948a9674b53854ef5fcd3318f12b619cfa7052045b7852f9"}, + {file = "mypy_boto3_appconfig-1.43.0.tar.gz", hash = "sha256:25c5e8fdd19dd1a790ceb2450bdb1c3c7288d939daf8f6962d6559c02d7b8a0a"}, ] [package.dependencies] @@ -3005,14 +3005,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-appconfigdata" -version = "1.42.3" -description = "Type annotations for boto3 AppConfigData 1.42.3 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 AppConfigData 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_appconfigdata-1.42.3-py3-none-any.whl", hash = "sha256:3ef47224643a511bd217a92c3360cccf39be8393ed218a199555bc0592ede64f"}, - {file = "mypy_boto3_appconfigdata-1.42.3.tar.gz", hash = "sha256:595e36e9f477205916e1f11d28c6c335d606a20e55bcb793a43a4b48a4b2b32d"}, + {file = "mypy_boto3_appconfigdata-1.43.0-py3-none-any.whl", hash = "sha256:a80c07bc643d9af1f934a4b76fe6ab0304f03d913bc7393eefe527e2072baa92"}, + {file = "mypy_boto3_appconfigdata-1.43.0.tar.gz", hash = "sha256:9570014a955620507743e66b93c5e5e6da07b39b48f146c7abc6b259ab39d562"}, ] [package.dependencies] @@ -3020,14 +3020,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-cloudformation" -version = "1.42.3" -description = "Type annotations for boto3 CloudFormation 1.42.3 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 CloudFormation 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_cloudformation-1.42.3-py3-none-any.whl", hash = "sha256:d4c802dd78844f10e944143b9f40c2c1199ed5f57f3540ab7bfc2281ac5bcaf0"}, - {file = "mypy_boto3_cloudformation-1.42.3.tar.gz", hash = "sha256:3bd3849bc89a371d4c368691535b320244ba00579cddd63bb58b73f28d70e510"}, + {file = "mypy_boto3_cloudformation-1.43.0-py3-none-any.whl", hash = "sha256:bcb2f8b8231f6bd96cc18d17c1c72ea0dfa6dc8156966d8d12495445f5041f4c"}, + {file = "mypy_boto3_cloudformation-1.43.0.tar.gz", hash = "sha256:5be845bc3dc1b9cdbd8b6b071fad7c42d0221d4087ac0cc7c5b9dd219b324606"}, ] [package.dependencies] @@ -3035,14 +3035,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-cloudwatch" -version = "1.42.56" -description = "Type annotations for boto3 CloudWatch 1.42.56 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.2" +description = "Type annotations for boto3 CloudWatch 1.43.2 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_cloudwatch-1.42.56-py3-none-any.whl", hash = "sha256:40621e91fbad74a739cdfb76bd5e331059a3d1bc13ae866ab332bf20641c1574"}, - {file = "mypy_boto3_cloudwatch-1.42.56.tar.gz", hash = "sha256:6791ab895dbd2c2871f8c0d686ae5adb39418dbd46515996e2c80a59664d0dcf"}, + {file = "mypy_boto3_cloudwatch-1.43.2-py3-none-any.whl", hash = "sha256:954a9ac4a7d24310aa4df4e3de943fcc1fedb0b1cd0361c51d05951df0ac7918"}, + {file = "mypy_boto3_cloudwatch-1.43.2.tar.gz", hash = "sha256:a08fb826321b88da8043a4175d7dce7a28119ac22aca6e12d938b0ae33228d05"}, ] [package.dependencies] @@ -3050,14 +3050,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.42.55" -description = "Type annotations for boto3 DynamoDB 1.42.55 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 DynamoDB 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_dynamodb-1.42.55-py3-none-any.whl", hash = "sha256:652af33641601d223fb35207b89bd98513a7493d2b95ae4cba47c925b6ec103c"}, - {file = "mypy_boto3_dynamodb-1.42.55.tar.gz", hash = "sha256:a445f439b6bc4532fd592cb7f44444c8fc8f397271c0d9087e712f71f196d2f9"}, + {file = "mypy_boto3_dynamodb-1.43.0-py3-none-any.whl", hash = "sha256:60b64d15e86d406a980d96f734d8c7fb1704668d0234dc8dabd2532c902a3ba6"}, + {file = "mypy_boto3_dynamodb-1.43.0.tar.gz", hash = "sha256:f0cea38e058f1d07361ecb55d8f40665d824b42cf4864724c7fccc8bf3946fcd"}, ] [package.dependencies] @@ -3065,14 +3065,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-lambda" -version = "1.42.37" -description = "Type annotations for boto3 Lambda 1.42.37 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 Lambda 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_lambda-1.42.37-py3-none-any.whl", hash = "sha256:9614518cbe3c300d3d1e2d9c3d857c3829c44a8544c4cd4ca393d35181b22619"}, - {file = "mypy_boto3_lambda-1.42.37.tar.gz", hash = "sha256:94f7f0708f9b5ffa5b8b3eb6d564be1ef402ebb8b8cd96045332b7a3bc1ea0e0"}, + {file = "mypy_boto3_lambda-1.43.0-py3-none-any.whl", hash = "sha256:847b8f12b74f881c743464cd0010a04e2b21201b39ac92b1040c6cd276bac4e6"}, + {file = "mypy_boto3_lambda-1.43.0.tar.gz", hash = "sha256:a58de26b5c13be54deab31723ee9ab7aaa922be1dfbd093dc3a4ca12cc853157"}, ] [package.dependencies] @@ -3080,14 +3080,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-logs" -version = "1.42.60" -description = "Type annotations for boto3 CloudWatchLogs 1.42.60 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.3" +description = "Type annotations for boto3 CloudWatchLogs 1.43.3 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_logs-1.42.60-py3-none-any.whl", hash = "sha256:4a34c1224a11d09b883789c47f1bd2910e7b50151fdec63266f7ff543caca3d0"}, - {file = "mypy_boto3_logs-1.42.60.tar.gz", hash = "sha256:08110d32d9332d7aa08c2cba0f5c3813ed1beb74c682e7407519fe4f3d1b2bff"}, + {file = "mypy_boto3_logs-1.43.3-py3-none-any.whl", hash = "sha256:853652fb1fb9de9eb1439c9ebbe578afe080cc7693d12e3ea778bba636aeb836"}, + {file = "mypy_boto3_logs-1.43.3.tar.gz", hash = "sha256:9c7484a6f848e7e5c346a2ea85663c24d282ae78797748321117b262d6ea845c"}, ] [package.dependencies] @@ -3095,14 +3095,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-s3" -version = "1.42.67" -description = "Type annotations for boto3 S3 1.42.67 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 S3 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_s3-1.42.67-py3-none-any.whl", hash = "sha256:93208799734611da4caa5fa8f5ce677b62758ddcd34b737b9f7ae471d179b95e"}, - {file = "mypy_boto3_s3-1.42.67.tar.gz", hash = "sha256:3a3a918a9949f2d6f8071d490b8968ddce634aa19590697537e5189cbdca403e"}, + {file = "mypy_boto3_s3-1.43.0-py3-none-any.whl", hash = "sha256:aaa7991e7ffafcf8ff4fb23c5fb4cc4554ef5724c889ff016b87e60f27405b5b"}, + {file = "mypy_boto3_s3-1.43.0.tar.gz", hash = "sha256:3bfb027b1f3df9316ff72ff29f4b2dc0d7d65ed5032d8bcf4892222994228588"}, ] [package.dependencies] @@ -3110,14 +3110,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-secretsmanager" -version = "1.42.8" -description = "Type annotations for boto3 SecretsManager 1.42.8 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 SecretsManager 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_secretsmanager-1.42.8-py3-none-any.whl", hash = "sha256:50c891a88e725a8dba7444018e47590ea63d8e938abe2b1c0b25e5413f39d51d"}, - {file = "mypy_boto3_secretsmanager-1.42.8.tar.gz", hash = "sha256:5ab42f35ce932765ebb1684146f478a87cc4b83bef950fd1aa0e268b88d59c81"}, + {file = "mypy_boto3_secretsmanager-1.43.0-py3-none-any.whl", hash = "sha256:38415cdecb73dd20e485707a7cf456f6dde54ff4b155e7fb255eb001eb47d5bc"}, + {file = "mypy_boto3_secretsmanager-1.43.0.tar.gz", hash = "sha256:265ee2fddf9d3e42ae39685625fb7861a539110d8e324372847c0e1cbd666b20"}, ] [package.dependencies] @@ -3125,14 +3125,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-ssm" -version = "1.42.54" -description = "Type annotations for boto3 SSM 1.42.54 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 SSM 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_ssm-1.42.54-py3-none-any.whl", hash = "sha256:dfd70aa5f60be70437b53482fa6e183bafe922598a50fc6c51f6ad3bd70d8c04"}, - {file = "mypy_boto3_ssm-1.42.54.tar.gz", hash = "sha256:f4bc19a08635757808b66ef94a5b52c3729da998587745962626e60606a1be2c"}, + {file = "mypy_boto3_ssm-1.43.0-py3-none-any.whl", hash = "sha256:56caee120bdc601aec269b4203e67365db7f1531797d87ff616e318249fc1399"}, + {file = "mypy_boto3_ssm-1.43.0.tar.gz", hash = "sha256:33cb659b6182160141f9598fbdf6ff921dc94247a86f62152abd870b24e4ff62"}, ] [package.dependencies] @@ -3140,14 +3140,14 @@ typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [[package]] name = "mypy-boto3-xray" -version = "1.42.3" -description = "Type annotations for boto3 XRay 1.42.3 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.0" +description = "Type annotations for boto3 XRay 1.43.0 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_xray-1.42.3-py3-none-any.whl", hash = "sha256:a8bd87257e3931a415bee6b82892190f3588580dbaf0b54233f348a8f27ebccd"}, - {file = "mypy_boto3_xray-1.42.3.tar.gz", hash = "sha256:8092c41967eed2d0fee096a22b082bb107cfe2bb467a8dd7fbdc392593f1969c"}, + {file = "mypy_boto3_xray-1.43.0-py3-none-any.whl", hash = "sha256:122dd8b99fcd6cbd66314211b692ff32c96a4d9dd02b40d82b5a376faf279a6e"}, + {file = "mypy_boto3_xray-1.43.0.tar.gz", hash = "sha256:68800f2eb955a85d166ad462b5f9563cbd6d0578845807137c93cd3f8e70eb44"}, ] [package.dependencies] @@ -4629,29 +4629,29 @@ files = [ [[package]] name = "ty" -version = "0.0.32" +version = "0.0.34" description = "An extremely fast Python type checker, written in Rust." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "ty-0.0.32-py3-none-linux_armv6l.whl", hash = "sha256:dacbc2f6cd698d488ae7436838ff929570455bf94bfa4d9fe57a630c552aff83"}, - {file = "ty-0.0.32-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914bbc4f605ce2a9e2a78982e28fae1d3359a169d141f9dc3b4c7749cd5eca81"}, - {file = "ty-0.0.32-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4787ac9fe1f86b1f3133f5c6732adbe2df5668b50c679ac6e2d98cd284da812f"}, - {file = "ty-0.0.32-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ea0a728af99fe40dd744cba6441a2404f80b7f4bde17aa6da393810af5ea57"}, - {file = "ty-0.0.32-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2850561f9b018ae33d7e5bbfa0ac414d3c518513edcffe43877dc9801446b9c5"}, - {file = "ty-0.0.32-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5fa2fb3c614349ee211d36476b49d88c5ef79a687cdb91b2872ad023b94d2f8"}, - {file = "ty-0.0.32-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b89969307ab2417d41c9be8059dd79feea577234e1e10d35132f5495e0d42c6"}, - {file = "ty-0.0.32-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b59868ede9b1d69a088f0d695df52a0061f95fa7baa1d5e0dc6fc9cf06e1334"}, - {file = "ty-0.0.32-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8300caf35345498e9b9b03e550bba03cee8f5f5f8ab4c83c3b1ff1b7403b7d3a"}, - {file = "ty-0.0.32-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:583c7094f4574b02f724db924f98b804d1387a0bd9405ecb5e078cc0f47fbcfb"}, - {file = "ty-0.0.32-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e44ebe1bb4143a5628bc4db67ac0dfebe14594af671e4ee66f6f2e983da56501"}, - {file = "ty-0.0.32-py3-none-musllinux_1_2_i686.whl", hash = "sha256:06f17ada3e069cba6148342ef88e9929156beca8473e8d4f101b68f66c75643e"}, - {file = "ty-0.0.32-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e96e60fa556cec04f15d7ea62d2ceee5982bd389233e961ab9fd42304e278175"}, - {file = "ty-0.0.32-py3-none-win32.whl", hash = "sha256:2ff2ebb4986b24aebcf1444db7db5ca41b36086040e95eea9f8fb851c11e805c"}, - {file = "ty-0.0.32-py3-none-win_amd64.whl", hash = "sha256:ba7284a4a954b598c1b31500352b3ec1f89bff533825592b5958848226fdc7ee"}, - {file = "ty-0.0.32-py3-none-win_arm64.whl", hash = "sha256:7e10aadbdbda989a7d567ee6a37f8b98d4d542e31e3b190a2879fd581f75d658"}, - {file = "ty-0.0.32.tar.gz", hash = "sha256:8743174c5f920f6700a4a0c9de140109189192ba16226884cd50095b43b8a45c"}, + {file = "ty-0.0.34-py3-none-linux_armv6l.whl", hash = "sha256:9ecc3d14f07a95a6ceb88e07f8e62358dbd37325d3d5bd56da7217ff1fef7fb8"}, + {file = "ty-0.0.34-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0dccffd8a9d02321cd2dee3249df205e26d62694e741f4eeca36b157fd8b419f"}, + {file = "ty-0.0.34-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b0ea47a2998e167ab3b21d2f4b5309a9cf33c297809f6d7e3e753252223174d0"}, + {file = "ty-0.0.34-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b37da00b41a118a459ae56d8947e70651073fb33ebfbceb820e4a10b22d5023"}, + {file = "ty-0.0.34-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81cbbb93c2342fe3de43e625d3a9eb149633e9f485e816ebf6395d08685355d8"}, + {file = "ty-0.0.34-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c5b4dea1594a021289e172582df9cde7089dce14b276fc650e7b212b1772e12"}, + {file = "ty-0.0.34-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:030fb00aa2d2a5b5ae9d9183d574e0c82dae80566700a7490c43669d8ece40cd"}, + {file = "ty-0.0.34-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ae9555e24e36c63a8218e037a5a63f15579eb6aa94f41017e57cd41d335cfb5"}, + {file = "ty-0.0.34-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99eb23df9ed129fc26d1ab00d6f0b8dfe5253b09c2ac6abdb11523fa70d67f10"}, + {file = "ty-0.0.34-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:85de45382016eceae69e104815eb2cfa200787df104002e262a86cbd43ed2c02"}, + {file = "ty-0.0.34-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:14cb575fb8fa5131f5129d100cfe23c1575d23faf5dfc5158432749a3e38c9b5"}, + {file = "ty-0.0.34-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c6fc0b69d8450e6910ba9db34572b959b81329a97ae273c391f70e9fb6c1aade"}, + {file = "ty-0.0.34-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:30dfcec2f0fde3993f4f912ed0e057dcbebc8615299f610a4c2ddb7b5a3e1e06"}, + {file = "ty-0.0.34-py3-none-win32.whl", hash = "sha256:97b77ddf007271b812a313a8f0a14929bc5590958433e1fb83ef585676f53342"}, + {file = "ty-0.0.34-py3-none-win_amd64.whl", hash = "sha256:1f543968accb952705134028d1fda8656882787dbbc667ad4d6c3ba23791d604"}, + {file = "ty-0.0.34-py3-none-win_arm64.whl", hash = "sha256:ea09108cbcb16b6b06d7596312b433bf49681e78d30e4dc7fb3c1b248a95e09a"}, + {file = "ty-0.0.34.tar.gz", hash = "sha256:a6efe66b0f13c03a65e6c72ec9abfe2792e2fd063c74fa67e2c4930e29d661be"}, ] [[package]] @@ -5189,4 +5189,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "7b5ee713f6904edb56fda6f83eaf2a0e34373f685e19a94d76b985dad427c81b" +content-hash = "f3a3c406f885fbf43aa21202c86dcc7da0e79933fbfd2a5d42d86ca8852dedeb" diff --git a/pyproject.toml b/pyproject.toml index c6a990aa246..57aa680a030 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.33" +ty = ">=0.0.23,<0.0.35" [tool.coverage.run] source = ["aws_lambda_powertools"] @@ -241,5 +241,6 @@ exclude = [ "aws_lambda_powertools/tracing/**", "aws_lambda_powertools/utilities/batch/**", "aws_lambda_powertools/utilities/idempotency/**", + "aws_lambda_powertools/utilities/parameters/**", "aws_lambda_powertools/event_handler/**", ] From 1cfde0025d69ede5d60072ec5649f4137ed46ae2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 19:13:47 +0100 Subject: [PATCH 73/84] chore(deps-dev): bump gitpython from 3.1.47 to 3.1.50 (#8214) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.47 to 3.1.50. - [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.47...3.1.50) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.50 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/poetry.lock b/poetry.lock index c9d611fad2d..735cd892774 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.2.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" @@ -325,7 +325,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"}, @@ -1837,7 +1837,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"}, @@ -1893,14 +1893,14 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.47" +version = "3.1.50" 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.47-py3-none-any.whl", hash = "sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905"}, - {file = "gitpython-3.1.47.tar.gz", hash = "sha256:dba27f922bd2b42cb54c87a8ab3cb6beb6bf07f3d564e21ac848913a05a8a3cd"}, + {file = "gitpython-3.1.50-py3-none-any.whl", hash = "sha256:d352abe2908d07355014abdd21ddf798c2a961469239afec4962e9da884858f9"}, + {file = "gitpython-3.1.50.tar.gz", hash = "sha256:80da2d12504d52e1f998772dc5baf6e553f8d2fcfe1fcc226c9d9a2ee3372dcc"}, ] [package.dependencies] @@ -3418,7 +3418,7 @@ files = [ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] annotated-types = ">=0.6.0" @@ -3560,7 +3560,7 @@ files = [ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] -markers = {main = "extra == \"parser\" or extra == \"all\""} +markers = {main = "extra == \"all\" or extra == \"parser\""} [package.dependencies] typing-extensions = ">=4.14.1" @@ -4815,7 +4815,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" @@ -5133,7 +5133,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 c4136e22e6dbd090b64a548825d6c7c7b732484b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 19:15:34 +0100 Subject: [PATCH 74/84] chore(deps): bump gitpython from 3.1.47 to 3.1.50 in /docs (#8213) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.47 to 3.1.50. - [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.47...3.1.50) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.50 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 f35bb2b968e..855ec4756d3 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.47 \ - --hash=sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905 \ - --hash=sha256:dba27f922bd2b42cb54c87a8ab3cb6beb6bf07f3d564e21ac848913a05a8a3cd +gitpython==3.1.50 \ + --hash=sha256:80da2d12504d52e1f998772dc5baf6e553f8d2fcfe1fcc226c9d9a2ee3372dcc \ + --hash=sha256:d352abe2908d07355014abdd21ddf798c2a961469239afec4962e9da884858f9 # via mkdocs-git-revision-date-plugin griffe==1.13.0 \ --hash=sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0 \ From 6a8a4cd7d9064fbda54bb93461bd7fc6c8b887d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 22:30:51 +0200 Subject: [PATCH 75/84] chore(deps): bump urllib3 from 2.6.3 to 2.7.0 in /docs (#8216) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.6.3 to 2.7.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.6.3...2.7.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.7.0 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 855ec4756d3..04693e95a0e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -419,9 +419,9 @@ typing-extensions==4.14.0 \ --hash=sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4 \ --hash=sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af # via beautifulsoup4 -urllib3==2.6.3 \ - --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ - --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4 +urllib3==2.7.0 \ + --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ + --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 # via requests watchdog==6.0.0 \ --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ From dfb19a50560957fca406df1cbf57a0e04e170986 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 22:38:34 +0200 Subject: [PATCH 76/84] chore(deps-dev): bump urllib3 from 2.6.3 to 2.7.0 (#8217) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.6.3 to 2.7.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.6.3...2.7.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.7.0 dependency-type: direct:development ... 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 735cd892774..40414de4b0a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4911,14 +4911,14 @@ files = [ [[package]] name = "urllib3" -version = "2.6.3" +version = "2.7.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, - {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, + {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, + {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, ] [package.extras] From e91fd5af15d53ef9d4e5b4947b868436d48ba5d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 22:40:35 +0200 Subject: [PATCH 77/84] chore(deps-dev): bump urllib3 from 2.6.3 to 2.7.0 in /layer_v3 (#8218) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.6.3 to 2.7.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.6.3...2.7.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.7.0 dependency-type: direct:development ... 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 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/layer_v3/poetry.lock b/layer_v3/poetry.lock index 283262858e7..79d0e9ccd06 100644 --- a/layer_v3/poetry.lock +++ b/layer_v3/poetry.lock @@ -476,14 +476,14 @@ markers = {dev = "python_version == \"3.10\""} [[package]] name = "urllib3" -version = "2.6.3" +version = "2.7.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, - {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, + {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, + {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, ] [package.extras] From bd9f9dc9a40d9acf4a6945aee702ebcde0450be5 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 13 May 2026 09:13:54 +0200 Subject: [PATCH 78/84] chore(deps): consolidate dependabot updates (13052026) (#8228) * 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.1120.0 to 2.1121.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1121.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1121.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.34 to 0.0.35 Bumps [ty](https://github.com/astral-sh/ty) from 0.0.34 to 0.0.35. - [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.34...0.0.35) --- updated-dependencies: - dependency-name: ty dependency-version: 0.0.35 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump types-protobuf Bumps [types-protobuf](https://github.com/python/typeshed) from 7.34.1.20260408 to 7.34.1.20260508. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-protobuf dependency-version: 7.34.1.20260508 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump types-python-dateutil Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.9.0.20260408 to 2.9.0.20260508. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-python-dateutil dependency-version: 2.9.0.20260508 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump aws-cdk-lib from 2.252.0 to 2.253.1 Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.252.0 to 2.253.1. - [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.252.0...v2.253.1) --- updated-dependencies: - dependency-name: aws-cdk-lib dependency-version: 2.253.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps): bump ujson from 5.12.0 to 5.12.1 Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.12.0 to 5.12.1. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.12.0...5.12.1) --- updated-dependencies: - dependency-name: ujson dependency-version: 5.12.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 8 +- package.json | 2 +- poetry.lock | 216 +++++++++++++++++++++++----------------------- pyproject.toml | 2 +- 4 files changed, 113 insertions(+), 115 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ba9e2b2226..e82814ea9ec 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.1120.0" + "aws-cdk": "^2.1121.0" } }, "node_modules/aws-cdk": { - "version": "2.1120.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1120.0.tgz", - "integrity": "sha512-vDVa0IX0FhizARdY/GLSParFglKbdHCIhM8IDmynrAv9w8uLLljzWMeLUOhC1XpMErDZ/npYEihAOjfKxTaMIw==", + "version": "2.1121.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1121.0.tgz", + "integrity": "sha512-cG7CHt/SytYTfwrK+BUNQpqmS1dwhjt8z6ExKL6GK4n+8/6ZCwFzxlZWA/jUd2+Y9xPc+Q8cLKfMqGmgxEXbkg==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 18d4fae537a..16ea39cd12e 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.1120.0" + "aws-cdk": "^2.1121.0" } } diff --git a/poetry.lock b/poetry.lock index 40414de4b0a..f5b5a5617af 100644 --- a/poetry.lock +++ b/poetry.lock @@ -241,14 +241,14 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.252.0" +version = "2.253.1" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.252.0-py3-none-any.whl", hash = "sha256:c96d02582d344ee81ea2ef8a5e22b6e680789973804720ec9f0e95a050257db1"}, - {file = "aws_cdk_lib-2.252.0.tar.gz", hash = "sha256:2498d771ab141599c48494bd2564ee9a4fbaade54befa9356811e9454616d0a0"}, + {file = "aws_cdk_lib-2.253.1-py3-none-any.whl", hash = "sha256:03a6f5080978f9e3576f490d06fbd1f41f159280d34dbca50721de4a19694136"}, + {file = "aws_cdk_lib-2.253.1.tar.gz", hash = "sha256:df03363cdaef4d2d7bac368b2d5d2bf4209921d21096cd5f8e5889347fee4793"}, ] [package.dependencies] @@ -4629,29 +4629,30 @@ files = [ [[package]] name = "ty" -version = "0.0.34" +version = "0.0.35" description = "An extremely fast Python type checker, written in Rust." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "ty-0.0.34-py3-none-linux_armv6l.whl", hash = "sha256:9ecc3d14f07a95a6ceb88e07f8e62358dbd37325d3d5bd56da7217ff1fef7fb8"}, - {file = "ty-0.0.34-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0dccffd8a9d02321cd2dee3249df205e26d62694e741f4eeca36b157fd8b419f"}, - {file = "ty-0.0.34-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b0ea47a2998e167ab3b21d2f4b5309a9cf33c297809f6d7e3e753252223174d0"}, - {file = "ty-0.0.34-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b37da00b41a118a459ae56d8947e70651073fb33ebfbceb820e4a10b22d5023"}, - {file = "ty-0.0.34-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81cbbb93c2342fe3de43e625d3a9eb149633e9f485e816ebf6395d08685355d8"}, - {file = "ty-0.0.34-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c5b4dea1594a021289e172582df9cde7089dce14b276fc650e7b212b1772e12"}, - {file = "ty-0.0.34-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:030fb00aa2d2a5b5ae9d9183d574e0c82dae80566700a7490c43669d8ece40cd"}, - {file = "ty-0.0.34-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ae9555e24e36c63a8218e037a5a63f15579eb6aa94f41017e57cd41d335cfb5"}, - {file = "ty-0.0.34-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99eb23df9ed129fc26d1ab00d6f0b8dfe5253b09c2ac6abdb11523fa70d67f10"}, - {file = "ty-0.0.34-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:85de45382016eceae69e104815eb2cfa200787df104002e262a86cbd43ed2c02"}, - {file = "ty-0.0.34-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:14cb575fb8fa5131f5129d100cfe23c1575d23faf5dfc5158432749a3e38c9b5"}, - {file = "ty-0.0.34-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c6fc0b69d8450e6910ba9db34572b959b81329a97ae273c391f70e9fb6c1aade"}, - {file = "ty-0.0.34-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:30dfcec2f0fde3993f4f912ed0e057dcbebc8615299f610a4c2ddb7b5a3e1e06"}, - {file = "ty-0.0.34-py3-none-win32.whl", hash = "sha256:97b77ddf007271b812a313a8f0a14929bc5590958433e1fb83ef585676f53342"}, - {file = "ty-0.0.34-py3-none-win_amd64.whl", hash = "sha256:1f543968accb952705134028d1fda8656882787dbbc667ad4d6c3ba23791d604"}, - {file = "ty-0.0.34-py3-none-win_arm64.whl", hash = "sha256:ea09108cbcb16b6b06d7596312b433bf49681e78d30e4dc7fb3c1b248a95e09a"}, - {file = "ty-0.0.34.tar.gz", hash = "sha256:a6efe66b0f13c03a65e6c72ec9abfe2792e2fd063c74fa67e2c4930e29d661be"}, + {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"}, ] [[package]] @@ -4699,14 +4700,14 @@ types-setuptools = "*" [[package]] name = "types-protobuf" -version = "7.34.1.20260408" +version = "7.34.1.20260508" description = "Typing stubs for protobuf" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_protobuf-7.34.1.20260408-py3-none-any.whl", hash = "sha256:ebbcd4e27b145aef6a59bc0cb6c013b3528151c1ba5e7f7337aeee355d276a5e"}, - {file = "types_protobuf-7.34.1.20260408.tar.gz", hash = "sha256:e2c0a0430e08c75b52671a6f0035abfdcc791aad12af16274282de1b721758ab"}, + {file = "types_protobuf-7.34.1.20260508-py3-none-any.whl", hash = "sha256:a5d647381f8651bd505304ed1148b8a7b342781796e0f80e0284c774c2262a09"}, + {file = "types_protobuf-7.34.1.20260508.tar.gz", hash = "sha256:1c93e8c294281b76a5255fc21c747db0004694463ac6ea9866ee06da969fa555"}, ] [[package]] @@ -4727,14 +4728,14 @@ types-cffi = "*" [[package]] name = "types-python-dateutil" -version = "2.9.0.20260408" +version = "2.9.0.20260508" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_python_dateutil-2.9.0.20260408-py3-none-any.whl", hash = "sha256:473139d514a71c9d1fbd8bb328974bedcb1cc3dba57aad04ffa4157f483c216f"}, - {file = "types_python_dateutil-2.9.0.20260408.tar.gz", hash = "sha256:8b056ec01568674235f64ecbcef928972a5fac412f5aab09c516dfa2acfbb582"}, + {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"}, ] [[package]] @@ -4822,91 +4823,88 @@ typing-extensions = ">=4.12.0" [[package]] name = "ujson" -version = "5.12.0" +version = "5.12.1" 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.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504"}, - {file = "ujson-5.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa"}, - {file = "ujson-5.12.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09"}, - {file = "ujson-5.12.0-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26"}, - {file = "ujson-5.12.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87"}, - {file = "ujson-5.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50"}, - {file = "ujson-5.12.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d"}, - {file = "ujson-5.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be"}, - {file = "ujson-5.12.0-cp310-cp310-win32.whl", hash = "sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2"}, - {file = "ujson-5.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb"}, - {file = "ujson-5.12.0-cp310-cp310-win_arm64.whl", hash = "sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d"}, - {file = "ujson-5.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00"}, - {file = "ujson-5.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797"}, - {file = "ujson-5.12.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65"}, - {file = "ujson-5.12.0-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e"}, - {file = "ujson-5.12.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab"}, - {file = "ujson-5.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61"}, - {file = "ujson-5.12.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f"}, - {file = "ujson-5.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94"}, - {file = "ujson-5.12.0-cp311-cp311-win32.whl", hash = "sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb"}, - {file = "ujson-5.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161"}, - {file = "ujson-5.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4"}, - {file = "ujson-5.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a"}, - {file = "ujson-5.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052"}, - {file = "ujson-5.12.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57"}, - {file = "ujson-5.12.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2"}, - {file = "ujson-5.12.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827"}, - {file = "ujson-5.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb"}, - {file = "ujson-5.12.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84"}, - {file = "ujson-5.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759"}, - {file = "ujson-5.12.0-cp312-cp312-win32.whl", hash = "sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d"}, - {file = "ujson-5.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3"}, - {file = "ujson-5.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68"}, - {file = "ujson-5.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8"}, - {file = "ujson-5.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654"}, - {file = "ujson-5.12.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da"}, - {file = "ujson-5.12.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b"}, - {file = "ujson-5.12.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a"}, - {file = "ujson-5.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487"}, - {file = "ujson-5.12.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87"}, - {file = "ujson-5.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed"}, - {file = "ujson-5.12.0-cp313-cp313-win32.whl", hash = "sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc"}, - {file = "ujson-5.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2"}, - {file = "ujson-5.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6"}, - {file = "ujson-5.12.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef"}, - {file = "ujson-5.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9"}, - {file = "ujson-5.12.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c"}, - {file = "ujson-5.12.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc"}, - {file = "ujson-5.12.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961"}, - {file = "ujson-5.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6"}, - {file = "ujson-5.12.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad"}, - {file = "ujson-5.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4"}, - {file = "ujson-5.12.0-cp314-cp314-win32.whl", hash = "sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9"}, - {file = "ujson-5.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da"}, - {file = "ujson-5.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0"}, - {file = "ujson-5.12.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d"}, - {file = "ujson-5.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983"}, - {file = "ujson-5.12.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315"}, - {file = "ujson-5.12.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e"}, - {file = "ujson-5.12.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0"}, - {file = "ujson-5.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c"}, - {file = "ujson-5.12.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e"}, - {file = "ujson-5.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e"}, - {file = "ujson-5.12.0-cp314-cp314t-win32.whl", hash = "sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382"}, - {file = "ujson-5.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e"}, - {file = "ujson-5.12.0-cp314-cp314t-win_arm64.whl", hash = "sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd"}, - {file = "ujson-5.12.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c"}, - {file = "ujson-5.12.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d"}, - {file = "ujson-5.12.0-graalpy312-graalpy250_312_native-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b"}, - {file = "ujson-5.12.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3"}, - {file = "ujson-5.12.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5"}, - {file = "ujson-5.12.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927"}, - {file = "ujson-5.12.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da"}, - {file = "ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688"}, - {file = "ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235"}, - {file = "ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e"}, - {file = "ujson-5.12.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab"}, - {file = "ujson-5.12.0.tar.gz", hash = "sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4"}, + {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"}, ] [[package]] @@ -5189,4 +5187,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "f3a3c406f885fbf43aa21202c86dcc7da0e79933fbfd2a5d42d86ca8852dedeb" +content-hash = "288a8d6ec133dc1a48636d7368ad817917442ed0a7cc7de6ce9a785499f9e4ad" diff --git a/pyproject.toml b/pyproject.toml index 57aa680a030..9bd63bc709c 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.35" +ty = ">=0.0.23,<0.0.36" [tool.coverage.run] source = ["aws_lambda_powertools"] From e2612dca24eef5a1b23090eb31120b6e70c6e5a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 09:35:25 +0200 Subject: [PATCH 79/84] chore(deps): bump the github-actions group with 3 updates (#8221) Bumps the github-actions group with 3 updates: [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials), [actions/dependency-review-action](https://github.com/actions/dependency-review-action) and [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter). Updates `aws-actions/configure-aws-credentials` from 6.1.0 to 6.1.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/ec61189d14ec14c8efccab744f656cffd0e33f37...d979d5b3a71173a29b74b5b88418bfda9437d885) Updates `actions/dependency-review-action` from 4.9.0 to 5.0.0 - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/2031cfc080254a8a887f58cffee85186f0e49e48...a1d282b36b6f3519aa1f3fc636f609c47dddb294) Updates `release-drafter/release-drafter` from 7.2.1 to 7.3.0 - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/563bf132657a13ded0b01fcb723c5a58cdd824e2...c2e2804cc59f45f57076a99af580d0fedb697927) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 6.1.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/dependency-review-action dependency-version: 5.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.3.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 | 4 ++-- .github/workflows/dependency-review.yml | 2 +- .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/release-drafter.yml | 2 +- .github/workflows/reusable_deploy_v3_layer_stack.yml | 2 +- .github/workflows/reusable_deploy_v3_sar.yml | 4 ++-- .github/workflows/reusable_publish_docs.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- .github/workflows/update_ssm.yml | 2 +- 13 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/bootstrap_region.yml b/.github/workflows/bootstrap_region.yml index 7bbfab18d76..dc8c142efd5 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@828e78a26eee3554dc2e1d96048004548fbb169f - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 with: aws-region: ${{ inputs.region }} role-to-assume: ${{ secrets.REGION_IAM_ROLE }} @@ -96,7 +96,7 @@ jobs: steps: - id: credentials name: AWS Credentials - uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1 with: aws-region: us-east-1 role-to-assume: ${{ secrets.REGION_IAM_ROLE }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 86dc50dd0eb..60ce40982bf 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -22,4 +22,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 + uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 diff --git a/.github/workflows/layer_govcloud.yml b/.github/workflows/layer_govcloud.yml index 0ce1b7af356..9daf6725808 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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 6f7c6a94d38..1dc2f4242d2 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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 3cce653182e..004f9e091fb 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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 c1d72353898..d3973e8083d 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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 caceb773dc6..433ac84e357 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1 with: role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }} aws-region: ${{ matrix.region}} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 60d41a2a0ca..e08dd925efe 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@563bf132657a13ded0b01fcb723c5a58cdd824e2 # v7.2.1 + - uses: release-drafter/release-drafter@c2e2804cc59f45f57076a99af580d0fedb697927 # v7.3.0 diff --git a/.github/workflows/reusable_deploy_v3_layer_stack.yml b/.github/workflows/reusable_deploy_v3_layer_stack.yml index a2ef355989f..58b7650e3cb 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} diff --git a/.github/workflows/reusable_deploy_v3_sar.yml b/.github/workflows/reusable_deploy_v3_sar.yml index 67dcc7d44b7..3fc8cbc2fd4 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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 683992f4ac4..dd054e98639 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -68,7 +68,7 @@ jobs: env: BRANCH: ${{ inputs.git_ref }} - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.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 dea1cc9e065..d05239bf089 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -72,7 +72,7 @@ jobs: - name: Install dependencies run: make dev-quality-code - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1 with: role-to-assume: ${{ secrets.AWS_TEST_ROLE_ARN }} aws-region: ${{ env.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/update_ssm.yml b/.github/workflows/update_ssm.yml index 994f1fb7685..f290d9e560b 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@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0 + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets[format('{0}', steps.transform.outputs.CONVERTED_REGION)] }} From 7fc7b2f2ee063c51cb0b4fe0b501a005e1a31c0c Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Wed, 13 May 2026 05:18:04 -0400 Subject: [PATCH 80/84] fix(docs): update broken AWS Lambda Metadata Endpoint link (#8209) fix(docs): update broken AWS Lambda Metadata Endpoint link in metadata.md The link to AWS Lambda Metadata Endpoint (LMDS) documentation was pointing to an outdated URL that redirects to "What is AWS Lambda?" instead of the correct configuration page. Updated URL from: https://docs.aws.amazon.com/lambda/latest/dg/lambda-metadata-endpoint.html To: https://docs.aws.amazon.com/lambda/latest/dg/configuration-metadata-endpoint.html fixes #8068 Signed-off-by: hirenkumar-n-dholariya Co-authored-by: Leandro Damascena --- docs/utilities/metadata.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/metadata.md b/docs/utilities/metadata.md index b1154d4cecd..4959d81d8c7 100644 --- a/docs/utilities/metadata.md +++ b/docs/utilities/metadata.md @@ -6,7 +6,7 @@ status: new -The Metadata utility allows you to fetch data from the [AWS Lambda Metadata Endpoint (LMDS)](https://docs.aws.amazon.com/lambda/latest/dg/lambda-metadata-endpoint.html){target="_blank"}. This can be useful for retrieving information about the Lambda execution environment, such as the Availability Zone ID. +The Metadata utility allows you to fetch data from the [AWS Lambda Metadata Endpoint (LMDS)](https://docs.aws.amazon.com/lambda/latest/dg/configuration-metadata-endpoint.html){target="_blank"}. This can be useful for retrieving information about the Lambda execution environment, such as the Availability Zone ID. ## Key features From 1b8654f00e1e13ee53ecdb38341eceedba7bb8af Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 21 May 2026 10:28:54 -0700 Subject: [PATCH 81/84] chore(deps): consolidate all open Dependabot updates (#8241) * chore(deps-dev): bump the dev-dependencies group with 3 updates Bumps the dev-dependencies group with 3 updates: [coverage](https://github.com/coveragepy/coveragepy), [mypy](https://github.com/python/mypy) and [ruff](https://github.com/astral-sh/ruff). Updates `coverage` from 7.13.5 to 7.14.0 - [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.13.5...7.14.0) Updates `mypy` from 1.20.2 to 2.1.0 - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.20.2...v2.1.0) Updates `ruff` from 0.15.12 to 0.15.13 - [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.12...0.15.13) --- updated-dependencies: - dependency-name: coverage dependency-version: 7.14.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: mypy dependency-version: 2.1.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: ruff dependency-version: 0.15.13 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... 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.316 to 0.1.317. - [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/compare/v0.1.316...v0.1.317) --- updated-dependencies: - dependency-name: cdklabs-generative-ai-cdk-constructs dependency-version: 0.1.317 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump types-protobuf Bumps [types-protobuf](https://github.com/python/typeshed) from 7.34.1.20260508 to 7.34.1.20260518. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-protobuf dependency-version: 7.34.1.20260518 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps): bump pydantic-settings from 2.14.0 to 2.14.1 Bumps [pydantic-settings](https://github.com/pydantic/pydantic-settings) from 2.14.0 to 2.14.1. - [Release notes](https://github.com/pydantic/pydantic-settings/releases) - [Commits](https://github.com/pydantic/pydantic-settings/compare/v2.14.0...v2.14.1) --- updated-dependencies: - dependency-name: pydantic-settings dependency-version: 2.14.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump types-requests Bumps [types-requests](https://github.com/python/typeshed) from 2.33.0.20260408 to 2.33.0.20260518. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-version: 2.33.0.20260518 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * 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.1121.0 to 2.1122.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1122.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1122.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: aws-cdk ... Signed-off-by: dependabot[bot] * chore(deps): bump codecov/codecov-action in the github-actions group Bumps the github-actions group with 1 update: [codecov/codecov-action](https://github.com/codecov/codecov-action). Updates `codecov/codecov-action` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/57e3a136b779b570ffcdbf80b3bdc90e7fab3de2...e79a6962e0d4c0c17b229090214935d2e33f8354) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] * chore(deps): bump idna from 3.10 to 3.15 in /docs Bumps [idna](https://github.com/kjd/idna) from 3.10 to 3.15. - [Release notes](https://github.com/kjd/idna/releases) - [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md) - [Commits](https://github.com/kjd/idna/compare/v3.10...v3.15) --- updated-dependencies: - dependency-name: idna dependency-version: '3.15' dependency-type: indirect ... Signed-off-by: dependabot[bot] * chore(deps): bump pymdown-extensions from 10.16.1 to 10.21.3 in /docs Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.16.1 to 10.21.3. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.16.1...10.21.3) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: 10.21.3 dependency-type: indirect ... Signed-off-by: dependabot[bot] * chore(deps-dev): bump pymdown-extensions from 10.16.1 to 10.21.3 Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.16.1 to 10.21.3. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.16.1...10.21.3) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: 10.21.3 dependency-type: indirect ... Signed-off-by: dependabot[bot] * chore(deps): bump idna from 3.10 to 3.15 Bumps [idna](https://github.com/kjd/idna) from 3.10 to 3.15. - [Release notes](https://github.com/kjd/idna/releases) - [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md) - [Commits](https://github.com/kjd/idna/compare/v3.10...v3.15) --- updated-dependencies: - dependency-name: idna dependency-version: '3.15' dependency-type: indirect ... Signed-off-by: dependabot[bot] * chore: fix ruff lint errors after dependency updates Co-Authored-By: Claude Opus 4.6 * chore: fix mypy errors from stricter type checking in new version Update RedisClientProtocol.delete to use variadic *names parameter matching the actual redis-py signature. Add casts for _init_client returns and type annotation for _regex_cache. Co-Authored-By: Claude Opus 4.6 * empty --------- 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/quality_check.yml | 2 +- .../utilities/data_masking/provider/base.py | 2 +- .../idempotency/persistence/redis.py | 25 +- benchmark/src/instrumented/main.py | 7 +- benchmark/src/reference/main.py | 4 +- docs/requirements.txt | 12 +- ...g_started_with_idempotency_redis_client.py | 2 +- .../using_redis_client_with_local_certs.py | 2 +- layer_v3/app.py | 1 - layer_v3/layer/canary/app.py | 2 +- package-lock.json | 8 +- package.json | 2 +- parallel_run_e2e.py | 5 +- poetry.lock | 668 ++++++++++-------- pyproject.toml | 4 +- 15 files changed, 396 insertions(+), 350 deletions(-) diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml index 19dcb626f41..dfbc6528e0d 100644 --- a/.github/workflows/quality_check.yml +++ b/.github/workflows/quality_check.yml @@ -78,7 +78,7 @@ jobs: - name: Complexity baseline run: make complexity-baseline - name: Upload coverage to Codecov - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # 6.0.0 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # 6.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./coverage.xml diff --git a/aws_lambda_powertools/utilities/data_masking/provider/base.py b/aws_lambda_powertools/utilities/data_masking/provider/base.py index 7905fa57db8..d05e8bde1cf 100644 --- a/aws_lambda_powertools/utilities/data_masking/provider/base.py +++ b/aws_lambda_powertools/utilities/data_masking/provider/base.py @@ -11,7 +11,7 @@ from collections.abc import Callable PRESERVE_CHARS = set("-_. ") -_regex_cache = {} +_regex_cache: dict[str, re.Pattern[str]] = {} JSON_DUMPS_CALL = functools.partial(json.dumps, ensure_ascii=False) diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py index 9327c33bda7..82a44e079de 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py @@ -5,7 +5,7 @@ import logging from contextlib import contextmanager from datetime import timedelta -from typing import Any, Literal, Protocol +from typing import Any, Literal, Protocol, cast import redis from typing_extensions import TypeAlias, deprecated @@ -76,7 +76,7 @@ def set( # noqa ) -> bool | None: raise NotImplementedError - def delete(self, keys: bytes | str | memoryview) -> Any: + def delete(self, *names: bytes | str | memoryview) -> Any: raise NotImplementedError @@ -185,7 +185,7 @@ def _init_client(self) -> RedisClientProtocol: try: if self.url: logger.debug(f"Using URL format to connect to Cache: {self.host}") - return client.from_url(url=self.url) + return cast(RedisClientProtocol, client.from_url(url=self.url)) else: # Cache in cluster mode doesn't support db parameter extra_param_connection: dict[str, Any] = {} @@ -193,14 +193,17 @@ def _init_client(self) -> RedisClientProtocol: extra_param_connection = {"db": self.db_index} logger.debug(f"Using arguments to connect to Cache: {self.host}") - return client( - host=self.host, - port=self.port, - username=self.username, - password=self.password, - decode_responses=True, - ssl=self.ssl, - **extra_param_connection, + return cast( + RedisClientProtocol, + client( + host=self.host, + port=self.port, + username=self.username, + password=self.password, + decode_responses=True, + ssl=self.ssl, + **extra_param_connection, + ), ) except redis.exceptions.ConnectionError as exc: logger.debug(f"Cannot connect to Cache endpoint: {self.host}") diff --git a/benchmark/src/instrumented/main.py b/benchmark/src/instrumented/main.py index e26d9326c26..7632e4f608c 100644 --- a/benchmark/src/instrumented/main.py +++ b/benchmark/src/instrumented/main.py @@ -1,5 +1,4 @@ -from aws_lambda_powertools import (Logger, Metrics, Tracer) - +from aws_lambda_powertools import Logger, Metrics, Tracer # Initialize core utilities logger = Logger() @@ -13,5 +12,5 @@ @tracer.capture_lambda_handler def handler(event, context): return { - "message": "success" - } \ No newline at end of file + "message": "success", + } diff --git a/benchmark/src/reference/main.py b/benchmark/src/reference/main.py index 4b5fb3900a7..3127cfb7a29 100644 --- a/benchmark/src/reference/main.py +++ b/benchmark/src/reference/main.py @@ -1,4 +1,4 @@ def handler(event, context): return { - "message": "success" - } \ No newline at end of file + "message": "success", + } diff --git a/docs/requirements.txt b/docs/requirements.txt index 04693e95a0e..a7b731a7d5a 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -147,9 +147,9 @@ griffe==1.13.0 \ --hash=sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0 \ --hash=sha256:470fde5b735625ac0a36296cd194617f039e9e83e301fcbd493e2b58382d0559 # via mkdocstrings-python -idna==3.10 \ - --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ - --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 +idna==3.15 \ + --hash=sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8 \ + --hash=sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc # via requests jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -324,9 +324,9 @@ pygments==2.19.2 \ --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b # via mkdocs-material -pymdown-extensions==10.16.1 \ - --hash=sha256:aace82bcccba3efc03e25d584e6a22d27a8e17caa3f4dd9f207e49b787aa9a91 \ - --hash=sha256:d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d +pymdown-extensions==10.21.3 \ + --hash=sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354 \ + --hash=sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6 # via # mkdocs-material # mkdocstrings diff --git a/examples/idempotency/src/getting_started_with_idempotency_redis_client.py b/examples/idempotency/src/getting_started_with_idempotency_redis_client.py index ac2a20587e8..91b6f5b47c4 100644 --- a/examples/idempotency/src/getting_started_with_idempotency_redis_client.py +++ b/examples/idempotency/src/getting_started_with_idempotency_redis_client.py @@ -21,7 +21,7 @@ max_connections=1000, ) -persistence_layer = CachePersistenceLayer(client=client) +persistence_layer = CachePersistenceLayer(client=client) # type: ignore[arg-type] @dataclass diff --git a/examples/idempotency/src/using_redis_client_with_local_certs.py b/examples/idempotency/src/using_redis_client_with_local_certs.py index 844f5b37e7d..b58571e3bbc 100644 --- a/examples/idempotency/src/using_redis_client_with_local_certs.py +++ b/examples/idempotency/src/using_redis_client_with_local_certs.py @@ -27,7 +27,7 @@ ssl_ca_certs=f"{abs_lambda_path()}/certs/cache_ca.pem", # (4)! ) -persistence_layer = CachePersistenceLayer(client=redis_client) +persistence_layer = CachePersistenceLayer(client=redis_client) # type: ignore[arg-type] config = IdempotencyConfig( expires_after_seconds=2 * 60, # 2 minutes ) diff --git a/layer_v3/app.py b/layer_v3/app.py index 25ed2b116ce..b488f640324 100644 --- a/layer_v3/app.py +++ b/layer_v3/app.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import aws_cdk as cdk - from layer.canary_stack import CanaryStack from layer.layer_stack import LayerStack diff --git a/layer_v3/layer/canary/app.py b/layer_v3/layer/canary/app.py index 667d8215636..135356ca730 100644 --- a/layer_v3/layer/canary/app.py +++ b/layer_v3/layer/canary/app.py @@ -66,7 +66,7 @@ def on_event(event, context): def on_create(event): props = event["ResourceProperties"] - logger.info("create new resource with properties %s" % props) + logger.info(f"create new resource with properties {props}") handler(event) diff --git a/package-lock.json b/package-lock.json index e82814ea9ec..a5282255e0a 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.1121.0" + "aws-cdk": "^2.1122.0" } }, "node_modules/aws-cdk": { - "version": "2.1121.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1121.0.tgz", - "integrity": "sha512-cG7CHt/SytYTfwrK+BUNQpqmS1dwhjt8z6ExKL6GK4n+8/6ZCwFzxlZWA/jUd2+Y9xPc+Q8cLKfMqGmgxEXbkg==", + "version": "2.1122.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1122.0.tgz", + "integrity": "sha512-AI2Ks9qioWLvBPD4IoEtTet3wUG/o/q6U3WR3VCQKH5sNYLLPALo8o9sermNpMnfd1OQkqhL20tp4cEyojrIZg==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 16ea39cd12e..1abc4ac1895 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.1121.0" + "aws-cdk": "^2.1122.0" } } diff --git a/parallel_run_e2e.py b/parallel_run_e2e.py index 1146f66931e..7a56c885705 100755 --- a/parallel_run_e2e.py +++ b/parallel_run_e2e.py @@ -1,4 +1,5 @@ -""" Calculate how many parallel workers are needed to complete E2E infrastructure jobs across available CPU Cores """ +"""Calculate how many parallel workers are needed to complete E2E infrastructure jobs across available CPU Cores""" + import subprocess import sys from pathlib import Path @@ -9,7 +10,7 @@ def main(): workers = len(list(features)) - 1 command = f"poetry run pytest -n {workers} -o log_cli=true tests/e2e" - result = subprocess.run(command.split(), shell=False) + result = subprocess.run(command.split(), shell=False, check=False) sys.exit(result.returncode) diff --git a/poetry.lock b/poetry.lock index f5b5a5617af..7d630bd4586 100644 --- a/poetry.lock +++ b/poetry.lock @@ -49,6 +49,49 @@ files = [ [package.extras] test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] +[[package]] +name = "ast-serialize" +version = "0.5.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"}, +] + [[package]] name = "async-timeout" version = "5.0.1" @@ -224,39 +267,39 @@ typeguard = "2.13.3" [[package]] name = "aws-cdk-cloud-assembly-schema" -version = "53.18.0" +version = "53.24.0" description = "Schema for the protocol between CDK framework and CDK CLI" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_cloud_assembly_schema-53.18.0-py3-none-any.whl", hash = "sha256:291a9645d70bb1e2fd73fb8e58fd48503353751b8330d8f2d72dafc13bdf84ac"}, - {file = "aws_cdk_cloud_assembly_schema-53.18.0.tar.gz", hash = "sha256:bb377de485f5214a47c78268b2a985332c83d7fd5c06922d1a9538ba31320afc"}, + {file = "aws_cdk_cloud_assembly_schema-53.24.0-py3-none-any.whl", hash = "sha256:360c4804f3073601ac320d1773432bc45b34201d7c8fb85aff7ed536801efb0c"}, + {file = "aws_cdk_cloud_assembly_schema-53.24.0.tar.gz", hash = "sha256:f999f4c777deaca6631c61993bf5583022ff57c3a94a65930e2fc6b68cb7c407"}, ] [package.dependencies] -jsii = ">=1.128.0,<2.0.0" +jsii = ">=1.129.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" [[package]] name = "aws-cdk-lib" -version = "2.253.1" +version = "2.254.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.253.1-py3-none-any.whl", hash = "sha256:03a6f5080978f9e3576f490d06fbd1f41f159280d34dbca50721de4a19694136"}, - {file = "aws_cdk_lib-2.253.1.tar.gz", hash = "sha256:df03363cdaef4d2d7bac368b2d5d2bf4209921d21096cd5f8e5889347fee4793"}, + {file = "aws_cdk_lib-2.254.0-py3-none-any.whl", hash = "sha256:626095eaa742e0b9d894c3a1bf06a6e7d1245a986165a72408871d41886c6d07"}, + {file = "aws_cdk_lib-2.254.0.tar.gz", hash = "sha256:ddbef134cad91f8985444f77f052f0337af5f132101ad7aea2215b4775ff7828"}, ] [package.dependencies] "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" +"aws-cdk.cloud-assembly-schema" = ">=53.21.0,<54.0.0" constructs = ">=10.5.0,<11.0.0" -jsii = ">=1.128.0,<2.0.0" +jsii = ">=1.129.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" @@ -988,40 +1031,40 @@ ujson = ["ujson (>=5.10.0)"] [[package]] name = "cdk-nag" -version = "2.37.55" +version = "2.38.2" description = "Check CDK v2 applications for best practices using a combination on available rule packs." optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "cdk_nag-2.37.55-py3-none-any.whl", hash = "sha256:bf83bcdeb98ac20bb813cac291af121d91c5a296fa815e01f93886b4f8b38845"}, - {file = "cdk_nag-2.37.55.tar.gz", hash = "sha256:e9dc517070ef5a19deef95e79731e5624bd86cd07b56d210380408ea1314e47b"}, + {file = "cdk_nag-2.38.2-py3-none-any.whl", hash = "sha256:d37f18ae9450f401bcc55d5d82138beee561486806579849cb9be25ff7565904"}, + {file = "cdk_nag-2.38.2.tar.gz", hash = "sha256:a4d419062ea4d64c2892942214b9184b124eb2bc36d087982007b3455e1ac443"}, ] [package.dependencies] aws-cdk-lib = ">=2.176.0,<3.0.0" -constructs = ">=10.0.5,<11.0.0" -jsii = ">=1.116.0,<2.0.0" +constructs = ">=10.5.1,<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 = "cdklabs-generative-ai-cdk-constructs" -version = "0.1.316" +version = "0.1.317" description = "AWS Generative AI CDK Constructs is a library for well-architected generative AI patterns." optional = false -python-versions = "~=3.9" +python-versions = "~=3.10" groups = ["dev"] files = [ - {file = "cdklabs_generative_ai_cdk_constructs-0.1.316-py3-none-any.whl", hash = "sha256:925926882b2978156918536460bbfa03ab1ed0b7641ff0982d7370c8a3f81f83"}, - {file = "cdklabs_generative_ai_cdk_constructs-0.1.316.tar.gz", hash = "sha256:8347018014753f5c99a14f93ea05756ded83f05286eef6fc712b492364fe173b"}, + {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"}, ] [package.dependencies] -aws-cdk-lib = ">=2.233.0,<3.0.0" -cdk-nag = ">=2.37.55,<3.0.0" -constructs = ">=10.3.0,<11.0.0" -jsii = ">=1.127.0,<2.0.0" +aws-cdk-lib = ">=2.254.0,<3.0.0" +cdk-nag = ">=2.38.2,<3.0.0" +constructs = ">=10.6.0,<11.0.0" +jsii = ">=1.130.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" @@ -1332,135 +1375,135 @@ development = ["black", "flake8", "mypy", "pytest", "types-colorama"] [[package]] name = "constructs" -version = "10.5.1" +version = "10.6.0" description = "A programming model for software-defined state" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "constructs-10.5.1-py3-none-any.whl", hash = "sha256:fc5c14f6b2770c8542a43e298aa29b63dee4b18701763e8c0fdce202624c3a7c"}, - {file = "constructs-10.5.1.tar.gz", hash = "sha256:c0e90bb2b9c2782f292017820b91714321cb78393c8965c9362b0b624bfaf23b"}, + {file = "constructs-10.6.0-py3-none-any.whl", hash = "sha256:ad4ffabdb53c17cde00fb94e441a1ba9fddac57c92ad49d263f8dbd416cec513"}, + {file = "constructs-10.6.0.tar.gz", hash = "sha256:bc55d1d390142424861e5ff5c6b8c243c4bae18fe7302e0939c2003f329ba365"}, ] [package.dependencies] -jsii = ">=1.126.0,<2.0.0" +jsii = ">=1.127.0,<2.0.0" publication = ">=0.0.3" typeguard = "2.13.3" [[package]] name = "coverage" -version = "7.13.5" +version = "7.14.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5"}, - {file = "coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf"}, - {file = "coverage-7.13.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8"}, - {file = "coverage-7.13.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4"}, - {file = "coverage-7.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d"}, - {file = "coverage-7.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930"}, - {file = "coverage-7.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d"}, - {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40"}, - {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878"}, - {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400"}, - {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0"}, - {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0"}, - {file = "coverage-7.13.5-cp310-cp310-win32.whl", hash = "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58"}, - {file = "coverage-7.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e"}, - {file = "coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d"}, - {file = "coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587"}, - {file = "coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642"}, - {file = "coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b"}, - {file = "coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686"}, - {file = "coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743"}, - {file = "coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75"}, - {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209"}, - {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a"}, - {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e"}, - {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd"}, - {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8"}, - {file = "coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf"}, - {file = "coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9"}, - {file = "coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028"}, - {file = "coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01"}, - {file = "coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422"}, - {file = "coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f"}, - {file = "coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5"}, - {file = "coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376"}, - {file = "coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256"}, - {file = "coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c"}, - {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5"}, - {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09"}, - {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9"}, - {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf"}, - {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c"}, - {file = "coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf"}, - {file = "coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810"}, - {file = "coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de"}, - {file = "coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1"}, - {file = "coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3"}, - {file = "coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26"}, - {file = "coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3"}, - {file = "coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b"}, - {file = "coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a"}, - {file = "coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969"}, - {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161"}, - {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15"}, - {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1"}, - {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6"}, - {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17"}, - {file = "coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85"}, - {file = "coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b"}, - {file = "coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664"}, - {file = "coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d"}, - {file = "coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0"}, - {file = "coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806"}, - {file = "coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3"}, - {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9"}, - {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd"}, - {file = "coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606"}, - {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e"}, - {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0"}, - {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87"}, - {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479"}, - {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2"}, - {file = "coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a"}, - {file = "coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819"}, - {file = "coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911"}, - {file = "coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f"}, - {file = "coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e"}, - {file = "coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a"}, - {file = "coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510"}, - {file = "coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247"}, - {file = "coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6"}, - {file = "coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0"}, - {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882"}, - {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740"}, - {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16"}, - {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0"}, - {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0"}, - {file = "coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc"}, - {file = "coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633"}, - {file = "coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8"}, - {file = "coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b"}, - {file = "coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c"}, - {file = "coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9"}, - {file = "coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29"}, - {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607"}, - {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90"}, - {file = "coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3"}, - {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab"}, - {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562"}, - {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2"}, - {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea"}, - {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a"}, - {file = "coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215"}, - {file = "coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43"}, - {file = "coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45"}, - {file = "coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61"}, - {file = "coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179"}, + {file = "coverage-7.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84c32d90bf4537f0e7b4dec9aaa9a938fb8205136b9d2ecf4d7629d5262dc075"}, + {file = "coverage-7.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7c843572c605ab51cfdb5c6b5f2586e2a8467c0d28eca4bdef4ec70c5fecbd82"}, + {file = "coverage-7.14.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0c451757d3fa2603354fdc789b5e58a0e327a117c370a40e3476ba4eabab228c"}, + {file = "coverage-7.14.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3fd43f0616e765ab78d069cf8358def7363957a45cee446d65c502dcfeea7893"}, + {file = "coverage-7.14.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:731e535b1498b27d13594a0527a79b0510867b0ad891532be41cb883f2128e20"}, + {file = "coverage-7.14.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c7492f2d493b976941c7ca050f273cbda2f43c381124f7586a3e3c16d1804fec"}, + {file = "coverage-7.14.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc38367eaa2abb1b766ac333142bce7655335a73537f5c8b75aaa89c2b987757"}, + {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0a951308cde22cf77f953955a754d04dccb57fe3bb8e345d685778ed9fc1632a"}, + {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fab3877e4ebb06bd9d4d4d00ee53309ee5478e66873c66a382272e3ee33eb7ea"}, + {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:b812eb847b19876ebf33fb6c4f11819af05ab6050b0bfa1bc53412ae81779adb"}, + {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d9c8ef6ed820c433de075657d72dda1f89a2984955e58b8a75feb3f184250218"}, + {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d128b1bba9361fbaaf6a19e179e6cfd6a9103ce0c0555876f72780acc93efd85"}, + {file = "coverage-7.14.0-cp310-cp310-win32.whl", hash = "sha256:65f267ca1370726ec2c1aa38bbe4df9a71a740f22878d2d4bf59d71a4cd8d323"}, + {file = "coverage-7.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:b34ece8065914f938ed7f2c5872bb865336977a52919149846eac3744327267a"}, + {file = "coverage-7.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a78e2a9d9c5e3b8d4ab9b9d28c985ea66fced0a7d7c2aec1f216e03a2011480"}, + {file = "coverage-7.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1816c505187592dcd1c5a5f226601a549f70365fbd00930ac88b0c225b76bb4"}, + {file = "coverage-7.14.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d8e1762f0e9cbc26ec315471e7b47855218e833cd5a032d706fbf43845d878c7"}, + {file = "coverage-7.14.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9336e23e8bb3a3925398261385e2a1533957d3e760e91070dcb0e98bfa514eed"}, + {file = "coverage-7.14.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd1169b2230f9cbe9c638ba38022ed7a2b1e641cc07f7cea0365e4be2a74980"}, + {file = "coverage-7.14.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d1bb3543b58fea74d2cd1abc4054cc927e4724687cb4560cd2ed88d2c7d820c0"}, + {file = "coverage-7.14.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a93bac2cb577ef60074999ed56d8a1535894398e2ed920d4185c3ec0c8864742"}, + {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5904abf7e18cddc463219b17552229650c6b79e061d31a1059283051169cf7d5"}, + {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:741f57cddc9004a8c81b084660215f33a6b597dbe62c31386b983ee26310e327"}, + {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:664123feb0929d7affc135717dbd70d61d98688a08ab1e5ba464739620c6252d"}, + {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:c83d2399a51bbec8429266905d33616f04bc5726b1138c35844d5fcd896b2e20"}, + {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb2e855b87321259a037429288ae85216d191c74de3e79bf57cd2bc0761992c"}, + {file = "coverage-7.14.0-cp311-cp311-win32.whl", hash = "sha256:731dc15b385ac52289743d476245b61e1a2927e803bef655b52bc3b2a75a21f3"}, + {file = "coverage-7.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:bfb0ed8ec5d25e93face268115d7964db9df8b9aae8edcde9ec6b16c726a7cc1"}, + {file = "coverage-7.14.0-cp311-cp311-win_arm64.whl", hash = "sha256:7ebb1c6df9f78046a1b1e0a89674cd4bf73b7c648914eebcf976a57fd99a5627"}, + {file = "coverage-7.14.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7ffd19fc8aed057fd686a17a4935eef5f9859d69208f96310e893e64b9b6ccf5"}, + {file = "coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:829994cfe1aeb773ca27bf246d4badc1e764893e3bfb98fff820fcecd1ca4662"}, + {file = "coverage-7.14.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b4f07cf7edcb7ec39431a5074d7ea83b29a9f71fcfc494f0f40af4e65180420f"}, + {file = "coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ca3d9cf2c32b521bd9518385608787fa86f38daf993695307531822c3430ed67"}, + {file = "coverage-7.14.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92af52828e7f29d827346b0294e5a0853fa206db77db0395b282918d41e28db9"}, + {file = "coverage-7.14.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7b2bb6c9d7e769360d0f20a0f219603fd64f0c8f97de17ab25853261602be0fb"}, + {file = "coverage-7.14.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1c9ed6ef99f88fb8c14aa8e2bf8eb0fe55fa2edfea68f8675d78741df1a5ac0e"}, + {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8231ade007f37959fbf58acc677f26b922c02eda6f0428ea307da0fd39681bf3"}, + {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d8b013632cc1ce1d09dbe4f32667b4d320ec2f54fc326ebeffcd0b0bcc2bb6c4"}, + {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1733198802d71ec4c524f322e2867ee05c62e9e75df86bdca545407a221827d1"}, + {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:72a305291fa8ee01332f1aaf38b348ca34097f6aa0b0ef627eef2837e57bbba5"}, + {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcaba850dd317c65423a9d63d88f9573c53b00354d6dd95724576cc98a131595"}, + {file = "coverage-7.14.0-cp312-cp312-win32.whl", hash = "sha256:5ac83957a80d0701310e96d8bec68cdcf4f90a7674b7d13f15a344315b41ab27"}, + {file = "coverage-7.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:70390b0da32cb90b501953716302906e8bcce087cb283e70d8c97729f22e92b2"}, + {file = "coverage-7.14.0-cp312-cp312-win_arm64.whl", hash = "sha256:91b993743d959b8be85b4abf9d5478216a69329c321efe5be0433c1a841d691d"}, + {file = "coverage-7.14.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f2bbb8254370eb4c628ff3d6fa8a7f74ddc40565394d4f7ab791d1fe568e37ef"}, + {file = "coverage-7.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:23b81107f46d3f21d0cbce30664fcec0f5d9f585638a67081750f99738f6bf66"}, + {file = "coverage-7.14.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:22a7e06a5f11a757cdfe79018e9095f9f69ae283c5cd8123774c788deec8717b"}, + {file = "coverage-7.14.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9d1aa57a1dc8e05bdc42e81c5d671d849577aeedf279f4c449d6d286f9ed88ca"}, + {file = "coverage-7.14.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90c1a51bcfddf645b3bb7ec333d9e94393a8e94f55642380fa8a9a5a9e636cb7"}, + {file = "coverage-7.14.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a841fae2fadcae4f438d43b6ccc4aac2ad609f47cdb6cfdce60cbb3fe5ca7bc2"}, + {file = "coverage-7.14.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c79d2319cabef1fe8e86df73371126931550804738f78ad7d31e3aad85a67367"}, + {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1b23b0c6f0b1db6ad769b7050c8b641c0bf215ded26c1816955b17b7f26edfa9"}, + {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:55d3089079ce181a4566b1065ab28d2575eb76d8ac8f81f4fcda2bf037fee087"}, + {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:49c005cba1e2f9677fb2845dcdf9a2e72a52a17d63e8231aaaae35d9f50215ef"}, + {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:9117377b823daa28aa8635fbb08cda1cd6be3d7143257345459559aeef852d52"}, + {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7b79d646cf46d5cf9a9f40281d4441df5849e445726e369006d2b117710b33fe"}, + {file = "coverage-7.14.0-cp313-cp313-win32.whl", hash = "sha256:fb609b3658479e33f9516d46f1a89dbb9b6c261366e3a11844a96ec487533dae"}, + {file = "coverage-7.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:0773d8329cf32b6fd222e4b52622c61fe8d503eb966cfc8d3c3c10c96266d50e"}, + {file = "coverage-7.14.0-cp313-cp313-win_arm64.whl", hash = "sha256:b4e26a0f1b696faf283bffe5b8569e44e336c582439df5d53281ab89ee0cba96"}, + {file = "coverage-7.14.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:953f521ca9445300397e65fda3dca58b2dbd68fee983777420b57ac3c77e9f90"}, + {file = "coverage-7.14.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:98af83fd65ae24b1fdd03aaead967a9f523bcd2f1aab2d4f3ffda65bb568a6f1"}, + {file = "coverage-7.14.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:668b92e6958c4db7cf92e81caac328dfbbdbb215db2850ad28f0cbe1eea0bfbd"}, + {file = "coverage-7.14.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9fbd898551762dea00d3fef2b1c4f99afd2c6a3ff952ea07d60a9bd5ed4f34bc"}, + {file = "coverage-7.14.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:68af363c07ecd8d4b7d4043d85cb376d7d227eceb54e5323ee45da73dbd3e426"}, + {file = "coverage-7.14.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6e57054a583da8ac55edf24117ea4c9133032cfc4cf72aa2d48c1e5d4b52f899"}, + {file = "coverage-7.14.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc3499459bbcdd51a65b64c35ab7ed2764eaf3cba826e0df3f1d7fe2e102b70b"}, + {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:45899ec2138a4346ed34d601dedf5076fb74edf2d1dd9dc76a78e82397edee90"}, + {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8767486808c436f05b23ab98eb963fb29185e32a9357a166971685cb3459900f"}, + {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:a3b5ddfd6aa7ddad53ee3edb231e88a2151507a43229b7d71b953916deca127d"}, + {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:63df0fe568e698e1045792399f8ab6da3a6c2dce3182813fb92afa2641087b47"}, + {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:827d6397dbd95144939b18f89edf31f63e1f99633e8d5f32f22ba8bdda567477"}, + {file = "coverage-7.14.0-cp313-cp313t-win32.whl", hash = "sha256:7bf43e000d24012599b879791cff41589af90674722421ef11b11a5431920bab"}, + {file = "coverage-7.14.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3f5549365af25d770e06b1f8f5682d9a5637d06eb494db91c6fa75d3950cc917"}, + {file = "coverage-7.14.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6d160217ec6fe890f16ad3a9531761589443749e448f91986c972714fad361c8"}, + {file = "coverage-7.14.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9aed9fa983514ca032790f3fe0d1c0e42ca7e16b42432af1706b50a9a46bef5d"}, + {file = "coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ba3b8390db29296dbbf49e91b6fe08f990743a90c8f447ba4c2ffc29670dfa63"}, + {file = "coverage-7.14.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3a5d8e876dfa2f102e970b183863d6dedd023d3c0eeca1fe7a9787bc5f28b212"}, + {file = "coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ebb8f4614a3787d567e610bbfdf96a4798dd69a1afb1bd8ad228d4111fe6ff3"}, + {file = "coverage-7.14.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b9bf47223dd8db3d4c4b2e443b02bace480d428f0822c3f991600448a176c97"}, + {file = "coverage-7.14.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3485a836550b303d006d57cc06e3d5afaabc642c77050b7c985a97b13e3776b8"}, + {file = "coverage-7.14.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3e7e88110bae996d199d1693ca8ec3fd52441d426401ae963437598667b4c5eb"}, + {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:15228a6800ce7bdf1b74800595e56db7138cecb338fdbf044806e10dcf182dfe"}, + {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9d26ac7f5398bafc5b57421ad994e8a4749e8a7a0e62d05ec7d53014d5963bfa"}, + {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb73254ff43c911c967a899e1359bc5049b4b115d6e8fbdde4937d0a2246cd5"}, + {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:454a380af72c6adada298ed270d38c7a391288198dbfb8467f786f588751a90c"}, + {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:65c86fb646d2bd2972e96bd1a8b45817ed907cee68655d6295fe7ec031d04cca"}, + {file = "coverage-7.14.0-cp314-cp314-win32.whl", hash = "sha256:6a6516b02a6101398e19a3f44820f69bab2590697f7def4331f668b14adaf828"}, + {file = "coverage-7.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:45e0f79d8351fa76e256716df91eab12890d32678b9590df7ae1042e4bd4cf5d"}, + {file = "coverage-7.14.0-cp314-cp314-win_arm64.whl", hash = "sha256:4b899594a8b2d81e5cc064a0d7f9cac2081fed91049456cae7676787e41549c9"}, + {file = "coverage-7.14.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f580f8c80acd94ac72e863efe2cab791d8c38d153e0b463b92dfa000d5c84cd1"}, + {file = "coverage-7.14.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a2bd259c442cd43c49b30fbafc51776eb19ea396faf159d26a83e6a0a5f13b0c"}, + {file = "coverage-7.14.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a706b908dfa85538863504c624b237a3cc34232bf403c057414ebfdb3b4d9f84"}, + {file = "coverage-7.14.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7333cd944ee4393b9b3d3c1b598c936d4fc8d70573a4c7dacfec5590dd50e436"}, + {file = "coverage-7.14.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f162bc9a15b82d947b02651b0c7e1609d6f7a8735ca330cfadec8481dd97d5a"}, + {file = "coverage-7.14.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:362cb78e01a5dc82009d88004cf60f2e6b6d6fcbfdec05b05af73b0abf40118f"}, + {file = "coverage-7.14.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:acebd068fca5512c3a6fde9c045f901613478781a73f0e82b307b214daef23fb"}, + {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:29fe3da551dface75deb2ccbf87b6b66e2e7ef38f6d89050b428be94afff3490"}, + {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b4cc4fce8672fffcb09b0eafc167b396b3ba53c4a7230f54b7aaffbf6c835fa9"}, + {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5d4a51aad8ba8bdcd2b8bd8f03d4aca19693fa2327a3470e4718a25b03481020"}, + {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9f323af3e1e4f68b60b7b247e37b8515563a61375518fa59de1af48ba28a3db6"}, + {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1a0abc7342ea9711c469dd8b821c6c311e6bc6aac1442e5fbd6b27fae0a8f3db"}, + {file = "coverage-7.14.0-cp314-cp314t-win32.whl", hash = "sha256:a9f864ef57b7172e2db87a096642dd51e179e085ab6b2c371c29e885f65c8fb2"}, + {file = "coverage-7.14.0-cp314-cp314t-win_amd64.whl", hash = "sha256:29943e552fdc08e082eb51400fb2f58e118a83b5542bd06531214e084399b644"}, + {file = "coverage-7.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:742a73ea621953b012f2c4c2219b512180dd84489acf5b1596b0aafc55b9100b"}, + {file = "coverage-7.14.0-py3-none-any.whl", hash = "sha256:8de5b61163aee3d05c8a2beab6f47913df7981dad1baf82c414d99158c286ab1"}, + {file = "coverage-7.14.0.tar.gz", hash = "sha256:057a6af2f160a85384cde4ab36f0d2777bae1057bae255f95413cdd382aa5c74"}, ] [package.dependencies] @@ -2054,18 +2097,18 @@ parser = ["pyhcl (>=0.4.4,<0.5.0)"] [[package]] name = "idna" -version = "3.11" +version = "3.15" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, - {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, + {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, + {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, ] [package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "ijson" @@ -2276,14 +2319,14 @@ files = [ [[package]] name = "jsii" -version = "1.128.0" +version = "1.130.0" description = "Python client for jsii runtime" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "jsii-1.128.0-py3-none-any.whl", hash = "sha256:25912f66516c08c21dfcd350c9efd4c71548a98fd1af61ed08e73d99a73e0af0"}, - {file = "jsii-1.128.0.tar.gz", hash = "sha256:05f21e1c16e899cd65db27e54c9379b561cf368c6d670b60ea012bffa801b6d7"}, + {file = "jsii-1.130.0-py3-none-any.whl", hash = "sha256:ce50e11ea588fe6b2d0766d90edaf4c78b9e97e2e1f075fbd8bc29349c6503c8"}, + {file = "jsii-1.130.0.tar.gz", hash = "sha256:7436ae382e2de27970b34a4ccfef953a45980c5070241c1bd610bf3af68a2d6b"}, ] [package.dependencies] @@ -2374,103 +2417,103 @@ referencing = ">=0.31.0" [[package]] name = "librt" -version = "0.8.1" +version = "0.11.0" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc"}, - {file = "librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7"}, - {file = "librt-0.8.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6"}, - {file = "librt-0.8.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0"}, - {file = "librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b"}, - {file = "librt-0.8.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891"}, - {file = "librt-0.8.1-cp310-cp310-win32.whl", hash = "sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7"}, - {file = "librt-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2"}, - {file = "librt-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd"}, - {file = "librt-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965"}, - {file = "librt-0.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da"}, - {file = "librt-0.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0"}, - {file = "librt-0.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e"}, - {file = "librt-0.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe"}, - {file = "librt-0.8.1-cp311-cp311-win32.whl", hash = "sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb"}, - {file = "librt-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b"}, - {file = "librt-0.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9"}, - {file = "librt-0.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a"}, - {file = "librt-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9"}, - {file = "librt-0.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb"}, - {file = "librt-0.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d"}, - {file = "librt-0.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7"}, - {file = "librt-0.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0"}, - {file = "librt-0.8.1-cp312-cp312-win32.whl", hash = "sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a"}, - {file = "librt-0.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444"}, - {file = "librt-0.8.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d"}, - {file = "librt-0.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35"}, - {file = "librt-0.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583"}, - {file = "librt-0.8.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c"}, - {file = "librt-0.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04"}, - {file = "librt-0.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363"}, - {file = "librt-0.8.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d"}, - {file = "librt-0.8.1-cp313-cp313-win32.whl", hash = "sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a"}, - {file = "librt-0.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79"}, - {file = "librt-0.8.1-cp313-cp313-win_arm64.whl", hash = "sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0"}, - {file = "librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f"}, - {file = "librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c"}, - {file = "librt-0.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc"}, - {file = "librt-0.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c"}, - {file = "librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3"}, - {file = "librt-0.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78"}, - {file = "librt-0.8.1-cp314-cp314-win32.whl", hash = "sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023"}, - {file = "librt-0.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730"}, - {file = "librt-0.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3"}, - {file = "librt-0.8.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1"}, - {file = "librt-0.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994"}, - {file = "librt-0.8.1-cp314-cp314t-win32.whl", hash = "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a"}, - {file = "librt-0.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4"}, - {file = "librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61"}, - {file = "librt-0.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac"}, - {file = "librt-0.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed"}, - {file = "librt-0.8.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd"}, - {file = "librt-0.8.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851"}, - {file = "librt-0.8.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128"}, - {file = "librt-0.8.1-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed"}, - {file = "librt-0.8.1-cp39-cp39-win32.whl", hash = "sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc"}, - {file = "librt-0.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7"}, - {file = "librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73"}, + {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"}, ] [[package]] @@ -2918,60 +2961,61 @@ dill = ">=0.4.1" [[package]] name = "mypy" -version = "1.20.2" +version = "2.1.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mypy-1.20.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cf5a4db6dca263010e2c7bff081c89383c72d187ba2cf4c44759aac970e2f0c4"}, - {file = "mypy-1.20.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b0e817b518bff7facd7f85ea05b643ad8bdcce684cf29784987b0a7c8e1f997"}, - {file = "mypy-1.20.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97d7b9a485b40f8ca425460e89bf1da2814625b2da627c0dcc6aa46c92631d14"}, - {file = "mypy-1.20.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e1c12f6d2db3d78b909b5f77513c11eb7f2dd2782b96a3ab6dffc7d44575c99"}, - {file = "mypy-1.20.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:89dce27e142d25ffbc154c1819383b69f2e9234dc4ed4766f42e0e8cb264ab5c"}, - {file = "mypy-1.20.2-cp310-cp310-win_amd64.whl", hash = "sha256:f376e37f9bf2a946872fc5fd1199c99310748e3c26c7a26683f13f8bdb756cbd"}, - {file = "mypy-1.20.2-cp310-cp310-win_arm64.whl", hash = "sha256:6e2b469efd811707bc530fd1effef0f5d6eebcb7fe376affae69025da4b979a2"}, - {file = "mypy-1.20.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4077797a273e56e8843d001e9dfe4ba10e33323d6ade647ff260e5cd97d9758c"}, - {file = "mypy-1.20.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cdecf62abcc4292500d7858aeae87a1f8f1150f4c4dd08fb0b336ee79b2a6df3"}, - {file = "mypy-1.20.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c566c3a88b6ece59b3d70f65bedef17304f48eb52ff040a6a18214e1917b3254"}, - {file = "mypy-1.20.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0deb80d062b2479f2c87ae568f89845afc71d11bc41b04179e58165fd9f31e98"}, - {file = "mypy-1.20.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bba9ad231e92a3e424b3e56b65aa17704993425bba97e302c832f9466bb85bac"}, - {file = "mypy-1.20.2-cp311-cp311-win_amd64.whl", hash = "sha256:baf593f2765fa3a6b1ef95807dbaa3d25b594f6a52adcc506a6b9cb115e1be67"}, - {file = "mypy-1.20.2-cp311-cp311-win_arm64.whl", hash = "sha256:20175a1c0f49863946ec20b7f63255768058ac4f07d2b9ded6a6b46cfb5a9100"}, - {file = "mypy-1.20.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4dbfcf869f6b0517f70cf0030ba6ea1d6645e132337a7d5204a18d8d5636c02b"}, - {file = "mypy-1.20.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b6481b228d072315b053210b01ac320e1be243dc17f9e5887ef167f23f5fae4"}, - {file = "mypy-1.20.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34397cdced6b90b836e38182076049fdb41424322e0b0728c946b0939ebdf9f6"}, - {file = "mypy-1.20.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5da6976f20cae27059ea8d0c86e7cef3de720e04c4bb9ee18e3690fdb792066"}, - {file = "mypy-1.20.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:56908d7e08318d39f85b1f0c6cfd47b0cac1a130da677630dac0de3e0623e102"}, - {file = "mypy-1.20.2-cp312-cp312-win_amd64.whl", hash = "sha256:d52ad8d78522da1d308789df651ee5379088e77c76cb1994858d40a426b343b9"}, - {file = "mypy-1.20.2-cp312-cp312-win_arm64.whl", hash = "sha256:785b08db19c9f214dc37d65f7c165d19a30fcecb48abfa30f31b01b5acaabb58"}, - {file = "mypy-1.20.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:edfbfca868cdd6bd8d974a60f8a3682f5565d3f5c99b327640cedd24c4264026"}, - {file = "mypy-1.20.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e2877a02380adfcdbc69071a0f74d6e9dbbf593c0dc9d174e1f223ffd5281943"}, - {file = "mypy-1.20.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7488448de6007cd5177c6cea0517ac33b4c0f5ee9b5e9f2be51ce75511a85517"}, - {file = "mypy-1.20.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb9c2fa06887e21d6a3a868762acb82aec34e2c6fd0174064f27c93ede68ad15"}, - {file = "mypy-1.20.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d56a78b646f2e3daa865bc70cd5ec5a46c50045801ca8ff17a0c43abc97e3ee"}, - {file = "mypy-1.20.2-cp313-cp313-win_amd64.whl", hash = "sha256:2a4102b03bb7481d9a91a6da8d174740c9c8c4401024684b9ca3b7cc5e49852f"}, - {file = "mypy-1.20.2-cp313-cp313-win_arm64.whl", hash = "sha256:a95a9248b0c6fd933a442c03c3b113c3b61320086b88e2c444676d3fd1ca3330"}, - {file = "mypy-1.20.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:419413398fe250aae057fd2fe50166b61077083c9b82754c341cf4fd73038f30"}, - {file = "mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e73c07f23009962885c197ccb9b41356a30cc0e5a1d0c2ea8fd8fb1362d7f924"}, - {file = "mypy-1.20.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c64e5973df366b747646fc98da921f9d6eba9716d57d1db94a83c026a08e0fb"}, - {file = "mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a65aa591af023864fd08a97da9974e919452cfe19cb146c8a5dc692626445dc"}, - {file = "mypy-1.20.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4fef51b01e638974a6e69885687e9bd40c8d1e09a6cd291cca0619625cf1f558"}, - {file = "mypy-1.20.2-cp314-cp314-win_amd64.whl", hash = "sha256:913485a03f1bcf5d279409a9d2b9ed565c151f61c09f29991e5faa14033da4c8"}, - {file = "mypy-1.20.2-cp314-cp314-win_arm64.whl", hash = "sha256:c3bae4f855d965b5453784300c12ffc63a548304ac7f99e55d4dc7c898673aa3"}, - {file = "mypy-1.20.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2de3dcea53babc1c3237a19002bc3d228ce1833278f093b8d619e06e7cc79609"}, - {file = "mypy-1.20.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:52b176444e2e5054dfcbcb8c75b0b719865c96247b37407184bbfca5c353f2c2"}, - {file = "mypy-1.20.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:688c3312e5dadb573a2c69c82af3a298d43ecf9e6d264e0f95df960b5f6ac19c"}, - {file = "mypy-1.20.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29752dbbf8cc53f89f6ac096d363314333045c257c9c75cbd189ca2de0455744"}, - {file = "mypy-1.20.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:803203d2b6ea644982c644895c2f78b28d0e208bba7b27d9b921e0ec5eb207c6"}, - {file = "mypy-1.20.2-cp314-cp314t-win_amd64.whl", hash = "sha256:9bcb8aa397ff0093c824182fd76a935a9ba7ad097fcbef80ae89bf6c1731d8ec"}, - {file = "mypy-1.20.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e061b58443f1736f8a37c48978d7ab581636d6ab03e3d4f99e3fa90463bb9382"}, - {file = "mypy-1.20.2-py3-none-any.whl", hash = "sha256:a94c5a76ab46c5e6257c7972b6c8cff0574201ca7dc05647e33e795d78680563"}, - {file = "mypy-1.20.2.tar.gz", hash = "sha256:e8222c26daaafd9e8626dec58ae36029f82585890589576f769a650dd20fd665"}, + {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"}, ] [package.dependencies] -librt = {version = ">=0.8.0", markers = "platform_python_implementation != \"PyPy\""} +ast-serialize = ">=0.3.0,<1.0.0" +librt = {version = ">=0.11.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\""} @@ -2985,7 +3029,6 @@ dmypy = ["psutil (>=4.0)"] faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] -native-parser = ["ast-serialize (>=0.1.1,<1.0.0)"] reports = ["lxml"] [[package]] @@ -3567,15 +3610,15 @@ typing-extensions = ">=4.14.1" [[package]] name = "pydantic-settings" -version = "2.14.0" +version = "2.14.1" description = "Settings management using Pydantic" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"all\"" files = [ - {file = "pydantic_settings-2.14.0-py3-none-any.whl", hash = "sha256:fc8d5d692eb7092e43c8647c1c35a3ecd00e040fcf02ed86f4cb5458ca62182e"}, - {file = "pydantic_settings-2.14.0.tar.gz", hash = "sha256:24285fd4b0e0c06507dd9fdfd331ee23794305352aaec8fc4eb92d4047aeb67d"}, + {file = "pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de"}, + {file = "pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa"}, ] [package.dependencies] @@ -3607,14 +3650,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.21.2" +version = "10.21.3" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pymdown_extensions-10.21.2-py3-none-any.whl", hash = "sha256:5c0fd2a2bea14eb39af8ff284f1066d898ab2187d81b889b75d46d4348c01638"}, - {file = "pymdown_extensions-10.21.2.tar.gz", hash = "sha256:c3f55a5b8a1d0edf6699e35dcbea71d978d34ff3fa79f3d807b8a5b3fa90fbdc"}, + {file = "pymdown_extensions-10.21.3-py3-none-any.whl", hash = "sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6"}, + {file = "pymdown_extensions-10.21.3.tar.gz", hash = "sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354"}, ] [package.dependencies] @@ -4310,30 +4353,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.12" +version = "0.15.13" 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.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c"}, - {file = "ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c"}, - {file = "ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e"}, - {file = "ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20"}, - {file = "ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d"}, - {file = "ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f"}, - {file = "ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6"}, + {file = "ruff-0.15.13-py3-none-linux_armv6l.whl", hash = "sha256:444b580fc72fd6887e650acd3e575e18cdc79dbcf42fb4030b491057921f61f8"}, + {file = "ruff-0.15.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6590d009e7cb7ebf36f83dbdd44a3fa48a0994ff6f1cdc1b08006abe58f98dc7"}, + {file = "ruff-0.15.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1c26d2f66163deeb6e08d8b39fbbe983ce3c71cea06a6d7591cfd1421793c629"}, + {file = "ruff-0.15.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbd6f94b434f896308e4d57fb7bfde0d02b99f7a64b3bdab0fdfa6a864203a5"}, + {file = "ruff-0.15.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3259f3be4d181bda591da5db2571aed6853c6a048157756448020bc6c5cd22"}, + {file = "ruff-0.15.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae9c17e5eb4430c154e76abc25d79a318190f5a997f38fb6b114416c5319ffc9"}, + {file = "ruff-0.15.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e2e39bff6c341f4b577a21b801326fab0b11847f48fcaa83f00a113c9b3cb55"}, + {file = "ruff-0.15.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e8d9a8e08013542e94d3220bc5b62cc3e5ef87c5f74bff367d3fac14fab013e6"}, + {file = "ruff-0.15.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc411dfebe5eebe55ce041c6ae080eb7668955e866daa2fbb16692a784f1c4ca"}, + {file = "ruff-0.15.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:768494eb08b9cee54e2fd27969966f74db5a57f6eaa7a90fcb3306af34dfc4bd"}, + {file = "ruff-0.15.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fb75f9a3a7e42ffe117d734494e6c5e5cb3565d66e12612cb63d0e572a41a5b6"}, + {file = "ruff-0.15.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8cb74dd33bb2f6613faf7fc03b660053b5ac4f80e706d5788c6335e2a8048d51"}, + {file = "ruff-0.15.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7ef823f817fcd191dc934e984be9cf4094f808effa16f2542ad8e821ba02bbf2"}, + {file = "ruff-0.15.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f345a13937bd7f09f6f5d19fa0721b0c103e00e7f62bc67089a8e5e037719e0b"}, + {file = "ruff-0.15.13-py3-none-win32.whl", hash = "sha256:4044f94208b3b05ba0fc4a4abd0558cf4d6459bd18325eead7fd8cc66f909b41"}, + {file = "ruff-0.15.13-py3-none-win_amd64.whl", hash = "sha256:7064884d442b7d477b4e7473d12da7f08851d2b1982763c5d3f388a19468a1a4"}, + {file = "ruff-0.15.13-py3-none-win_arm64.whl", hash = "sha256:2471da9bd1068c8c064b5fd9c0c4b6dddffd6369cb1cd68b29993b1709ff1b21"}, + {file = "ruff-0.15.13.tar.gz", hash = "sha256:f9d89f17f7ba7fb2ed42921f0df75da797a9a5d71bc39049e2c687cf2baf44b7"}, ] [[package]] @@ -4700,14 +4743,14 @@ types-setuptools = "*" [[package]] name = "types-protobuf" -version = "7.34.1.20260508" +version = "7.34.1.20260518" description = "Typing stubs for protobuf" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_protobuf-7.34.1.20260508-py3-none-any.whl", hash = "sha256:a5d647381f8651bd505304ed1148b8a7b342781796e0f80e0284c774c2262a09"}, - {file = "types_protobuf-7.34.1.20260508.tar.gz", hash = "sha256:1c93e8c294281b76a5255fc21c747db0004694463ac6ea9866ee06da969fa555"}, + {file = "types_protobuf-7.34.1.20260518-py3-none-any.whl", hash = "sha256:a0a5337413347166439c0e07cbc26c6164d091401c6f01b1dfd8cdb966c4dd8f"}, + {file = "types_protobuf-7.34.1.20260518.tar.gz", hash = "sha256:28cfaded25889cb83ebfb63cfb0a43628f0b6f3785767bec17287dc6468795f2"}, ] [[package]] @@ -4756,14 +4799,14 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.33.0.20260408" +version = "2.33.0.20260518" description = "Typing stubs for requests" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_requests-2.33.0.20260408-py3-none-any.whl", hash = "sha256:81f31d5ea4acb39f03be7bc8bed569ba6d5a9c5d97e89f45ac43d819b68ca50f"}, - {file = "types_requests-2.33.0.20260408.tar.gz", hash = "sha256:95b9a86376807a216b2fb412b47617b202091c3ea7c078f47cc358d5528ccb7b"}, + {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"}, ] [package.dependencies] @@ -4825,9 +4868,10 @@ typing-extensions = ">=4.12.0" name = "ujson" version = "5.12.1" 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.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"}, @@ -5187,4 +5231,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "288a8d6ec133dc1a48636d7368ad817917442ed0a7cc7de6ce9a785499f9e4ad" +content-hash = "c1c5be88465a41887bc5ad41bee1927f981ae39760a72c89f96ae00e1101de48" diff --git a/pyproject.toml b/pyproject.toml index 9bd63bc709c..986880f93c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -111,12 +111,12 @@ aws-requests-auth = "^0.4.3" urllib3 = ">=1.25.4,!=2.2.0,<3" requests = ">=2.32.0" cfn-lint = "1.48.1" -mypy = "^1.1.1" +mypy = ">=1.1.1,<3.0.0" 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.13" +ruff = ">=0.5.1,<0.15.14" retry2 = "^0.9.5" pytest-socket = ">=0.6,<0.8" types-redis = "^4.6.0.7" From 7514b797ec184761d362ed76d7a00b3a5849eb04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 10:35:27 -0700 Subject: [PATCH 82/84] chore(deps-dev): bump aws-cdk from 2.1122.0 to 2.1124.1 in the aws-cdk group across 1 directory (#8234) chore(deps-dev): bump aws-cdk in the aws-cdk group across 1 directory Bumps the aws-cdk group with 1 update in the / directory: [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `aws-cdk` from 2.1122.0 to 2.1124.1 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1124.1/packages/aws-cdk) --- updated-dependencies: - dependency-name: aws-cdk dependency-version: 2.1122.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> --- 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 a5282255e0a..3ef587c3ca1 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.1122.0" + "aws-cdk": "^2.1124.1" } }, "node_modules/aws-cdk": { - "version": "2.1122.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1122.0.tgz", - "integrity": "sha512-AI2Ks9qioWLvBPD4IoEtTet3wUG/o/q6U3WR3VCQKH5sNYLLPALo8o9sermNpMnfd1OQkqhL20tp4cEyojrIZg==", + "version": "2.1124.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1124.1.tgz", + "integrity": "sha512-sRYdPMdkX+02EHaT946AFV0w0CMfbHKWpLZPv525xTCkaVu1eYu6DzHFuTdimxdSN0uGQ2D4LHrD1sr94tRhow==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 1abc4ac1895..e862df39fb7 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.1122.0" + "aws-cdk": "^2.1124.1" } } From d457710fb5c22d0a02a39864dc92e59a7f6a7252 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 10:44:52 -0700 Subject: [PATCH 83/84] chore(deps-dev): bump the dev-dependencies group across 1 directory with 2 updates (#8242) Bumps the dev-dependencies group with 2 updates in the / directory: [ruff](https://github.com/astral-sh/ruff) and [pytest-socket](https://github.com/miketheman/pytest-socket). Updates `ruff` from 0.15.13 to 0.15.14 - [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.13...0.15.14) Updates `pytest-socket` from 0.7.0 to 0.8.0 - [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.7.0...0.8.0) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.15.14 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: pytest-socket dependency-version: 0.8.0 dependency-type: direct:development update-type: version-update:semver-minor 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 | 80 +++++++++++++++++++++++++++++--------------------- pyproject.toml | 4 +-- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7d630bd4586..fdc75dcbcac 100644 --- a/poetry.lock +++ b/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 = "annotated-types" @@ -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" @@ -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" @@ -962,6 +964,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" @@ -1079,6 +1082,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" @@ -1327,6 +1331,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" @@ -1712,11 +1717,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" @@ -2106,6 +2111,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)"] @@ -2392,7 +2398,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" @@ -3412,6 +3418,7 @@ files = [ {file = "protobuf-7.34.1-py3-none-any.whl", hash = "sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11"}, {file = "protobuf-7.34.1.tar.gz", hash = "sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280"}, ] +markers = {main = "extra == \"kafka-consumer-protobuf\" or extra == \"valkey\""} [[package]] name = "publication" @@ -3773,18 +3780,18 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "pytest-socket" -version = "0.7.0" +version = "0.8.0" description = "Pytest Plugin to disable socket calls during tests" optional = false -python-versions = ">=3.8,<4.0" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pytest_socket-0.7.0-py3-none-any.whl", hash = "sha256:7e0f4642177d55d317bbd58fc68c6bd9048d6eadb2d46a89307fa9221336ce45"}, - {file = "pytest_socket-0.7.0.tar.gz", hash = "sha256:71ab048cbbcb085c15a4423b73b619a8b35d6a307f46f78ea46be51b1b7e11b3"}, + {file = "pytest_socket-0.8.0-py3-none-any.whl", hash = "sha256:81821ba59f07d7600fe2b551d8714f40b068bd46e8b6704c48664e9d60cdacb8"}, + {file = "pytest_socket-0.8.0.tar.gz", hash = "sha256:af9bb5f487da72be63573a6194cfac033b6c7a1c1561e150521105970f9e99f2"}, ] [package.dependencies] -pytest = ">=6.2.5" +pytest = ">=7.0.0" [[package]] name = "pytest-xdist" @@ -3818,6 +3825,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" @@ -4182,6 +4190,7 @@ files = [ {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}, {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}, ] +markers = {main = "extra == \"datadog\""} [package.dependencies] certifi = ">=2023.5.7" @@ -4353,30 +4362,30 @@ files = [ [[package]] name = "ruff" -version = "0.15.13" +version = "0.15.14" 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.13-py3-none-linux_armv6l.whl", hash = "sha256:444b580fc72fd6887e650acd3e575e18cdc79dbcf42fb4030b491057921f61f8"}, - {file = "ruff-0.15.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6590d009e7cb7ebf36f83dbdd44a3fa48a0994ff6f1cdc1b08006abe58f98dc7"}, - {file = "ruff-0.15.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1c26d2f66163deeb6e08d8b39fbbe983ce3c71cea06a6d7591cfd1421793c629"}, - {file = "ruff-0.15.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbd6f94b434f896308e4d57fb7bfde0d02b99f7a64b3bdab0fdfa6a864203a5"}, - {file = "ruff-0.15.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3259f3be4d181bda591da5db2571aed6853c6a048157756448020bc6c5cd22"}, - {file = "ruff-0.15.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae9c17e5eb4430c154e76abc25d79a318190f5a997f38fb6b114416c5319ffc9"}, - {file = "ruff-0.15.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e2e39bff6c341f4b577a21b801326fab0b11847f48fcaa83f00a113c9b3cb55"}, - {file = "ruff-0.15.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e8d9a8e08013542e94d3220bc5b62cc3e5ef87c5f74bff367d3fac14fab013e6"}, - {file = "ruff-0.15.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc411dfebe5eebe55ce041c6ae080eb7668955e866daa2fbb16692a784f1c4ca"}, - {file = "ruff-0.15.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:768494eb08b9cee54e2fd27969966f74db5a57f6eaa7a90fcb3306af34dfc4bd"}, - {file = "ruff-0.15.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fb75f9a3a7e42ffe117d734494e6c5e5cb3565d66e12612cb63d0e572a41a5b6"}, - {file = "ruff-0.15.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8cb74dd33bb2f6613faf7fc03b660053b5ac4f80e706d5788c6335e2a8048d51"}, - {file = "ruff-0.15.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7ef823f817fcd191dc934e984be9cf4094f808effa16f2542ad8e821ba02bbf2"}, - {file = "ruff-0.15.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f345a13937bd7f09f6f5d19fa0721b0c103e00e7f62bc67089a8e5e037719e0b"}, - {file = "ruff-0.15.13-py3-none-win32.whl", hash = "sha256:4044f94208b3b05ba0fc4a4abd0558cf4d6459bd18325eead7fd8cc66f909b41"}, - {file = "ruff-0.15.13-py3-none-win_amd64.whl", hash = "sha256:7064884d442b7d477b4e7473d12da7f08851d2b1982763c5d3f388a19468a1a4"}, - {file = "ruff-0.15.13-py3-none-win_arm64.whl", hash = "sha256:2471da9bd1068c8c064b5fd9c0c4b6dddffd6369cb1cd68b29993b1709ff1b21"}, - {file = "ruff-0.15.13.tar.gz", hash = "sha256:f9d89f17f7ba7fb2ed42921f0df75da797a9a5d71bc39049e2c687cf2baf44b7"}, + {file = "ruff-0.15.14-py3-none-linux_armv6l.whl", hash = "sha256:8dd2db9416e487c8d4b01fa7056bb02c4d05969d4f8d17a08c229c2f4ff3c108"}, + {file = "ruff-0.15.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:be4ff55af755bd71a00ab3dc6bd7ffc467bd76e0df6881e286c2e3d23e8fb43b"}, + {file = "ruff-0.15.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:48d5909d7d06276ce7dde6d32bfa4b0d4cb2651145cd8ee4b440722cbc77832f"}, + {file = "ruff-0.15.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca8cbfa94c4f90984a67561978602746d4cd27103568f745fa90eee3f0d4107d"}, + {file = "ruff-0.15.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a6bbc0333f1ab053423bcbf6226477d266ca7cec7738c4c8e3f55647803f3c4"}, + {file = "ruff-0.15.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a24a4f7605d7003a6674d4387651effd939dead3fddd0f36561eb77a9a2e542"}, + {file = "ruff-0.15.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:049b5326e53ed80978f2fc041a280603f69dd6b0c95464342a2bb4572d9d9e2f"}, + {file = "ruff-0.15.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4ed42e6696c8dfa5f06728e6441993901f548eb92d73bc472cb5a38d1395fbf"}, + {file = "ruff-0.15.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:715c543cf450c4888251f91c52f1942a800541d9bddd7ac060aa4e6b77ae7cba"}, + {file = "ruff-0.15.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ebab6013ec887d439d8b7593737a0a4ffb06d45d209d4e4bf2e92813082d3f"}, + {file = "ruff-0.15.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:49072d36abdbe97a8dd7f480afe9c675699c0c495d4c84076e2c1203c4550581"}, + {file = "ruff-0.15.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:958522aee105068640c2c2ceae08f413ae44d922f52a1374ac13d6a96032fc93"}, + {file = "ruff-0.15.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f3707da619a143a2e8830e2abab8224478d69ace2d28cb6c20543ae97c36bf61"}, + {file = "ruff-0.15.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bb01d645694e3ec0102105d07ef2d53703970407d59c04e59d3ba0b7a1d53553"}, + {file = "ruff-0.15.14-py3-none-win32.whl", hash = "sha256:6d0c1ad2a0ab718d39b6d8fd2217981ce4d625cd96a720095f798fb47d8b13e6"}, + {file = "ruff-0.15.14-py3-none-win_amd64.whl", hash = "sha256:802342981e056db3851a7836e5b070f8f15f67d4a685ae2a6160939d364b2902"}, + {file = "ruff-0.15.14-py3-none-win_arm64.whl", hash = "sha256:ff47b90a9ef6a40c9e2f3b479c1fb78531adf055b94c1eba0a7ba04b31951826"}, + {file = "ruff-0.15.14.tar.gz", hash = "sha256:48e866b165be4a9bdbf310f7d3c9a07edef2fe8cd63ffeb4e00bb590506ebf9f"}, ] [[package]] @@ -4390,12 +4399,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" @@ -4488,6 +4498,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" @@ -4962,6 +4973,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\""] @@ -5231,4 +5243,4 @@ valkey = ["valkey-glide"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0.0" -content-hash = "c1c5be88465a41887bc5ad41bee1927f981ae39760a72c89f96ae00e1101de48" +content-hash = "ec4397857f1745105717c60a48f9791c37387457cba3aca337c2afa55b29d77d" diff --git a/pyproject.toml b/pyproject.toml index 986880f93c9..5ca4ee98915 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -116,9 +116,9 @@ 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.14" +ruff = ">=0.5.1,<0.15.15" retry2 = "^0.9.5" -pytest-socket = ">=0.6,<0.8" +pytest-socket = ">=0.6,<0.9" types-redis = "^4.6.0.7" testcontainers = { extras = ["redis"], version = ">=3.7.1,<5.0.0" } multiprocess = "^0.70.16" From 92c18b01a924929619194a2b79759db46468f5af Mon Sep 17 00:00:00 2001 From: derdelean Date: Thu, 21 May 2026 19:46:26 +0200 Subject: [PATCH 84/84] docs(metadata): fix broken Lambda Metadata Endpoint link (#8212) Co-authored-by: Leandro Damascena