From cb79b4b676ebc837c43e65cd503fdbc5007b847b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Fonseca?= Date: Tue, 24 Jan 2023 15:10:29 +0000 Subject: [PATCH 01/30] fix: bump aws-cdk version --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1764eda669e..f466bfd38a1 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.44.0" + "aws-cdk": "2.61.1" } }, "node_modules/aws-cdk": { - "version": "2.44.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.44.0.tgz", - "integrity": "sha512-9hbK4Yc1GQ28zSjZE2ajidt7sRrTLYpijkI7HT7JcDhXLe2ZGP9EOZrqKy5EEsOv0wDQ7cdXB3/oMiMGSmSQ5A==", + "version": "2.61.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.61.1.tgz", + "integrity": "sha512-bufvOB+I2T6YjVjT6D0j6xbi6CnX62j7TfHL905WLd5UQhPecwlL8wLe2whUOKqZj2wmGjaP7jAjIE1FFfh98w==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -43,9 +43,9 @@ }, "dependencies": { "aws-cdk": { - "version": "2.44.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.44.0.tgz", - "integrity": "sha512-9hbK4Yc1GQ28zSjZE2ajidt7sRrTLYpijkI7HT7JcDhXLe2ZGP9EOZrqKy5EEsOv0wDQ7cdXB3/oMiMGSmSQ5A==", + "version": "2.61.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.61.1.tgz", + "integrity": "sha512-bufvOB+I2T6YjVjT6D0j6xbi6CnX62j7TfHL905WLd5UQhPecwlL8wLe2whUOKqZj2wmGjaP7jAjIE1FFfh98w==", "dev": true, "requires": { "fsevents": "2.3.2" diff --git a/package.json b/package.json index 6d5eb3f5bee..1d9a62c13d9 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.44.0" + "aws-cdk": "2.61.1" } } From f7bb4e9bcf9bae89f4a5327bda010eb6a7352adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Fonseca?= Date: Tue, 24 Jan 2023 15:15:59 +0000 Subject: [PATCH 02/30] fix: parallel_run should fail when e2e tests fail --- parallel_run_e2e.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/parallel_run_e2e.py b/parallel_run_e2e.py index 745f1392f67..be3e1ab0cf8 100755 --- a/parallel_run_e2e.py +++ b/parallel_run_e2e.py @@ -1,5 +1,6 @@ """ Calculate how many parallel workers are needed to complete E2E infrastructure jobs across available CPU Cores """ import subprocess +import sys from pathlib import Path @@ -8,7 +9,8 @@ def main(): workers = len(list(features)) - 1 command = f"poetry run pytest -n {workers} --dist loadfile -o log_cli=true tests/e2e" - subprocess.run(command.split(), shell=False) + result = subprocess.run(command.split(), shell=False) + sys.exit(result.returncode) if __name__ == "__main__": From 20e43f6b0ba396df089c60d7ce08facd45cc8e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Fonseca?= Date: Tue, 24 Jan 2023 15:52:15 +0000 Subject: [PATCH 03/30] fix(ci): scope e2e tests by python version --- tests/e2e/utils/infrastructure.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/e2e/utils/infrastructure.py b/tests/e2e/utils/infrastructure.py index 29e45b83abf..daf1a817c89 100644 --- a/tests/e2e/utils/infrastructure.py +++ b/tests/e2e/utils/infrastructure.py @@ -1,6 +1,7 @@ import json import logging import os +import platform import subprocess import sys import textwrap @@ -56,7 +57,7 @@ def __init__(self) -> None: self._feature_infra_module_path = self.feature_path / "infrastructure" self._feature_infra_file = self.feature_path / "infrastructure.py" self._handlers_dir = self.feature_path / "handlers" - self._cdk_out_dir: Path = CDK_OUT_PATH / self.feature_name + self._cdk_out_dir: Path = CDK_OUT_PATH / "-".join(platform.python_version_tuple()) / self.feature_name self._stack_outputs_file = f'{self._cdk_out_dir / "stack_outputs.json"}' if not self._feature_infra_file.exists(): From 32597d8bf6c4b3882f6fce1602bea412d373e3a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 20:10:29 +0000 Subject: [PATCH 04/30] chore(deps-dev): bump mypy-boto3-lambda from 1.26.49 to 1.26.55 (#1856) Bumps [mypy-boto3-lambda](https://github.com/youtype/mypy_boto3_builder) from 1.26.49 to 1.26.55. - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) --- updated-dependencies: - dependency-name: mypy-boto3-lambda dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 11 ++++++----- pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8b7320b4381..042a08914d1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1062,6 +1062,7 @@ category = "dev" optional = false python-versions = "*" files = [ + {file = "junit-xml-1.9.tar.gz", hash = "sha256:de16a051990d4e25a3982b2dd9e89d671067548718866416faec14d9de56db9f"}, {file = "junit_xml-1.9-py2.py3-none-any.whl", hash = "sha256:ec5ca1a55aefdd76d28fcc0b135251d156c7106fa979686a4b48d62b761b4732"}, ] @@ -1436,14 +1437,14 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-lambda" -version = "1.26.49" -description = "Type annotations for boto3.Lambda 1.26.49 service generated with mypy-boto3-builder 7.12.3" +version = "1.26.55" +description = "Type annotations for boto3.Lambda 1.26.55 service generated with mypy-boto3-builder 7.12.3" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-lambda-1.26.49.tar.gz", hash = "sha256:748222e6dfd602a667b76b9ce0e8c8b31664bc3bd78cc43363fb22ca2885b4c3"}, - {file = "mypy_boto3_lambda-1.26.49-py3-none-any.whl", hash = "sha256:ef346c1fbbc80a907c1d44f19ea9335f8c3889fb48766cb0f7e4439e339fae2b"}, + {file = "mypy-boto3-lambda-1.26.55.tar.gz", hash = "sha256:357e80e81c1e6674a1d5d879f6f1578103d3825bb87a7d2c897e8626a0f95fc0"}, + {file = "mypy_boto3_lambda-1.26.55-py3-none-any.whl", hash = "sha256:3df0dc3e24ec0c79b0bdd024d40694aa41d2a5e355f9441863657eb632567312"}, ] [package.dependencies] @@ -2665,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "5b925c7de2441a1193ae75efe1548070b10b71cb99bc4627e5cabef683b05f95" +content-hash = "bbd738d5ea06ac51cce9db50ee6cde80f00026611716e690272de80c45992d6b" diff --git a/pyproject.toml b/pyproject.toml index 29e6aa21609..d40cef2a25d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,7 @@ mypy-boto3-appconfig = "^1.26.0" mypy-boto3-cloudformation = "^1.26.35" mypy-boto3-cloudwatch = "^1.26.52" mypy-boto3-dynamodb = "^1.26.24" -mypy-boto3-lambda = "^1.26.49" +mypy-boto3-lambda = "^1.26.55" mypy-boto3-logs = "^1.26.53" mypy-boto3-secretsmanager = "^1.26.49" mypy-boto3-ssm = "^1.26.43" From ffbcdcb435b8636c5614298a257e3b01c6415e4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 22:21:48 +0000 Subject: [PATCH 05/30] chore(deps): bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 (#1855) --- .github/workflows/auto-merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 8402ff66d2e..2e799c65333 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v1.3.5 + uses: dependabot/fetch-metadata@v1.3.6 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Enable auto-merge for mypy-boto3 stubs Dependabot PRs From 864771c2e8d93222dca3f9fcd1d165aea799f278 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Jan 2023 20:10:32 +0000 Subject: [PATCH 06/30] chore(deps-dev): bump aws-cdk-lib from 2.61.1 to 2.62.0 (#1863) Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.61.1 to 2.62.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/v2.62.0/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.61.1...v2.62.0) --- updated-dependencies: - dependency-name: aws-cdk-lib dependency-type: direct:development 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> --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 042a08914d1..7664b8496c6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -110,14 +110,14 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.61.1" +version = "2.62.0" description = "Version 2 of the AWS Cloud Development Kit library" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk-lib-2.61.1.tar.gz", hash = "sha256:d2bb672be182e0cd675717648fa100e1a49f01de606ffa4f7a0b580093f31b27"}, - {file = "aws_cdk_lib-2.61.1-py3-none-any.whl", hash = "sha256:e0b5d49c73be945ca176b38ff3d2ccfc9474639000afb6af65a1eaf8b6aa3385"}, + {file = "aws-cdk-lib-2.62.0.tar.gz", hash = "sha256:e1fecab6e7765ce286a5ab7f971aaca26ab78fdbb84a4f516a80d2d5bda8bba9"}, + {file = "aws_cdk_lib-2.62.0-py3-none-any.whl", hash = "sha256:bc153647ea598bb76dcc047e4d419edcfa6f923540448510b0627f0b2ae5a9f1"}, ] [package.dependencies] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "bbd738d5ea06ac51cce9db50ee6cde80f00026611716e690272de80c45992d6b" +content-hash = "e478d2275a13d26509cf176e523c543940bcef85a5620398081c3e72653f7c6e" diff --git a/pyproject.toml b/pyproject.toml index d40cef2a25d..3007dd22c5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" retry = "^0.9.2" pytest-xdist = "^3.1.0" -aws-cdk-lib = "^2.61.1" +aws-cdk-lib = "^2.62.0" "aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" From a556d28909b6676021da146dc9efbdaaaa3f81a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 07:40:57 +0000 Subject: [PATCH 07/30] chore(deps-dev): bump coverage from 7.0.5 to 7.1.0 (#1862) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 106 ++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7664b8496c6..4b1d1261b48 100644 --- a/poetry.lock +++ b/poetry.lock @@ -390,63 +390,63 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "coverage" -version = "7.0.5" +version = "7.1.0" description = "Code coverage measurement for Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "coverage-7.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2a7f23bbaeb2a87f90f607730b45564076d870f1fb07b9318d0c21f36871932b"}, - {file = "coverage-7.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c18d47f314b950dbf24a41787ced1474e01ca816011925976d90a88b27c22b89"}, - {file = "coverage-7.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef14d75d86f104f03dea66c13188487151760ef25dd6b2dbd541885185f05f40"}, - {file = "coverage-7.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66e50680e888840c0995f2ad766e726ce71ca682e3c5f4eee82272c7671d38a2"}, - {file = "coverage-7.0.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9fed35ca8c6e946e877893bbac022e8563b94404a605af1d1e6accc7eb73289"}, - {file = "coverage-7.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d8d04e755934195bdc1db45ba9e040b8d20d046d04d6d77e71b3b34a8cc002d0"}, - {file = "coverage-7.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e109f1c9a3ece676597831874126555997c48f62bddbcace6ed17be3e372de8"}, - {file = "coverage-7.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0a1890fca2962c4f1ad16551d660b46ea77291fba2cc21c024cd527b9d9c8809"}, - {file = "coverage-7.0.5-cp310-cp310-win32.whl", hash = "sha256:be9fcf32c010da0ba40bf4ee01889d6c737658f4ddff160bd7eb9cac8f094b21"}, - {file = "coverage-7.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:cbfcba14a3225b055a28b3199c3d81cd0ab37d2353ffd7f6fd64844cebab31ad"}, - {file = "coverage-7.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:30b5fec1d34cc932c1bc04017b538ce16bf84e239378b8f75220478645d11fca"}, - {file = "coverage-7.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1caed2367b32cc80a2b7f58a9f46658218a19c6cfe5bc234021966dc3daa01f0"}, - {file = "coverage-7.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d254666d29540a72d17cc0175746cfb03d5123db33e67d1020e42dae611dc196"}, - {file = "coverage-7.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19245c249aa711d954623d94f23cc94c0fd65865661f20b7781210cb97c471c0"}, - {file = "coverage-7.0.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b05ed4b35bf6ee790832f68932baf1f00caa32283d66cc4d455c9e9d115aafc"}, - {file = "coverage-7.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:29de916ba1099ba2aab76aca101580006adfac5646de9b7c010a0f13867cba45"}, - {file = "coverage-7.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e057e74e53db78122a3979f908973e171909a58ac20df05c33998d52e6d35757"}, - {file = "coverage-7.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:411d4ff9d041be08fdfc02adf62e89c735b9468f6d8f6427f8a14b6bb0a85095"}, - {file = "coverage-7.0.5-cp311-cp311-win32.whl", hash = "sha256:52ab14b9e09ce052237dfe12d6892dd39b0401690856bcfe75d5baba4bfe2831"}, - {file = "coverage-7.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:1f66862d3a41674ebd8d1a7b6f5387fe5ce353f8719040a986551a545d7d83ea"}, - {file = "coverage-7.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b69522b168a6b64edf0c33ba53eac491c0a8f5cc94fa4337f9c6f4c8f2f5296c"}, - {file = "coverage-7.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436e103950d05b7d7f55e39beeb4d5be298ca3e119e0589c0227e6d0b01ee8c7"}, - {file = "coverage-7.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8c56bec53d6e3154eaff6ea941226e7bd7cc0d99f9b3756c2520fc7a94e6d96"}, - {file = "coverage-7.0.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a38362528a9115a4e276e65eeabf67dcfaf57698e17ae388599568a78dcb029"}, - {file = "coverage-7.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f67472c09a0c7486e27f3275f617c964d25e35727af952869dd496b9b5b7f6a3"}, - {file = "coverage-7.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:220e3fa77d14c8a507b2d951e463b57a1f7810a6443a26f9b7591ef39047b1b2"}, - {file = "coverage-7.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ecb0f73954892f98611e183f50acdc9e21a4653f294dfbe079da73c6378a6f47"}, - {file = "coverage-7.0.5-cp37-cp37m-win32.whl", hash = "sha256:d8f3e2e0a1d6777e58e834fd5a04657f66affa615dae61dd67c35d1568c38882"}, - {file = "coverage-7.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:9e662e6fc4f513b79da5d10a23edd2b87685815b337b1a30cd11307a6679148d"}, - {file = "coverage-7.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:790e4433962c9f454e213b21b0fd4b42310ade9c077e8edcb5113db0818450cb"}, - {file = "coverage-7.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49640bda9bda35b057b0e65b7c43ba706fa2335c9a9896652aebe0fa399e80e6"}, - {file = "coverage-7.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d66187792bfe56f8c18ba986a0e4ae44856b1c645336bd2c776e3386da91e1dd"}, - {file = "coverage-7.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:276f4cd0001cd83b00817c8db76730938b1ee40f4993b6a905f40a7278103b3a"}, - {file = "coverage-7.0.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95304068686545aa368b35dfda1cdfbbdbe2f6fe43de4a2e9baa8ebd71be46e2"}, - {file = "coverage-7.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:17e01dd8666c445025c29684d4aabf5a90dc6ef1ab25328aa52bedaa95b65ad7"}, - {file = "coverage-7.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea76dbcad0b7b0deb265d8c36e0801abcddf6cc1395940a24e3595288b405ca0"}, - {file = "coverage-7.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:50a6adc2be8edd7ee67d1abc3cd20678987c7b9d79cd265de55941e3d0d56499"}, - {file = "coverage-7.0.5-cp38-cp38-win32.whl", hash = "sha256:e4ce984133b888cc3a46867c8b4372c7dee9cee300335e2925e197bcd45b9e16"}, - {file = "coverage-7.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:4a950f83fd3f9bca23b77442f3a2b2ea4ac900944d8af9993743774c4fdc57af"}, - {file = "coverage-7.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c2155943896ac78b9b0fd910fb381186d0c345911f5333ee46ac44c8f0e43ab"}, - {file = "coverage-7.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:54f7e9705e14b2c9f6abdeb127c390f679f6dbe64ba732788d3015f7f76ef637"}, - {file = "coverage-7.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ee30375b409d9a7ea0f30c50645d436b6f5dfee254edffd27e45a980ad2c7f4"}, - {file = "coverage-7.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b78729038abea6a5df0d2708dce21e82073463b2d79d10884d7d591e0f385ded"}, - {file = "coverage-7.0.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13250b1f0bd023e0c9f11838bdeb60214dd5b6aaf8e8d2f110c7e232a1bff83b"}, - {file = "coverage-7.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c407b1950b2d2ffa091f4e225ca19a66a9bd81222f27c56bd12658fc5ca1209"}, - {file = "coverage-7.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c76a3075e96b9c9ff00df8b5f7f560f5634dffd1658bafb79eb2682867e94f78"}, - {file = "coverage-7.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f26648e1b3b03b6022b48a9b910d0ae209e2d51f50441db5dce5b530fad6d9b1"}, - {file = "coverage-7.0.5-cp39-cp39-win32.whl", hash = "sha256:ba3027deb7abf02859aca49c865ece538aee56dcb4871b4cced23ba4d5088904"}, - {file = "coverage-7.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:949844af60ee96a376aac1ded2a27e134b8c8d35cc006a52903fc06c24a3296f"}, - {file = "coverage-7.0.5-pp37.pp38.pp39-none-any.whl", hash = "sha256:b9727ac4f5cf2cbf87880a63870b5b9730a8ae3a4a360241a0fdaa2f71240ff0"}, - {file = "coverage-7.0.5.tar.gz", hash = "sha256:051afcbd6d2ac39298d62d340f94dbb6a1f31de06dfaf6fcef7b759dd3860c45"}, + {file = "coverage-7.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b946bbcd5a8231383450b195cfb58cb01cbe7f8949f5758566b881df4b33baf"}, + {file = "coverage-7.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec8e767f13be637d056f7e07e61d089e555f719b387a7070154ad80a0ff31801"}, + {file = "coverage-7.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a5a5879a939cb84959d86869132b00176197ca561c664fc21478c1eee60d75"}, + {file = "coverage-7.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b643cb30821e7570c0aaf54feaf0bfb630b79059f85741843e9dc23f33aaca2c"}, + {file = "coverage-7.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32df215215f3af2c1617a55dbdfb403b772d463d54d219985ac7cd3bf124cada"}, + {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:33d1ae9d4079e05ac4cc1ef9e20c648f5afabf1a92adfaf2ccf509c50b85717f"}, + {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:29571503c37f2ef2138a306d23e7270687c0efb9cab4bd8038d609b5c2393a3a"}, + {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:63ffd21aa133ff48c4dff7adcc46b7ec8b565491bfc371212122dd999812ea1c"}, + {file = "coverage-7.1.0-cp310-cp310-win32.whl", hash = "sha256:4b14d5e09c656de5038a3f9bfe5228f53439282abcab87317c9f7f1acb280352"}, + {file = "coverage-7.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:8361be1c2c073919500b6601220a6f2f98ea0b6d2fec5014c1d9cfa23dd07038"}, + {file = "coverage-7.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:da9b41d4539eefd408c46725fb76ecba3a50a3367cafb7dea5f250d0653c1040"}, + {file = "coverage-7.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5b15ed7644ae4bee0ecf74fee95808dcc34ba6ace87e8dfbf5cb0dc20eab45a"}, + {file = "coverage-7.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d12d076582507ea460ea2a89a8c85cb558f83406c8a41dd641d7be9a32e1274f"}, + {file = "coverage-7.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2617759031dae1bf183c16cef8fcfb3de7617f394c813fa5e8e46e9b82d4222"}, + {file = "coverage-7.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4e4881fa9e9667afcc742f0c244d9364d197490fbc91d12ac3b5de0bf2df146"}, + {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9d58885215094ab4a86a6aef044e42994a2bd76a446dc59b352622655ba6621b"}, + {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2"}, + {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3baf5f126f30781b5e93dbefcc8271cb2491647f8283f20ac54d12161dff080e"}, + {file = "coverage-7.1.0-cp311-cp311-win32.whl", hash = "sha256:ded59300d6330be27bc6cf0b74b89ada58069ced87c48eaf9344e5e84b0072f7"}, + {file = "coverage-7.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:6a43c7823cd7427b4ed763aa7fb63901ca8288591323b58c9cd6ec31ad910f3c"}, + {file = "coverage-7.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a726d742816cb3a8973c8c9a97539c734b3a309345236cd533c4883dda05b8d"}, + {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc7c85a150501286f8b56bd8ed3aa4093f4b88fb68c0843d21ff9656f0009d6a"}, + {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8"}, + {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddb726cb861c3117a553f940372a495fe1078249ff5f8a5478c0576c7be12050"}, + {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:51b236e764840a6df0661b67e50697aaa0e7d4124ca95e5058fa3d7cbc240b7c"}, + {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7ee5c9bb51695f80878faaa5598040dd6c9e172ddcf490382e8aedb8ec3fec8d"}, + {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c31b75ae466c053a98bf26843563b3b3517b8f37da4d47b1c582fdc703112bc3"}, + {file = "coverage-7.1.0-cp37-cp37m-win32.whl", hash = "sha256:3b155caf3760408d1cb903b21e6a97ad4e2bdad43cbc265e3ce0afb8e0057e73"}, + {file = "coverage-7.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2a60d6513781e87047c3e630b33b4d1e89f39836dac6e069ffee28c4786715f5"}, + {file = "coverage-7.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06"}, + {file = "coverage-7.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beeb129cacea34490ffd4d6153af70509aa3cda20fdda2ea1a2be870dfec8d52"}, + {file = "coverage-7.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851"}, + {file = "coverage-7.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef382417db92ba23dfb5864a3fc9be27ea4894e86620d342a116b243ade5d35d"}, + {file = "coverage-7.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c7c0d0827e853315c9bbd43c1162c006dd808dbbe297db7ae66cd17b07830f0"}, + {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e5cdbb5cafcedea04924568d990e20ce7f1945a1dd54b560f879ee2d57226912"}, + {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9817733f0d3ea91bea80de0f79ef971ae94f81ca52f9b66500c6a2fea8e4b4f8"}, + {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:218fe982371ac7387304153ecd51205f14e9d731b34fb0568181abaf7b443ba0"}, + {file = "coverage-7.1.0-cp38-cp38-win32.whl", hash = "sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab"}, + {file = "coverage-7.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8ae125d1134bf236acba8b83e74c603d1b30e207266121e76484562bc816344c"}, + {file = "coverage-7.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2bf1d5f2084c3932b56b962a683074a3692bce7cabd3aa023c987a2a8e7612f6"}, + {file = "coverage-7.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:98b85dd86514d889a2e3dd22ab3c18c9d0019e696478391d86708b805f4ea0fa"}, + {file = "coverage-7.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38da2db80cc505a611938d8624801158e409928b136c8916cd2e203970dde4dc"}, + {file = "coverage-7.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3164d31078fa9efe406e198aecd2a02d32a62fecbdef74f76dad6a46c7e48311"}, + {file = "coverage-7.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db61a79c07331e88b9a9974815c075fbd812bc9dbc4dc44b366b5368a2936063"}, + {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ccb092c9ede70b2517a57382a601619d20981f56f440eae7e4d7eaafd1d1d09"}, + {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:33ff26d0f6cc3ca8de13d14fde1ff8efe1456b53e3f0273e63cc8b3c84a063d8"}, + {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d47dd659a4ee952e90dc56c97d78132573dc5c7b09d61b416a9deef4ebe01a0c"}, + {file = "coverage-7.1.0-cp39-cp39-win32.whl", hash = "sha256:d248cd4a92065a4d4543b8331660121b31c4148dd00a691bfb7a5cdc7483cfa4"}, + {file = "coverage-7.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:7ed681b0f8e8bcbbffa58ba26fcf5dbc8f79e7997595bf071ed5430d8c08d6f3"}, + {file = "coverage-7.1.0-pp37.pp38.pp39-none-any.whl", hash = "sha256:755e89e32376c850f826c425ece2c35a4fc266c081490eb0a841e7c1cb0d3bda"}, + {file = "coverage-7.1.0.tar.gz", hash = "sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265"}, ] [package.dependencies] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "e478d2275a13d26509cf176e523c543940bcef85a5620398081c3e72653f7c6e" +content-hash = "8fb5c7a4e1893d36e3e9c1acf9fd3391905f15ab685a0ba7e9ca7e08969041d0" diff --git a/pyproject.toml b/pyproject.toml index 3007dd22c5e..aa99595dffe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ boto3 = { version = "^1.20.32", optional = true } typing-extensions = "^4.4.0" [tool.poetry.dev-dependencies] -coverage = {extras = ["toml"], version = "^7.0"} +coverage = {extras = ["toml"], version = "^7.1"} pytest = "^7.2.1" black = "^22.12" boto3 = "^1.18" From 07ff75793fedc650fd4ef172a13adeed82cdfce8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 20:07:28 +0000 Subject: [PATCH 08/30] chore(deps-dev): bump mypy-boto3-cloudformation from 1.26.35.post1 to 1.26.57 (#1865) chore(deps-dev): bump mypy-boto3-cloudformation Bumps [mypy-boto3-cloudformation](https://github.com/youtype/mypy_boto3_builder) from 1.26.35.post1 to 1.26.57. - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) --- updated-dependencies: - dependency-name: mypy-boto3-cloudformation dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4b1d1261b48..223b6d74e08 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1392,14 +1392,14 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-cloudformation" -version = "1.26.35.post1" -description = "Type annotations for boto3.CloudFormation 1.26.35 service generated with mypy-boto3-builder 7.12.1" +version = "1.26.57" +description = "Type annotations for boto3.CloudFormation 1.26.57 service generated with mypy-boto3-builder 7.12.3" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudformation-1.26.35.post1.tar.gz", hash = "sha256:b6f35ed5c463946185ae10e15b38f0400a8d88d9faa0534d7b8478474eefdbd4"}, - {file = "mypy_boto3_cloudformation-1.26.35.post1-py3-none-any.whl", hash = "sha256:087ad75bc0760eddb6cf3ef524d079061a5b8af82c7300555ccec21255de420b"}, + {file = "mypy-boto3-cloudformation-1.26.57.tar.gz", hash = "sha256:c1659cf032825293b3eef1acca1a29fb82a7149b6c3ce06bbf405f54b78d3172"}, + {file = "mypy_boto3_cloudformation-1.26.57-py3-none-any.whl", hash = "sha256:4a45872b0fc1d503fa1147560fd842d3bcbec38aad4ca3516b51c33e6dfa05f2"}, ] [package.dependencies] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "8fb5c7a4e1893d36e3e9c1acf9fd3391905f15ab685a0ba7e9ca7e08969041d0" +content-hash = "8e620f99247414babded66a7a864136b20d6f6d089c29cf1dfaacbbfd2ee86ce" diff --git a/pyproject.toml b/pyproject.toml index aa99595dffe..592fba20d0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ aws-cdk-lib = "^2.62.0" pytest-benchmark = "^4.0.0" python-snappy = "^0.6.1" mypy-boto3-appconfig = "^1.26.0" -mypy-boto3-cloudformation = "^1.26.35" +mypy-boto3-cloudformation = "^1.26.57" mypy-boto3-cloudwatch = "^1.26.52" mypy-boto3-dynamodb = "^1.26.24" mypy-boto3-lambda = "^1.26.55" From 3611e9321c47c5e335175e0d5e46e58f6733f670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 20:17:08 +0000 Subject: [PATCH 09/30] chore(deps-dev): bump aws-cdk-lib from 2.62.0 to 2.62.1 (#1866) Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.62.0 to 2.62.1. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.62.0...v2.62.1) --- updated-dependencies: - dependency-name: aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 223b6d74e08..565f9510c40 100644 --- a/poetry.lock +++ b/poetry.lock @@ -110,14 +110,14 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.62.0" +version = "2.62.1" description = "Version 2 of the AWS Cloud Development Kit library" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk-lib-2.62.0.tar.gz", hash = "sha256:e1fecab6e7765ce286a5ab7f971aaca26ab78fdbb84a4f516a80d2d5bda8bba9"}, - {file = "aws_cdk_lib-2.62.0-py3-none-any.whl", hash = "sha256:bc153647ea598bb76dcc047e4d419edcfa6f923540448510b0627f0b2ae5a9f1"}, + {file = "aws-cdk-lib-2.62.1.tar.gz", hash = "sha256:6becf9946c1d14c9e2b3a4caf07571b1fbc1f85192298cc15fb6dd143f60cf39"}, + {file = "aws_cdk_lib-2.62.1-py3-none-any.whl", hash = "sha256:ed897ff0291b19861d4f9b9f545cb8e7710579de646ccc4b8ed60808ba965a35"}, ] [package.dependencies] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "8e620f99247414babded66a7a864136b20d6f6d089c29cf1dfaacbbfd2ee86ce" +content-hash = "8de3ccafeab629cdefa2d38ae10b1b9ca97d00fd9d4b0a2f4f641ae278d794ef" diff --git a/pyproject.toml b/pyproject.toml index 592fba20d0b..7854d1810a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" retry = "^0.9.2" pytest-xdist = "^3.1.0" -aws-cdk-lib = "^2.62.0" +aws-cdk-lib = "^2.62.1" "aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" From 0c6c14c9f17f8cbff1ff9077cf7c768058fcb9af Mon Sep 17 00:00:00 2001 From: Ashutosh Ojha Date: Fri, 27 Jan 2023 16:38:10 +0530 Subject: [PATCH 10/30] docs(event-source): fix incorrect method in example CloudWatch Logs (#1857) --- docs/utilities/data_classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index 85c58e7ce72..cd02f6e8971 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -491,7 +491,7 @@ decompress and parse json data from the event. @event_source(data_class=CloudWatchLogsEvent) def lambda_handler(event: CloudWatchLogsEvent, context): - decompressed_log: CloudWatchLogsDecodedData = event.parse_logs_data + decompressed_log: CloudWatchLogsDecodedData = event.parse_logs_data() log_events = decompressed_log.log_events for event in log_events: do_something_with(event.timestamp, event.message) From 26a630fb7c487f47d210e8c78822353248867a96 Mon Sep 17 00:00:00 2001 From: Release bot Date: Fri, 27 Jan 2023 11:08:38 +0000 Subject: [PATCH 11/30] update changelog with latest changes --- CHANGELOG.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6df040df4ab..5ba5029602d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,28 @@ ## Bug Fixes +* parallel_run should fail when e2e tests fail +* bump aws-cdk version +* **ci:** scope e2e tests by python version + +## Documentation + +* **event-source:** fix incorrect method in example CloudWatch Logs ([#1857](https://github.com/awslabs/aws-lambda-powertools-python/issues/1857)) + +## Maintenance + +* **deps:** bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 ([#1855](https://github.com/awslabs/aws-lambda-powertools-python/issues/1855)) +* **deps-dev:** bump aws-cdk-lib from 2.62.0 to 2.62.1 ([#1866](https://github.com/awslabs/aws-lambda-powertools-python/issues/1866)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.26.35.post1 to 1.26.57 ([#1865](https://github.com/awslabs/aws-lambda-powertools-python/issues/1865)) +* **deps-dev:** bump coverage from 7.0.5 to 7.1.0 ([#1862](https://github.com/awslabs/aws-lambda-powertools-python/issues/1862)) +* **deps-dev:** bump aws-cdk-lib from 2.61.1 to 2.62.0 ([#1863](https://github.com/awslabs/aws-lambda-powertools-python/issues/1863)) +* **deps-dev:** bump mypy-boto3-lambda from 1.26.49 to 1.26.55 ([#1856](https://github.com/awslabs/aws-lambda-powertools-python/issues/1856)) + + + +## [v2.7.0] - 2023-01-24 +## Bug Fixes + * git-chlg docker image is broken ## Features @@ -14,16 +36,17 @@ ## Maintenance +* update v2 layer ARN on documentation * **deps:** bump peaceiris/actions-gh-pages from 3.9.1 to 3.9.2 ([#1841](https://github.com/awslabs/aws-lambda-powertools-python/issues/1841)) * **deps:** bump future from 0.18.2 to 0.18.3 ([#1836](https://github.com/awslabs/aws-lambda-powertools-python/issues/1836)) * **deps:** bump zgosalvez/github-actions-ensure-sha-pinned-actions from 2.0.4 to 2.0.5 ([#1837](https://github.com/awslabs/aws-lambda-powertools-python/issues/1837)) -* **deps-dev:** bump mkdocs-material from 9.0.5 to 9.0.6 ([#1851](https://github.com/awslabs/aws-lambda-powertools-python/issues/1851)) +* **deps-dev:** bump mkdocs-material from 9.0.4 to 9.0.5 ([#1840](https://github.com/awslabs/aws-lambda-powertools-python/issues/1840)) * **deps-dev:** bump types-requests from 2.28.11.7 to 2.28.11.8 ([#1843](https://github.com/awslabs/aws-lambda-powertools-python/issues/1843)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.26.30 to 1.26.52 ([#1847](https://github.com/awslabs/aws-lambda-powertools-python/issues/1847)) * **deps-dev:** bump pytest from 7.2.0 to 7.2.1 ([#1838](https://github.com/awslabs/aws-lambda-powertools-python/issues/1838)) -* **deps-dev:** bump mkdocs-material from 9.0.4 to 9.0.5 ([#1840](https://github.com/awslabs/aws-lambda-powertools-python/issues/1840)) * **deps-dev:** bump aws-cdk-lib from 2.60.0 to 2.61.1 ([#1849](https://github.com/awslabs/aws-lambda-powertools-python/issues/1849)) * **deps-dev:** bump mypy-boto3-logs from 1.26.49 to 1.26.53 ([#1850](https://github.com/awslabs/aws-lambda-powertools-python/issues/1850)) +* **deps-dev:** bump mkdocs-material from 9.0.5 to 9.0.6 ([#1851](https://github.com/awslabs/aws-lambda-powertools-python/issues/1851)) * **deps-dev:** bump mkdocs-material from 9.0.3 to 9.0.4 ([#1833](https://github.com/awslabs/aws-lambda-powertools-python/issues/1833)) * **deps-dev:** bump mypy-boto3-logs from 1.26.43 to 1.26.49 ([#1834](https://github.com/awslabs/aws-lambda-powertools-python/issues/1834)) * **deps-dev:** bump mypy-boto3-secretsmanager from 1.26.40 to 1.26.49 ([#1835](https://github.com/awslabs/aws-lambda-powertools-python/issues/1835)) @@ -2778,7 +2801,8 @@ * Merge pull request [#5](https://github.com/awslabs/aws-lambda-powertools-python/issues/5) from jfuss/feat/python38 -[Unreleased]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v2.6.0...HEAD +[Unreleased]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v2.7.0...HEAD +[v2.7.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v2.6.0...v2.7.0 [v2.6.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v2.5.0...v2.6.0 [v2.5.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v2.4.0...v2.5.0 [v2.4.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v2.3.1...v2.4.0 From d7c23f9c3cc790043a01bbfbe844f36b4e98edff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jan 2023 20:05:25 +0000 Subject: [PATCH 12/30] chore(deps-dev): bump mypy-boto3-s3 from 1.26.0.post1 to 1.26.58 (#1868) Bumps [mypy-boto3-s3](https://github.com/youtype/mypy_boto3_builder) from 1.26.0.post1 to 1.26.58. - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) --- updated-dependencies: - dependency-name: mypy-boto3-s3 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 | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 565f9510c40..0034f7eef14 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1467,14 +1467,14 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-s3" -version = "1.26.0.post1" -description = "Type annotations for boto3.S3 1.26.0 service generated with mypy-boto3-builder 7.11.10" +version = "1.26.58" +description = "Type annotations for boto3.S3 1.26.58 service generated with mypy-boto3-builder 7.12.3" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-s3-1.26.0.post1.tar.gz", hash = "sha256:6d7079f8c739dc993cbedad0736299c413b297814b73795a3855a79169ecc938"}, - {file = "mypy_boto3_s3-1.26.0.post1-py3-none-any.whl", hash = "sha256:7de2792ff0cc541b84cd46ff3a6aa2b6e5f267217f2203f27f6e4016bddc644d"}, + {file = "mypy-boto3-s3-1.26.58.tar.gz", hash = "sha256:02aa9514877147da996ea62e9d3d326d6b33f46c9c20b26f1e45fd125ba03518"}, + {file = "mypy_boto3_s3-1.26.58-py3-none-any.whl", hash = "sha256:34989e04ae85ae5e7b653ea28359e9caad12bdd7eac68071e2166409e5e39e66"}, ] [package.dependencies] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "8de3ccafeab629cdefa2d38ae10b1b9ca97d00fd9d4b0a2f4f641ae278d794ef" +content-hash = "fbee2b27c86f0cc43ddf20ec3a33292ac2624733a7850d522d514e231d24369b" diff --git a/pyproject.toml b/pyproject.toml index 7854d1810a9..1badeeeb33d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,7 @@ mypy-boto3-lambda = "^1.26.55" mypy-boto3-logs = "^1.26.53" mypy-boto3-secretsmanager = "^1.26.49" mypy-boto3-ssm = "^1.26.43" -mypy-boto3-s3 = "^1.26.0" +mypy-boto3-s3 = "^1.26.58" mypy-boto3-xray = "^1.26.11" types-requests = "^2.28.11" typing-extensions = "^4.4.0" From e7527e70ae5cb9c9648a841c25f3847623c7b8ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jan 2023 22:06:42 +0000 Subject: [PATCH 13/30] chore(deps-dev): bump aws-cdk-lib from 2.62.1 to 2.62.2 (#1869) Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.62.1 to 2.62.2. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.62.1...v2.62.2) --- updated-dependencies: - dependency-name: aws-cdk-lib 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 | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0034f7eef14..83c36e27073 100644 --- a/poetry.lock +++ b/poetry.lock @@ -110,14 +110,14 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.62.1" +version = "2.62.2" description = "Version 2 of the AWS Cloud Development Kit library" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk-lib-2.62.1.tar.gz", hash = "sha256:6becf9946c1d14c9e2b3a4caf07571b1fbc1f85192298cc15fb6dd143f60cf39"}, - {file = "aws_cdk_lib-2.62.1-py3-none-any.whl", hash = "sha256:ed897ff0291b19861d4f9b9f545cb8e7710579de646ccc4b8ed60808ba965a35"}, + {file = "aws-cdk-lib-2.62.2.tar.gz", hash = "sha256:f85000438d849a0522ffcd8e7cb5a70be5fa34339082d4d569734169c6d37b4d"}, + {file = "aws_cdk_lib-2.62.2-py3-none-any.whl", hash = "sha256:03dfb8303b00333177b18e3b60c95d738adf4d90086a5b1e707e896fdc234d52"}, ] [package.dependencies] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "fbee2b27c86f0cc43ddf20ec3a33292ac2624733a7850d522d514e231d24369b" +content-hash = "6593de2a17ba398072a78ad12e6d3ec19bb3f0ec70ee572502e5e8b3c1866fb9" diff --git a/pyproject.toml b/pyproject.toml index 1badeeeb33d..71b9ad96319 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" retry = "^0.9.2" pytest-xdist = "^3.1.0" -aws-cdk-lib = "^2.62.1" +aws-cdk-lib = "^2.62.2" "aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" From 3780a9547b61228e78f254999290ec5dccf0eeeb Mon Sep 17 00:00:00 2001 From: Ruben Fonseca Date: Mon, 30 Jan 2023 10:24:24 +0100 Subject: [PATCH 14/30] fix(tests): make sure multiple e2e tests run concurrently (#1861) --- .github/workflows/run-e2e-tests.yml | 1 + parallel_run_e2e.py | 2 +- tests/e2e/event_handler/conftest.py | 2 +- .../event_handler/test_header_serializer.py | 5 ++++ .../test_paths_ending_with_slash.py | 4 ++++ tests/e2e/idempotency/conftest.py | 4 ++-- .../idempotency/test_idempotency_dynamodb.py | 3 +++ tests/e2e/logger/conftest.py | 4 ++-- tests/e2e/logger/test_logger.py | 1 + tests/e2e/metrics/conftest.py | 4 ++-- tests/e2e/metrics/test_metrics.py | 2 ++ tests/e2e/parameters/conftest.py | 4 ++-- tests/e2e/parameters/infrastructure.py | 2 +- tests/e2e/parameters/test_appconfig.py | 1 + tests/e2e/parameters/test_ssm.py | 2 +- tests/e2e/pytest.ini | 2 ++ tests/e2e/streaming/conftest.py | 4 ++-- tests/e2e/streaming/test_s3_object.py | 18 ++++++++++++++ tests/e2e/tracer/conftest.py | 2 +- tests/e2e/tracer/test_tracer.py | 3 +++ tests/e2e/utils/functions.py | 24 ++++++++++++++++--- tests/e2e/utils/infrastructure.py | 3 +-- 22 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 tests/e2e/pytest.ini diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 06196b97f92..7a8fb00ebbe 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -26,6 +26,7 @@ jobs: id-token: write # needed to request JWT with GitHub's OIDC Token endpoint. docs: https://bit.ly/3MNgQO9 contents: read strategy: + fail-fast: false # needed so if a version fails, the others will still be able to complete and cleanup matrix: version: ["3.7", "3.8", "3.9"] if: ${{ github.actor != 'dependabot[bot]' }} diff --git a/parallel_run_e2e.py b/parallel_run_e2e.py index be3e1ab0cf8..1146f66931e 100755 --- a/parallel_run_e2e.py +++ b/parallel_run_e2e.py @@ -8,7 +8,7 @@ def main(): features = Path("tests/e2e").rglob("infrastructure.py") workers = len(list(features)) - 1 - command = f"poetry run pytest -n {workers} --dist loadfile -o log_cli=true tests/e2e" + command = f"poetry run pytest -n {workers} -o log_cli=true tests/e2e" result = subprocess.run(command.split(), shell=False) sys.exit(result.returncode) diff --git a/tests/e2e/event_handler/conftest.py b/tests/e2e/event_handler/conftest.py index 43941946ac7..664c870e1de 100644 --- a/tests/e2e/event_handler/conftest.py +++ b/tests/e2e/event_handler/conftest.py @@ -3,7 +3,7 @@ from tests.e2e.event_handler.infrastructure import EventHandlerStack -@pytest.fixture(autouse=True, scope="module") +@pytest.fixture(autouse=True, scope="package") def infrastructure(): """Setup and teardown logic for E2E test infrastructure diff --git a/tests/e2e/event_handler/test_header_serializer.py b/tests/e2e/event_handler/test_header_serializer.py index eedb69ccaad..5026bf6aa4a 100644 --- a/tests/e2e/event_handler/test_header_serializer.py +++ b/tests/e2e/event_handler/test_header_serializer.py @@ -36,6 +36,7 @@ def lambda_function_url_endpoint(infrastructure: dict) -> str: return infrastructure.get("LambdaFunctionUrl", "") +@pytest.mark.xdist_group(name="event_handler") def test_alb_headers_serializer(alb_basic_listener_endpoint): # GIVEN url = f"{alb_basic_listener_endpoint}/todos" @@ -74,6 +75,7 @@ def test_alb_headers_serializer(alb_basic_listener_endpoint): assert response.cookies.get(last_cookie.name) == last_cookie.value +@pytest.mark.xdist_group(name="event_handler") def test_alb_multi_value_headers_serializer(alb_multi_value_header_listener_endpoint): # GIVEN url = f"{alb_multi_value_header_listener_endpoint}/todos" @@ -112,6 +114,7 @@ def test_alb_multi_value_headers_serializer(alb_multi_value_header_listener_endp assert response.cookies.get(cookie.name) == cookie.value +@pytest.mark.xdist_group(name="event_handler") def test_api_gateway_rest_headers_serializer(apigw_rest_endpoint): # GIVEN url = f"{apigw_rest_endpoint}todos" @@ -147,6 +150,7 @@ def test_api_gateway_rest_headers_serializer(apigw_rest_endpoint): assert response.cookies.get(cookie.name) == cookie.value +@pytest.mark.xdist_group(name="event_handler") def test_api_gateway_http_headers_serializer(apigw_http_endpoint): # GIVEN url = f"{apigw_http_endpoint}todos" @@ -182,6 +186,7 @@ def test_api_gateway_http_headers_serializer(apigw_http_endpoint): assert response.cookies.get(cookie.name) == cookie.value +@pytest.mark.xdist_group(name="event_handler") def test_lambda_function_url_headers_serializer(lambda_function_url_endpoint): # GIVEN url = f"{lambda_function_url_endpoint}todos" # the function url endpoint already has the trailing / diff --git a/tests/e2e/event_handler/test_paths_ending_with_slash.py b/tests/e2e/event_handler/test_paths_ending_with_slash.py index 4c1461d6fc5..1944768c2ff 100644 --- a/tests/e2e/event_handler/test_paths_ending_with_slash.py +++ b/tests/e2e/event_handler/test_paths_ending_with_slash.py @@ -33,6 +33,7 @@ def lambda_function_url_endpoint(infrastructure: dict) -> str: return infrastructure.get("LambdaFunctionUrl", "") +@pytest.mark.xdist_group(name="event_handler") def test_api_gateway_rest_trailing_slash(apigw_rest_endpoint): # GIVEN API URL ends in a trailing slash url = f"{apigw_rest_endpoint}todos/" @@ -51,6 +52,7 @@ def test_api_gateway_rest_trailing_slash(apigw_rest_endpoint): assert response.status_code == 200 +@pytest.mark.xdist_group(name="event_handler") def test_api_gateway_http_trailing_slash(apigw_http_endpoint): # GIVEN the URL for the API ends in a trailing slash API gateway should return a 404 url = f"{apigw_http_endpoint}todos/" @@ -67,6 +69,7 @@ def test_api_gateway_http_trailing_slash(apigw_http_endpoint): ) +@pytest.mark.xdist_group(name="event_handler") def test_lambda_function_url_trailing_slash(lambda_function_url_endpoint): # GIVEN the URL for the API ends in a trailing slash it should behave as if there was not one url = f"{lambda_function_url_endpoint}todos/" # the function url endpoint already has the trailing / @@ -83,6 +86,7 @@ def test_lambda_function_url_trailing_slash(lambda_function_url_endpoint): ) +@pytest.mark.xdist_group(name="event_handler") def test_alb_url_trailing_slash(alb_multi_value_header_listener_endpoint): # GIVEN url has a trailing slash - it should behave as if there was not one url = f"{alb_multi_value_header_listener_endpoint}/todos/" diff --git a/tests/e2e/idempotency/conftest.py b/tests/e2e/idempotency/conftest.py index 24a7c71c1f2..61578d904a6 100644 --- a/tests/e2e/idempotency/conftest.py +++ b/tests/e2e/idempotency/conftest.py @@ -3,8 +3,8 @@ from tests.e2e.idempotency.infrastructure import IdempotencyDynamoDBStack -@pytest.fixture(autouse=True, scope="module") -def infrastructure(tmp_path_factory, worker_id): +@pytest.fixture(autouse=True, scope="package") +def infrastructure(): """Setup and teardown logic for E2E test infrastructure Yields diff --git a/tests/e2e/idempotency/test_idempotency_dynamodb.py b/tests/e2e/idempotency/test_idempotency_dynamodb.py index 87b61d285ec..d3452a1a161 100644 --- a/tests/e2e/idempotency/test_idempotency_dynamodb.py +++ b/tests/e2e/idempotency/test_idempotency_dynamodb.py @@ -27,6 +27,7 @@ def idempotency_table_name(infrastructure: dict) -> str: return infrastructure.get("DynamoDBTable", "") +@pytest.mark.xdist_group(name="idempotency") def test_ttl_caching_expiration_idempotency(ttl_cache_expiration_handler_fn_arn: str): # GIVEN payload = json.dumps({"message": "Lambda Powertools - TTL 5s"}) @@ -56,6 +57,7 @@ def test_ttl_caching_expiration_idempotency(ttl_cache_expiration_handler_fn_arn: assert third_execution_response != second_execution_response +@pytest.mark.xdist_group(name="idempotency") def test_ttl_caching_timeout_idempotency(ttl_cache_timeout_handler_fn_arn: str): # GIVEN payload_timeout_execution = json.dumps({"sleep": 5, "message": "Lambda Powertools - TTL 1s"}) @@ -79,6 +81,7 @@ def test_ttl_caching_timeout_idempotency(ttl_cache_timeout_handler_fn_arn: str): assert payload_working_execution == execution_working_response +@pytest.mark.xdist_group(name="idempotency") def test_parallel_execution_idempotency(parallel_execution_handler_fn_arn: str): # GIVEN arguments = json.dumps({"message": "Lambda Powertools - Parallel execution"}) diff --git a/tests/e2e/logger/conftest.py b/tests/e2e/logger/conftest.py index a31be77031b..ad336931a93 100644 --- a/tests/e2e/logger/conftest.py +++ b/tests/e2e/logger/conftest.py @@ -3,8 +3,8 @@ from tests.e2e.logger.infrastructure import LoggerStack -@pytest.fixture(autouse=True, scope="module") -def infrastructure(tmp_path_factory, worker_id): +@pytest.fixture(autouse=True, scope="package") +def infrastructure(): """Setup and teardown logic for E2E test infrastructure Yields diff --git a/tests/e2e/logger/test_logger.py b/tests/e2e/logger/test_logger.py index e5c27dd0a8f..28ee9c0aac0 100644 --- a/tests/e2e/logger/test_logger.py +++ b/tests/e2e/logger/test_logger.py @@ -17,6 +17,7 @@ def basic_handler_fn_arn(infrastructure: dict) -> str: return infrastructure.get("BasicHandlerArn", "") +@pytest.mark.xdist_group(name="logger") def test_basic_lambda_logs_visible(basic_handler_fn, basic_handler_fn_arn): # GIVEN message = "logs should be visible with default settings" diff --git a/tests/e2e/metrics/conftest.py b/tests/e2e/metrics/conftest.py index 2f72e7950be..197aaff847f 100644 --- a/tests/e2e/metrics/conftest.py +++ b/tests/e2e/metrics/conftest.py @@ -3,8 +3,8 @@ from tests.e2e.metrics.infrastructure import MetricsStack -@pytest.fixture(autouse=True, scope="module") -def infrastructure(tmp_path_factory, worker_id): +@pytest.fixture(autouse=True, scope="package") +def infrastructure(): """Setup and teardown logic for E2E test infrastructure Yields diff --git a/tests/e2e/metrics/test_metrics.py b/tests/e2e/metrics/test_metrics.py index 516f93ac1f0..192cbcc25af 100644 --- a/tests/e2e/metrics/test_metrics.py +++ b/tests/e2e/metrics/test_metrics.py @@ -28,6 +28,7 @@ def cold_start_fn_arn(infrastructure: dict) -> str: METRIC_NAMESPACE = "powertools-e2e-metric" +@pytest.mark.xdist_group(name="metrics") def test_basic_lambda_metric_is_visible(basic_handler_fn: str, basic_handler_fn_arn: str): # GIVEN metric_name = data_builder.build_metric_name() @@ -47,6 +48,7 @@ def test_basic_lambda_metric_is_visible(basic_handler_fn: str, basic_handler_fn_ assert metric_values == [3.0] +@pytest.mark.xdist_group(name="metrics") def test_cold_start_metric(cold_start_fn_arn: str, cold_start_fn: str): # GIVEN metric_name = "ColdStart" diff --git a/tests/e2e/parameters/conftest.py b/tests/e2e/parameters/conftest.py index f4c9d7396dd..99146607384 100644 --- a/tests/e2e/parameters/conftest.py +++ b/tests/e2e/parameters/conftest.py @@ -3,8 +3,8 @@ from tests.e2e.parameters.infrastructure import ParametersStack -@pytest.fixture(autouse=True, scope="module") -def infrastructure(tmp_path_factory, worker_id): +@pytest.fixture(autouse=True, scope="package") +def infrastructure(): """Setup and teardown logic for E2E test infrastructure Yields diff --git a/tests/e2e/parameters/infrastructure.py b/tests/e2e/parameters/infrastructure.py index e2cd5101ba7..018fceab2aa 100644 --- a/tests/e2e/parameters/infrastructure.py +++ b/tests/e2e/parameters/infrastructure.py @@ -27,7 +27,7 @@ def create_resources(self): iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ - "ssm:GetParameter", + "ssm:GetParameters", ], resources=[f"arn:aws:ssm:{self.region}:{self.account_id}:parameter/powertools/e2e/parameters/*"], ) diff --git a/tests/e2e/parameters/test_appconfig.py b/tests/e2e/parameters/test_appconfig.py index 0129adb1515..7cf6f87067f 100644 --- a/tests/e2e/parameters/test_appconfig.py +++ b/tests/e2e/parameters/test_appconfig.py @@ -35,6 +35,7 @@ def parameter_appconfig_freeform_profile(infrastructure: dict) -> str: return infrastructure.get("AppConfigProfile", "") +@pytest.mark.xdist_group(name="parameters") def test_get_parameter_appconfig_freeform( parameter_appconfig_freeform_handler_fn_arn: str, parameter_appconfig_freeform_value: str, diff --git a/tests/e2e/parameters/test_ssm.py b/tests/e2e/parameters/test_ssm.py index 7e9614f8ea0..239813fab51 100644 --- a/tests/e2e/parameters/test_ssm.py +++ b/tests/e2e/parameters/test_ssm.py @@ -17,7 +17,7 @@ def parameters_list(infrastructure: dict) -> List[str]: return json.loads(param_list) -# +@pytest.mark.xdist_group(name="parameters") def test_get_parameters_by_name( ssm_get_parameters_by_name_fn_arn: str, parameters_list: str, diff --git a/tests/e2e/pytest.ini b/tests/e2e/pytest.ini new file mode 100644 index 00000000000..3fc35fa5847 --- /dev/null +++ b/tests/e2e/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = -ra -vv --dist loadgroup \ No newline at end of file diff --git a/tests/e2e/streaming/conftest.py b/tests/e2e/streaming/conftest.py index c3a44365d39..94f7f212af0 100644 --- a/tests/e2e/streaming/conftest.py +++ b/tests/e2e/streaming/conftest.py @@ -3,8 +3,8 @@ from tests.e2e.streaming.infrastructure import StreamingStack -@pytest.fixture(autouse=True, scope="module") -def infrastructure(tmp_path_factory, worker_id): +@pytest.fixture(autouse=True, scope="package") +def infrastructure(): """Setup and teardown logic for E2E test infrastructure Yields diff --git a/tests/e2e/streaming/test_s3_object.py b/tests/e2e/streaming/test_s3_object.py index 1e2fe1a0222..fe4fd638b10 100644 --- a/tests/e2e/streaming/test_s3_object.py +++ b/tests/e2e/streaming/test_s3_object.py @@ -21,6 +21,7 @@ def s3_object_handler_fn_arn(infrastructure: dict) -> str: return infrastructure.get("S3ObjectHandler", "") +@pytest.mark.xdist_group(name="streaming") def get_object_version(bucket, key) -> str: s3 = boto3.client("s3") versions = s3.list_object_versions(Bucket=bucket) @@ -43,6 +44,7 @@ def get_lambda_result_payload(s3_object_handler_fn_arn: str, payload: dict) -> d return json.loads(handler_result["Payload"].read()) +@pytest.mark.xdist_group(name="streaming") def test_s3_object_size(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "plain.txt"} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) @@ -50,6 +52,7 @@ def test_s3_object_size(s3_object_handler_fn_arn, regular_bucket_name): assert result.get("body") == "hello world" +@pytest.mark.xdist_group(name="streaming") def test_s3_versioned_object_size(s3_object_handler_fn_arn, versioned_bucket_name): key = "plain.txt" payload = { @@ -62,18 +65,21 @@ def test_s3_versioned_object_size(s3_object_handler_fn_arn, versioned_bucket_nam assert result.get("body") == "hello world" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_non_existent(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "NOTEXISTENT.txt"} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("error") == "Not found" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_csv_constructor(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "csv.txt", "is_csv": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("body") == {"name": "hello", "value": "world"} +@pytest.mark.xdist_group(name="streaming") def test_s3_versioned_object_csv_constructor(s3_object_handler_fn_arn, versioned_bucket_name): key = "csv.txt" payload = { @@ -86,24 +92,28 @@ def test_s3_versioned_object_csv_constructor(s3_object_handler_fn_arn, versioned assert result.get("body") == {"name": "hello", "value": "world"} +@pytest.mark.xdist_group(name="streaming") def test_s3_object_csv_transform(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "csv.txt", "transform_csv": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("body") == {"name": "hello", "value": "world"} +@pytest.mark.xdist_group(name="streaming") def test_s3_object_csv_transform_in_place(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "csv.txt", "transform_csv": True, "in_place": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("body") == {"name": "hello", "value": "world"} +@pytest.mark.xdist_group(name="streaming") def test_s3_object_csv_gzip_constructor(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "csv.txt.gz", "is_csv": True, "is_gzip": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("body") == {"name": "hello", "value": "world"} +@pytest.mark.xdist_group(name="streaming") def test_s3_versioned_object_csv_gzip_constructor(s3_object_handler_fn_arn, versioned_bucket_name): key = "csv.txt.gz" payload = { @@ -117,12 +127,14 @@ def test_s3_versioned_object_csv_gzip_constructor(s3_object_handler_fn_arn, vers assert result.get("body") == {"name": "hello", "value": "world"} +@pytest.mark.xdist_group(name="streaming") def test_s3_object_gzip_constructor(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "plain.txt.gz", "is_gzip": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("body") == "hello world" +@pytest.mark.xdist_group(name="streaming") def test_s3_versioned_object_gzip_constructor(s3_object_handler_fn_arn, versioned_bucket_name): key = "plain.txt.gz" payload = { @@ -135,18 +147,21 @@ def test_s3_versioned_object_gzip_constructor(s3_object_handler_fn_arn, versione assert result.get("body") == "hello world" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_gzip_transform(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "plain.txt.gz", "transform_gzip": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("body") == "hello world" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_gzip_transform_in_place(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "plain.txt.gz", "transform_gzip": True, "in_place": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) assert result.get("body") == "hello world" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_zip_transform(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "fileset.zip", "transform_zip": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) @@ -154,6 +169,7 @@ def test_s3_object_zip_transform(s3_object_handler_fn_arn, regular_bucket_name): assert result.get("body") == "This is file 2" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_zip_transform_in_place(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "fileset.zip", "transform_zip": True, "in_place": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) @@ -161,6 +177,7 @@ def test_s3_object_zip_transform_in_place(s3_object_handler_fn_arn, regular_buck assert result.get("body") == "This is file 2" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_zip_lzma_transform(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "fileset.zip.lzma", "transform_zip_lzma": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) @@ -168,6 +185,7 @@ def test_s3_object_zip_lzma_transform(s3_object_handler_fn_arn, regular_bucket_n assert result.get("body") == "This is file 2" +@pytest.mark.xdist_group(name="streaming") def test_s3_object_zip_lzma_transform_in_place(s3_object_handler_fn_arn, regular_bucket_name): payload = {"bucket": regular_bucket_name, "key": "fileset.zip.lzma", "transform_zip_lzma": True, "in_place": True} result = get_lambda_result_payload(s3_object_handler_fn_arn, payload) diff --git a/tests/e2e/tracer/conftest.py b/tests/e2e/tracer/conftest.py index afb34ffee2b..d3728ab91ba 100644 --- a/tests/e2e/tracer/conftest.py +++ b/tests/e2e/tracer/conftest.py @@ -3,7 +3,7 @@ from tests.e2e.tracer.infrastructure import TracerStack -@pytest.fixture(autouse=True, scope="module") +@pytest.fixture(autouse=True, scope="package") def infrastructure(): """Setup and teardown logic for E2E test infrastructure diff --git a/tests/e2e/tracer/test_tracer.py b/tests/e2e/tracer/test_tracer.py index e2abc5af6bc..5dfe68ee08c 100644 --- a/tests/e2e/tracer/test_tracer.py +++ b/tests/e2e/tracer/test_tracer.py @@ -36,6 +36,7 @@ def async_fn(infrastructure: dict) -> str: return infrastructure.get("AsyncCapture", "") +@pytest.mark.xdist_group(name="tracer") def test_lambda_handler_trace_is_visible(basic_handler_fn_arn: str, basic_handler_fn: str): # GIVEN service = data_builder.build_service_name() @@ -64,6 +65,7 @@ def test_lambda_handler_trace_is_visible(basic_handler_fn_arn: str, basic_handle assert len(trace.get_subsegment(name=method_subsegment)) == 2 +@pytest.mark.xdist_group(name="tracer") def test_lambda_handler_trace_multiple_functions_same_name(same_function_name_arn: str, same_function_name_fn: str): # GIVEN service = data_builder.build_service_name() @@ -90,6 +92,7 @@ def test_lambda_handler_trace_multiple_functions_same_name(same_function_name_ar assert len(trace.get_subsegment(name=method_subsegment_comments)) == 1 +@pytest.mark.xdist_group(name="tracer") def test_async_trace_is_visible(async_fn_arn: str, async_fn: str): # GIVEN service = data_builder.build_service_name() diff --git a/tests/e2e/utils/functions.py b/tests/e2e/utils/functions.py index 7b64c439298..db70f4ab6b9 100644 --- a/tests/e2e/utils/functions.py +++ b/tests/e2e/utils/functions.py @@ -1,4 +1,6 @@ -from concurrent.futures import ThreadPoolExecutor +import time +from concurrent.futures import Future, ThreadPoolExecutor +from typing import List from tests.e2e.utils import data_fetcher # noqa F401 @@ -6,9 +8,25 @@ def execute_lambdas_in_parallel(function_name: str, lambdas_arn: list, arguments: str): result_list = [] with ThreadPoolExecutor() as executor: - running_tasks = executor.map(lambda exec: eval(function_name)(*exec), [(arn, arguments) for arn in lambdas_arn]) + running_tasks: List[Future] = [] + for arn in lambdas_arn: + # Sleep 0.5, 1, 1.5, ... seconds between each invocation. This way + # we can guarantee that lambdas are executed in parallel, but they are + # called in the same "order" as they are passed in, thus guaranteeing that + # we can assert on the correct output. + time.sleep(0.5 * len(running_tasks)) + running_tasks.append( + executor.submit( + lambda lname, larn, largs: eval(lname)(larn, largs), + function_name, + arn, + arguments, + ) + ) + executor.shutdown(wait=True) + for running_task in running_tasks: - result_list.append(running_task) + result_list.append(running_task.result()) return result_list diff --git a/tests/e2e/utils/infrastructure.py b/tests/e2e/utils/infrastructure.py index daf1a817c89..29e45b83abf 100644 --- a/tests/e2e/utils/infrastructure.py +++ b/tests/e2e/utils/infrastructure.py @@ -1,7 +1,6 @@ import json import logging import os -import platform import subprocess import sys import textwrap @@ -57,7 +56,7 @@ def __init__(self) -> None: self._feature_infra_module_path = self.feature_path / "infrastructure" self._feature_infra_file = self.feature_path / "infrastructure.py" self._handlers_dir = self.feature_path / "handlers" - self._cdk_out_dir: Path = CDK_OUT_PATH / "-".join(platform.python_version_tuple()) / self.feature_name + self._cdk_out_dir: Path = CDK_OUT_PATH / self.feature_name self._stack_outputs_file = f'{self._cdk_out_dir / "stack_outputs.json"}' if not self._feature_infra_file.exists(): From 40f8946dc11d080a5e809d329cf7bf0fa0b38285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Fonseca?= Date: Mon, 30 Jan 2023 10:27:03 +0100 Subject: [PATCH 15/30] fix(tests): remove custom workers --- .github/actionlint.yaml | 5 ----- .github/workflows/publish_v2_layer.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- 4 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 .github/actionlint.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml deleted file mode 100644 index e96446a551a..00000000000 --- a/.github/actionlint.yaml +++ /dev/null @@ -1,5 +0,0 @@ -self-hosted-runner: - labels: - - aws-lambda-powertools_ubuntu-latest_4-core - - aws-lambda-powertools_ubuntu-latest_8-core - - aws-lambda-powertools_ubuntu-latest_16-core diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 96f25cd9dd8..6d91d908ac0 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -32,7 +32,7 @@ jobs: build-layer: permissions: contents: read - runs-on: aws-lambda-powertools_ubuntu-latest_8-core + runs-on: ubuntu-latest defaults: run: working-directory: ./layer diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 77050bc25fd..5d6d509aec4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,7 +49,7 @@ on: jobs: release: environment: release - runs-on: aws-lambda-powertools_ubuntu-latest_4-core + runs-on: ubuntu-latest permissions: contents: write outputs: diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 7a8fb00ebbe..f81f994b908 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -21,7 +21,7 @@ env: jobs: run: - runs-on: aws-lambda-powertools_ubuntu-latest_8-core + runs-on: ubuntu-latest permissions: id-token: write # needed to request JWT with GitHub's OIDC Token endpoint. docs: https://bit.ly/3MNgQO9 contents: read From 2653f39705334afda53255339bec2d98f89043a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Fonseca?= Date: Mon, 30 Jan 2023 11:38:41 +0100 Subject: [PATCH 16/30] Revert "fix(tests): remove custom workers" This reverts commit 40f8946dc11d080a5e809d329cf7bf0fa0b38285. --- .github/actionlint.yaml | 5 +++++ .github/workflows/publish_v2_layer.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .github/actionlint.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 00000000000..e96446a551a --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,5 @@ +self-hosted-runner: + labels: + - aws-lambda-powertools_ubuntu-latest_4-core + - aws-lambda-powertools_ubuntu-latest_8-core + - aws-lambda-powertools_ubuntu-latest_16-core diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 6d91d908ac0..96f25cd9dd8 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -32,7 +32,7 @@ jobs: build-layer: permissions: contents: read - runs-on: ubuntu-latest + runs-on: aws-lambda-powertools_ubuntu-latest_8-core defaults: run: working-directory: ./layer diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d6d509aec4..77050bc25fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,7 +49,7 @@ on: jobs: release: environment: release - runs-on: ubuntu-latest + runs-on: aws-lambda-powertools_ubuntu-latest_4-core permissions: contents: write outputs: diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index f81f994b908..7a8fb00ebbe 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -21,7 +21,7 @@ env: jobs: run: - runs-on: ubuntu-latest + runs-on: aws-lambda-powertools_ubuntu-latest_8-core permissions: id-token: write # needed to request JWT with GitHub's OIDC Token endpoint. docs: https://bit.ly/3MNgQO9 contents: read From 222759ee90aa64ece403f9e6ebdd7b005206ee65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 21:23:06 +0100 Subject: [PATCH 17/30] chore(deps-dev): bump isort from 5.11.4 to 5.11.5 (#1875) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 83c36e27073..5acf63010e4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -901,19 +901,19 @@ files = [ [[package]] name = "isort" -version = "5.11.4" +version = "5.11.5" description = "A Python utility / library to sort Python imports." category = "dev" optional = false python-versions = ">=3.7.0" files = [ - {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, - {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, + {file = "isort-5.11.5-py3-none-any.whl", hash = "sha256:ba1d72fb2595a01c7895a5128f9585a5cc4b6d395f1c8d514989b9a7eb2a8746"}, + {file = "isort-5.11.5.tar.gz", hash = "sha256:6be1f76a507cb2ecf16c7cf14a37e41609ca082330be4e3436a18ef74add55db"}, ] [package.extras] colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] requirements-deprecated-finder = ["pip-api", "pipreqs"] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "6593de2a17ba398072a78ad12e6d3ec19bb3f0ec70ee572502e5e8b3c1866fb9" +content-hash = "df4bd0eee1900fc236eb117555746b5e119bae5a3776e97df7f7d285f4071661" diff --git a/pyproject.toml b/pyproject.toml index 71b9ad96319..e48c49a0247 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ flake8-debugger = "^4.0.0" flake8-fixme = "^1.1.1" flake8-variables-names = "^0.0.5" flake8-black = "^0.3.6" -isort = "^5.11.4" +isort = "^5.11.5" pytest-cov = "^4.0.0" pytest-mock = "^3.5.1" pdoc3 = "^0.10.0" From 7d5866fd295a2f72268a56b7465b8a9eb0e34917 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 21:25:01 +0100 Subject: [PATCH 18/30] chore(deps): bump docker/setup-buildx-action from 2.0.0 to 2.4.0 (#1873) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish_v2_layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 96f25cd9dd8..b3e6f143dc5 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -65,7 +65,7 @@ jobs: # NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM) - name: Set up Docker Buildx id: builder - uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 # v2.0.0 + uses: docker/setup-buildx-action@15c905b16b06416d2086efa066dd8e3a35cc7f98 # v2.4.0 with: install: true driver: docker From bea1c0e1d8efcceec5aa396ace1ef8490a41c57e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 21:31:16 +0100 Subject: [PATCH 19/30] chore(deps-dev): bump mkdocs-material from 9.0.6 to 9.0.8 (#1874) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5acf63010e4..c4db2a456b1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1282,14 +1282,14 @@ mkdocs = ">=0.17" [[package]] name = "mkdocs-material" -version = "9.0.6" +version = "9.0.8" description = "Documentation that simply works" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mkdocs_material-9.0.6-py3-none-any.whl", hash = "sha256:4a71195ddc100dddf07d4b23b53373f36c5f0f1010fa4ea301ca7a8e949dd9e7"}, - {file = "mkdocs_material-9.0.6.tar.gz", hash = "sha256:6065b573e38746dc267d7fc84252be31b73da955b2ce553687806b6030e51ee0"}, + {file = "mkdocs_material-9.0.8-py3-none-any.whl", hash = "sha256:03f8a2249627efb91a57d9f4a4e298d2d61d6e65fe2a864cc5961dc540bdd540"}, + {file = "mkdocs_material-9.0.8.tar.gz", hash = "sha256:268e7aab0b8585352400b4e93bfe4efd0ca213005d7bae1a0ec69b7ded205fcd"}, ] [package.dependencies] @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "df4bd0eee1900fc236eb117555746b5e119bae5a3776e97df7f7d285f4071661" +content-hash = "599f640b527a1990f40b58c1a0915388385a3054d148dd83e840687ca6134c14" diff --git a/pyproject.toml b/pyproject.toml index e48c49a0247..3e3f2903f2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ mypy-boto3-s3 = "^1.26.58" mypy-boto3-xray = "^1.26.11" types-requests = "^2.28.11" typing-extensions = "^4.4.0" -mkdocs-material = "^9.0.6" +mkdocs-material = "^9.0.8" filelock = "^3.9.0" checksumdir = "^1.2.0" mypy-boto3-appconfigdata = "^1.26.0" From 289a874bad1e772c53de3f02da140067429b01f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 12:56:40 +0100 Subject: [PATCH 20/30] chore(deps-dev): bump flake8-bugbear from 22.12.6 to 23.1.20 (#1854) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rúben Fonseca --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- tests/functional/idempotency/test_idempotency.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index c4db2a456b1..b06738c5b3a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -597,14 +597,14 @@ develop = ["build", "twine"] [[package]] name = "flake8-bugbear" -version = "22.12.6" +version = "23.1.20" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "flake8-bugbear-22.12.6.tar.gz", hash = "sha256:4cdb2c06e229971104443ae293e75e64c6107798229202fbe4f4091427a30ac0"}, - {file = "flake8_bugbear-22.12.6-py3-none-any.whl", hash = "sha256:b69a510634f8a9c298dfda2b18a8036455e6b19ecac4fe582e4d7a0abfa50a30"}, + {file = "flake8-bugbear-23.1.20.tar.gz", hash = "sha256:55902ab5a48c5ea53d8689ecd146eda548e72f2724192b9c1d68f6d975d13c06"}, + {file = "flake8_bugbear-23.1.20-py3-none-any.whl", hash = "sha256:04a115e5f9c8e87c38bdbbcdf9f58223ffe05469c07c9a7bd8633330bc4d078b"}, ] [package.dependencies] @@ -612,7 +612,7 @@ attrs = ">=19.2.0" flake8 = ">=3.0.0" [package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] [[package]] name = "flake8-builtins" @@ -2666,4 +2666,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "599f640b527a1990f40b58c1a0915388385a3054d148dd83e840687ca6134c14" +content-hash = "56cd214c7cf052567ee4dc5829d2801b57dc8b484e185ccccac149275695619e" diff --git a/pyproject.toml b/pyproject.toml index 3e3f2903f2d..e9aed57ce76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ bandit = "^1.7.1" radon = "^5.1.0" xenon = "^0.9.0" flake8-eradicate = "^1.2.1" -flake8-bugbear = "^22.12.6" +flake8-bugbear = "^23.1.20" mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" retry = "^0.9.2" diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index 8d78c1bdf2b..e3131747e48 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -397,7 +397,7 @@ def test_idempotent_lambda_exception( def lambda_handler(event, context): raise Exception("Something went wrong!") - with pytest.raises(Exception): + with pytest.raises(Exception, match="Something went wrong!"): lambda_handler(lambda_apigw_event, lambda_context) stubber.assert_no_pending_responses() From 04ee1d03c45067c8143c14c809065f1c1acab6a4 Mon Sep 17 00:00:00 2001 From: Ruben Fonseca Date: Tue, 31 Jan 2023 14:08:32 +0100 Subject: [PATCH 21/30] fix(tests): make logs fetching more robust (#1878) Co-authored-by: Heitor Lessa --- tests/e2e/logger/test_logger.py | 2 +- tests/e2e/utils/data_fetcher/logs.py | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/e2e/logger/test_logger.py b/tests/e2e/logger/test_logger.py index 28ee9c0aac0..80379125d11 100644 --- a/tests/e2e/logger/test_logger.py +++ b/tests/e2e/logger/test_logger.py @@ -30,7 +30,7 @@ def test_basic_lambda_logs_visible(basic_handler_fn, basic_handler_fn_arn): data_fetcher.get_lambda_response(lambda_arn=basic_handler_fn_arn, payload=payload) # THEN - logs = data_fetcher.get_logs(function_name=basic_handler_fn, start_time=execution_time) + logs = data_fetcher.get_logs(function_name=basic_handler_fn, start_time=execution_time, minimum_log_entries=2) assert len(logs) == 2 assert len(logs.get_cold_start_log()) == 1 diff --git a/tests/e2e/utils/data_fetcher/logs.py b/tests/e2e/utils/data_fetcher/logs.py index a005009f5f5..79fcee9290b 100644 --- a/tests/e2e/utils/data_fetcher/logs.py +++ b/tests/e2e/utils/data_fetcher/logs.py @@ -29,6 +29,7 @@ def __init__( start_time: datetime, log_client: Optional[CloudWatchLogsClient] = None, filter_expression: Optional[str] = None, + minimum_log_entries: int = 1, ): """Fetch and expose Powertools Logger logs from CloudWatch Logs @@ -42,12 +43,15 @@ def __init__( Amazon CloudWatch Logs Client, by default boto3.client('logs) filter_expression : Optional[str], optional CloudWatch Logs Filter Pattern expression, by default "message" + minimum_log_entries: int + Minimum number of log entries to be retrieved before exhausting retry attempts """ self.function_name = function_name self.start_time = int(start_time.timestamp()) self.log_client = log_client or boto3.client("logs") self.filter_expression = filter_expression or "message" # Logger message key self.log_group = f"/aws/lambda/{self.function_name}" + self.minimum_log_entries = minimum_log_entries self.logs: List[Log] = self._get_logs() def get_log(self, key: str, value: Optional[any] = None) -> List[Log]: @@ -112,6 +116,11 @@ def _get_logs(self) -> List[Log]: continue filtered_logs.append(message) + if len(filtered_logs) < self.minimum_log_entries: + raise ValueError( + f"Number of log entries found doesn't meet minimum required ({self.minimum_log_entries}). Repeating..." + ) + return filtered_logs def __len__(self) -> int: @@ -122,6 +131,7 @@ def __len__(self) -> int: def get_logs( function_name: str, start_time: datetime, + minimum_log_entries: int = 1, filter_expression: Optional[str] = None, log_client: Optional[CloudWatchLogsClient] = None, ) -> LogFetcher: @@ -133,6 +143,8 @@ def get_logs( Name of Lambda function to fetch logs for start_time : datetime Start date range to filter traces + minimum_log_entries : int + Minimum number of log entries to be retrieved before exhausting retry attempts log_client : Optional[CloudWatchLogsClient], optional Amazon CloudWatch Logs Client, by default boto3.client('logs) filter_expression : Optional[str], optional @@ -144,5 +156,9 @@ def get_logs( LogFetcher instance with logs available as properties and methods """ return LogFetcher( - function_name=function_name, start_time=start_time, filter_expression=filter_expression, log_client=log_client + function_name=function_name, + start_time=start_time, + filter_expression=filter_expression, + log_client=log_client, + minimum_log_entries=minimum_log_entries, ) From 3314893eef355fe62be1a6d2465abef04cf821a1 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 31 Jan 2023 13:40:01 +0000 Subject: [PATCH 22/30] docs(parameters): snippets split, improved, and lint (#1564) * chore(parameters): refactoring examples * chore(parameters): adding cache examples * chore(parameters): adding builtin examples and fix mypy errors * chore(parameters): adding all providers with custom config * chore(parameters): adding custom provider * chore(parameters): adding custom provider * chore(parameters): adding custom provider * chore(parameters): adding DynamoDB provider * chore(parameters): adding tests - mock * chore(parameters): adding more tests * chore(parameters): adding appconfig builtin provider * chore(parameters): adding final examples * chore(parameters): adding final examples * chore(parameters): highlights - small changes * fix(docs): broken link in boto3_session * fix(docs): improve constrast ratio * fix(docs): typing and correctness on null endpoint * (chore): addressing Ruben's feedbacks * (chore): import errors --------- Signed-off-by: Leandro Damascena Co-authored-by: heitorlessa --- docs/utilities/parameters.md | 722 ++++++------------ .../sam/sam_dynamodb_custom_fields.yaml | 22 + .../sam/sam_dynamodb_table_recursive.yaml | 22 + .../sam/sam_dynamodb_table_single.yaml | 18 + .../parameters/src/appconfig_force_fetch.py | 21 + .../parameters/src/appconfig_with_cache.py | 21 + .../src/builtin_provider_appconfig.py | 23 + ...iltin_provider_dynamodb_custom_endpoint.py | 22 + ...builtin_provider_dynamodb_custom_fields.py | 24 + ...n_provider_dynamodb_recursive_parameter.py | 33 + ...ltin_provider_dynamodb_single_parameter.py | 22 + .../parameters/src/builtin_provider_secret.py | 27 + ...uiltin_provider_ssm_recursive_parameter.py | 44 ++ .../builtin_provider_ssm_single_parameter.py | 25 + .../src/builtin_provider_ssm_with_decrypt.py | 28 + .../builtin_provider_ssm_with_no_recursive.py | 39 + .../src/custom_boto3_all_providers.py | 17 + examples/parameters/src/custom_boto_client.py | 13 + examples/parameters/src/custom_boto_config.py | 13 + .../parameters/src/custom_boto_session.py | 13 + examples/parameters/src/custom_provider_s3.py | 52 ++ .../parameters/src/custom_provider_vault.py | 36 + .../get_parameter_by_name_error_handling.py | 21 + .../src/getting_started_appconfig.py | 19 + .../src/getting_started_parameter_by_name.py | 17 + ...getting_started_recursive_ssm_parameter.py | 26 + .../parameters/src/getting_started_secret.py | 23 + .../getting_started_single_ssm_parameter.py | 17 + .../src/handling_error_transform.py | 22 + .../recursive_ssm_parameter_force_fetch.py | 25 + .../src/recursive_ssm_parameter_with_cache.py | 25 + examples/parameters/src/secret_force_fetch.py | 23 + examples/parameters/src/secret_with_cache.py | 23 + .../src/single_ssm_parameter_force_fetch.py | 19 + .../src/single_ssm_parameter_with_cache.py | 19 + .../src/working_with_auto_transform.py | 10 + .../src/working_with_own_provider_s3.py | 30 + .../src/working_with_own_provider_vault.py | 35 + .../working_with_sdk_additional_arguments.py | 11 + .../src/working_with_transform_high_level.py | 19 + .../src/working_with_transform_provider.py | 23 + examples/parameters/tests/src/__init__.py | 0 examples/parameters/tests/src/app.py | 10 + examples/parameters/tests/src/single_mock.py | 7 + .../tests/test_clear_cache_global.py | 24 + .../tests/test_clear_cache_method.py | 22 + examples/parameters/tests/test_single_mock.py | 10 + .../parameters/tests/test_with_fixture.py | 16 + .../parameters/tests/test_with_monkeypatch.py | 13 + mypy.ini | 3 + poetry.lock | 612 +++++++++------ pyproject.toml | 1 + 52 files changed, 1638 insertions(+), 744 deletions(-) create mode 100644 examples/parameters/sam/sam_dynamodb_custom_fields.yaml create mode 100644 examples/parameters/sam/sam_dynamodb_table_recursive.yaml create mode 100644 examples/parameters/sam/sam_dynamodb_table_single.yaml create mode 100644 examples/parameters/src/appconfig_force_fetch.py create mode 100644 examples/parameters/src/appconfig_with_cache.py create mode 100644 examples/parameters/src/builtin_provider_appconfig.py create mode 100644 examples/parameters/src/builtin_provider_dynamodb_custom_endpoint.py create mode 100644 examples/parameters/src/builtin_provider_dynamodb_custom_fields.py create mode 100644 examples/parameters/src/builtin_provider_dynamodb_recursive_parameter.py create mode 100644 examples/parameters/src/builtin_provider_dynamodb_single_parameter.py create mode 100644 examples/parameters/src/builtin_provider_secret.py create mode 100644 examples/parameters/src/builtin_provider_ssm_recursive_parameter.py create mode 100644 examples/parameters/src/builtin_provider_ssm_single_parameter.py create mode 100644 examples/parameters/src/builtin_provider_ssm_with_decrypt.py create mode 100644 examples/parameters/src/builtin_provider_ssm_with_no_recursive.py create mode 100644 examples/parameters/src/custom_boto3_all_providers.py create mode 100644 examples/parameters/src/custom_boto_client.py create mode 100644 examples/parameters/src/custom_boto_config.py create mode 100644 examples/parameters/src/custom_boto_session.py create mode 100644 examples/parameters/src/custom_provider_s3.py create mode 100644 examples/parameters/src/custom_provider_vault.py create mode 100644 examples/parameters/src/get_parameter_by_name_error_handling.py create mode 100644 examples/parameters/src/getting_started_appconfig.py create mode 100644 examples/parameters/src/getting_started_parameter_by_name.py create mode 100644 examples/parameters/src/getting_started_recursive_ssm_parameter.py create mode 100644 examples/parameters/src/getting_started_secret.py create mode 100644 examples/parameters/src/getting_started_single_ssm_parameter.py create mode 100644 examples/parameters/src/handling_error_transform.py create mode 100644 examples/parameters/src/recursive_ssm_parameter_force_fetch.py create mode 100644 examples/parameters/src/recursive_ssm_parameter_with_cache.py create mode 100644 examples/parameters/src/secret_force_fetch.py create mode 100644 examples/parameters/src/secret_with_cache.py create mode 100644 examples/parameters/src/single_ssm_parameter_force_fetch.py create mode 100644 examples/parameters/src/single_ssm_parameter_with_cache.py create mode 100644 examples/parameters/src/working_with_auto_transform.py create mode 100644 examples/parameters/src/working_with_own_provider_s3.py create mode 100644 examples/parameters/src/working_with_own_provider_vault.py create mode 100644 examples/parameters/src/working_with_sdk_additional_arguments.py create mode 100644 examples/parameters/src/working_with_transform_high_level.py create mode 100644 examples/parameters/src/working_with_transform_provider.py create mode 100644 examples/parameters/tests/src/__init__.py create mode 100644 examples/parameters/tests/src/app.py create mode 100644 examples/parameters/tests/src/single_mock.py create mode 100644 examples/parameters/tests/test_clear_cache_global.py create mode 100644 examples/parameters/tests/test_clear_cache_method.py create mode 100644 examples/parameters/tests/test_single_mock.py create mode 100644 examples/parameters/tests/test_with_fixture.py create mode 100644 examples/parameters/tests/test_with_monkeypatch.py diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index 9441d94fe12..d021ae44a61 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -15,6 +15,9 @@ The parameters utility provides high-level functions to retrieve one or multiple ## Getting started +???+ tip + All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}. + By default, we fetch parameters from System Manager Parameter Store, secrets from Secrets Manager, and application configuration from AppConfig. ### IAM Permissions @@ -37,54 +40,26 @@ This utility requires additional permissions to work as expected. ### Fetching parameters -You can retrieve a single parameter using `get_parameter` high-level function. - -```python hl_lines="5" title="Fetching a single parameter" -from aws_lambda_powertools.utilities import parameters +You can retrieve a single parameter using the `get_parameter` high-level function. -def handler(event, context): - # Retrieve a single parameter - value = parameters.get_parameter("/my/parameter") - -``` +=== "getting_started_single_ssm_parameter.py" + ```python hl_lines="3 10" + --8<-- "examples/parameters/src/getting_started_single_ssm_parameter.py" + ``` For multiple parameters, you can use either: * `get_parameters` to recursively fetch all parameters by path. * `get_parameters_by_name` to fetch distinct parameters by their full name. It also accepts custom caching, transform, decrypt per parameter. -=== "get_parameters" - - ```python hl_lines="1 6" - from aws_lambda_powertools.utilities import parameters - - def handler(event, context): - # Retrieve multiple parameters from a path prefix recursively - # This returns a dict with the parameter name as key - values = parameters.get_parameters("/my/path/prefix") - for parameter, value in values.items(): - print(f"{parameter}: {value}") +=== "getting_started_recursive_ssm_parameter.py" + ```python hl_lines="3 10 13" + --8<-- "examples/parameters/src/getting_started_recursive_ssm_parameter.py" ``` -=== "get_parameters_by_name" - - ```python hl_lines="3 5 14" - from typing import Any - - from aws_lambda_powertools.utilities import get_parameters_by_name - - parameters = { - "/develop/service/commons/telemetry/config": {"max_age": 300, "transform": "json"}, - "/no_cache_param": {"max_age": 0}, - # inherit default values - "/develop/service/payment/api/capture/url": {}, - } - - def handler(event, context): - # This returns a dict with the parameter name as key - response: dict[str, Any] = parameters.get_parameters_by_name(parameters=parameters, max_age=60) - for parameter, value in response.items(): - print(f"{parameter}: {value}") +=== "getting_started_parameter_by_name.py" + ```python hl_lines="3 14" + --8<-- "examples/parameters/src/getting_started_parameter_by_name.py" ``` ???+ tip "`get_parameters_by_name` supports graceful error handling" @@ -96,40 +71,19 @@ For multiple parameters, you can use either: * Keep only successful parameter names and their values in the response * Raise `GetParameterError` if any of your parameters is named `_errors` -```python hl_lines="3 5 12-13 15" title="Graceful error handling" -from typing import Any - -from aws_lambda_powertools.utilities import get_parameters_by_name - -parameters = { - "/develop/service/commons/telemetry/config": {"max_age": 300, "transform": "json"}, - # it would fail by default - "/this/param/does/not/exist" -} - -def handler(event, context): - values: dict[str, Any] = parameters.get_parameters_by_name(parameters=parameters, raise_on_error=False) - errors: list[str] = values.get("_errors", []) - - # Handle gracefully, since '/this/param/does/not/exist' will only be available in `_errors` - if errors: - ... - - for parameter, value in values.items(): - print(f"{parameter}: {value}") -``` +=== "get_parameter_by_name_error_handling.py" + ```python hl_lines="3 5 12-13 15" + --8<-- "examples/parameters/src/get_parameter_by_name_error_handling.py" + ``` ### Fetching secrets -You can fetch secrets stored in Secrets Manager using `get_secrets`. +You can fetch secrets stored in Secrets Manager using `get_secret`. -```python hl_lines="1 5" title="Fetching secrets" -from aws_lambda_powertools.utilities import parameters - -def handler(event, context): - # Retrieve a single secret - value = parameters.get_secret("my-secret") -``` +=== "getting_started_secret.py" + ```python hl_lines="5 15" + --8<-- "examples/parameters/src/getting_started_secret.py" + ``` ### Fetching app configurations @@ -137,79 +91,84 @@ You can fetch application configurations in AWS AppConfig using `get_app_config` The following will retrieve the latest version and store it in the cache. -```python hl_lines="1 5" title="Fetching latest config from AppConfig" -from aws_lambda_powertools.utilities import parameters - -def handler(event, context): - # Retrieve a single configuration, latest version - value: bytes = parameters.get_app_config(name="my_configuration", environment="my_env", application="my_app") -``` +=== "getting_started_appconfig.py" + ```python hl_lines="5 12" + --8<-- "examples/parameters/src/getting_started_appconfig.py" + ``` ## Advanced ### Adjusting cache TTL ???+ tip - `max_age` parameter is also available in high level functions like `get_parameter`, `get_secret`, etc. + `max_age` parameter is also available in underlying provider functions like `get()`, `get_multiple()`, etc. By default, we cache parameters retrieved in-memory for 5 seconds. -You can adjust how long we should keep values in cache by using the param `max_age`, when using `get()` or `get_multiple()` methods across all providers. +You can adjust how long we should keep values in cache by using the param `max_age`, when using `get_parameter()`, `get_parameters()` and `get_secret()` methods across all providers. -```python hl_lines="9" title="Caching parameter(s) value in memory for longer than 5 seconds" -from aws_lambda_powertools.utilities import parameters -from botocore.config import Config +=== "single_ssm_parameter_with_cache.py" + ```python hl_lines="5 12" + --8<-- "examples/parameters/src/single_ssm_parameter_with_cache.py" + ``` -config = Config(region_name="us-west-1") -ssm_provider = parameters.SSMProvider(config=config) +=== "recursive_ssm_parameter_with_cache.py" + ```python hl_lines="5 12" + --8<-- "examples/parameters/src/recursive_ssm_parameter_with_cache.py" + ``` -def handler(event, context): - # Retrieve a single parameter - value = ssm_provider.get("/my/parameter", max_age=60) # 1 minute +=== "secret_with_cache.py" + ```python hl_lines="5 15" + --8<-- "examples/parameters/src/secret_with_cache.py" + ``` - # Retrieve multiple parameters from a path prefix - values = ssm_provider.get_multiple("/my/path/prefix", max_age=60) - for k, v in values.items(): - print(f"{k}: {v}") -``` +=== "appconfig_with_cache.py" + ```python hl_lines="5 12-14" + --8<-- "examples/parameters/src/appconfig_with_cache.py" + ``` ### Always fetching the latest If you'd like to always ensure you fetch the latest parameter from the store regardless if already available in cache, use `force_fetch` param. -```python hl_lines="5" title="Forcefully fetching the latest parameter whether TTL has expired or not" -from aws_lambda_powertools.utilities import parameters +=== "single_ssm_parameter_force_fetch.py" + ```python hl_lines="5 12" + --8<-- "examples/parameters/src/single_ssm_parameter_force_fetch.py" + ``` -def handler(event, context): - # Retrieve a single parameter - value = parameters.get_parameter("/my/parameter", force_fetch=True) -``` +=== "recursive_ssm_parameter_force_fetch.py" + ```python hl_lines="5 12" + --8<-- "examples/parameters/src/recursive_ssm_parameter_force_fetch.py" + ``` + +=== "secret_force_fetch.py" + ```python hl_lines="5 15" + --8<-- "examples/parameters/src/secret_force_fetch.py" + ``` + +=== "appconfig_force_fetch.py" + ```python hl_lines="5 12-14" + --8<-- "examples/parameters/src/appconfig_force_fetch.py" + ``` ### Built-in provider class For greater flexibility such as configuring the underlying SDK client used by built-in providers, you can use their respective Provider Classes directly. ???+ tip - This can be used to retrieve values from other regions, change the retry behavior, etc. + This is useful when you need to customize parameters for the SDK client, such as region, credentials, retries and others. For more information, read [botocore.config](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html) and [boto3.session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#module-boto3.session). #### SSMProvider -```python hl_lines="5 9 12" title="Example with SSMProvider for further extensibility" -from aws_lambda_powertools.utilities import parameters -from botocore.config import Config - -config = Config(region_name="us-west-1") -ssm_provider = parameters.SSMProvider(config=config) # or boto3_session=boto3.Session() - -def handler(event, context): - # Retrieve a single parameter - value = ssm_provider.get("/my/parameter") +=== "builtin_provider_ssm_single_parameter.py" + ```python hl_lines="6 11 12" + --8<-- "examples/parameters/src/builtin_provider_ssm_single_parameter.py" + ``` - # Retrieve multiple parameters from a path prefix - values = ssm_provider.get_multiple("/my/path/prefix") - for k, v in values.items(): - print(f"{k}: {v}") -``` +=== "builtin_provider_ssm_recursive_parameter.py" + ```python hl_lines="6 19-25" + --8<-- "examples/parameters/src/builtin_provider_ssm_recursive_parameter.py" + ``` The AWS Systems Manager Parameter Store provider supports two additional arguments for the `get()` and `get_multiple()` methods: @@ -218,30 +177,24 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen | **decrypt** | `False` | Will automatically decrypt the parameter. | | **recursive** | `True` | For `get_multiple()` only, will fetch all parameter values recursively based on a path prefix. | -```python hl_lines="6 8" title="Example with get() and get_multiple()" -from aws_lambda_powertools.utilities import parameters - -ssm_provider = parameters.SSMProvider() +You can create `SecureString` parameters, which are parameters that have a plaintext parameter name and an encrypted parameter value. If you don't use the `decrypt` argument, you will get an encrypted value. Read [here](https://docs.aws.amazon.com/kms/latest/developerguide/services-parameter-store.html) about best practices using KMS to secure your parameters. -def handler(event, context): - decrypted_value = ssm_provider.get("/my/encrypted/parameter", decrypt=True) +=== "builtin_provider_ssm_with_decrypt.py" + ```python hl_lines="6 10 16" + --8<-- "examples/parameters/src/builtin_provider_ssm_with_decrypt.py" + ``` - no_recursive_values = ssm_provider.get_multiple("/my/path/prefix", recursive=False) -``` +=== "builtin_provider_ssm_with_no_recursive.py" + ```python hl_lines="5 8 21" + --8<-- "examples/parameters/src/builtin_provider_ssm_with_no_recursive.py" + ``` #### SecretsProvider -```python hl_lines="5 9" title="Example with SecretsProvider for further extensibility" -from aws_lambda_powertools.utilities import parameters -from botocore.config import Config - -config = Config(region_name="us-west-1") -secrets_provider = parameters.SecretsProvider(config=config) - -def handler(event, context): - # Retrieve a single secret - value = secrets_provider.get("my-secret") -``` +=== "builtin_provider_secret.py" + ```python hl_lines="4 6 9" + --8<-- "examples/parameters/src/builtin_provider_secret.py" + ``` #### DynamoDBProvider @@ -261,25 +214,22 @@ For single parameters, you must use `id` as the [partition key](https://docs.aws With this table, `dynamodb_provider.get("my-param")` will return `my-value`. -=== "app.py" - ```python hl_lines="3 7" - from aws_lambda_powertools.utilities import parameters - - dynamodb_provider = parameters.DynamoDBProvider(table_name="my-table") - - def handler(event, context): - # Retrieve a value from DynamoDB - value = dynamodb_provider.get("my-parameter") - ``` +=== "builtin_provider_dynamodb_single_parameter.py" + ```python hl_lines="5 8 15" + --8<-- "examples/parameters/src/builtin_provider_dynamodb_single_parameter.py" + ``` -=== "DynamoDB Local example" - You can initialize the DynamoDB provider pointing to [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html) using `endpoint_url` parameter: +=== "sam_dynamodb_table_single.yaml" + ```yaml hl_lines="12-14" + --8<-- "examples/parameters/sam/sam_dynamodb_table_single.yaml" + ``` - ```python hl_lines="3" - from aws_lambda_powertools.utilities import parameters +You can initialize the DynamoDB provider pointing to [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html) using `endpoint_url` parameter: - dynamodb_provider = parameters.DynamoDBProvider(table_name="my-table", endpoint_url="http://localhost:8000") - ``` +=== "builtin_provider_dynamodb_custom_endpoint.py" + ```python hl_lines="5 8 15" + --8<-- "examples/parameters/src/builtin_provider_dynamodb_custom_endpoint.py" + ``` **DynamoDB table structure for multiple values parameters** @@ -289,39 +239,22 @@ You can retrieve multiple parameters sharing the same `id` by having a sort key DynamoDB table with `id` primary key, `sk` as sort key` and `value` as attribute - | id | sk | value | - | ----------- | ------- | ---------- | - | my-hash-key | param-a | my-value-a | - | my-hash-key | param-b | my-value-b | - | my-hash-key | param-c | my-value-c | + | id | sk | value | + | ------ | ----------------- | ------------------------------------------------ | + | config | endpoint_comments | | + | config | limit | 10 | -With this table, `dynamodb_provider.get_multiple("my-hash-key")` will return a dictionary response in the shape of `sk:value`. +With this table, `dynamodb_provider.get_multiple("config")` will return a dictionary response in the shape of `sk:value`. -=== "app.py" - ```python hl_lines="3 8" - from aws_lambda_powertools.utilities import parameters - - dynamodb_provider = parameters.DynamoDBProvider(table_name="my-table") - - def handler(event, context): - # Retrieve multiple values by performing a Query on the DynamoDB table - # This returns a dict with the sort key attribute as dict key. - parameters = dynamodb_provider.get_multiple("my-hash-key") - for k, v in parameters.items(): - # k: param-a - # v: "my-value-a" - print(f"{k}: {v}") - ``` - -=== "parameters dict response" - - ```json - { - "param-a": "my-value-a", - "param-b": "my-value-b", - "param-c": "my-value-c" - } - ``` +=== "builtin_provider_dynamodb_recursive_parameter.py" + ```python hl_lines="5 8 15" + --8<-- "examples/parameters/src/builtin_provider_dynamodb_recursive_parameter.py" + ``` + +=== "sam_dynamodb_table_recursive.yaml" + ```yaml hl_lines="15-18" + --8<-- "examples/parameters/sam/sam_dynamodb_table_recursive.yaml" + ``` **Customizing DynamoDBProvider** @@ -334,33 +267,22 @@ DynamoDB provider can be customized at initialization to match your table struct | **sort_attr** | No | `sk` | Range key for the DynamoDB table. You don't need to set this if you don't use the `get_multiple()` method. | | **value_attr** | No | `value` | Name of the attribute containing the parameter value. | -```python hl_lines="3-8" title="Customizing DynamoDBProvider to suit your table design" -from aws_lambda_powertools.utilities import parameters - -dynamodb_provider = parameters.DynamoDBProvider( - table_name="my-table", - key_attr="MyKeyAttr", - sort_attr="MySortAttr", - value_attr="MyvalueAttr" -) +=== "builtin_provider_dynamodb_custom_fields.py" + ```python hl_lines="3 8-10 17" + --8<-- "examples/parameters/src/builtin_provider_dynamodb_custom_fields.py" + ``` -def handler(event, context): - value = dynamodb_provider.get("my-parameter") -``` +=== "sam_dynamodb_custom_fields.yaml" + ```yaml hl_lines="5 8-10 17" + --8<-- "examples/parameters/sam/sam_dynamodb_custom_fields.yaml" + ``` #### AppConfigProvider -```python hl_lines="5 9" title="Using AppConfigProvider" -from aws_lambda_powertools.utilities import parameters -from botocore.config import Config - -config = Config(region_name="us-west-1") -appconf_provider = parameters.AppConfigProvider(environment="my_env", application="my_app", config=config) - -def handler(event, context): - # Retrieve a single secret - value: bytes = appconf_provider.get("my_conf") -``` +=== "builtin_provider_appconfig.py" + ```python hl_lines="6 9 10 16" + --8<-- "examples/parameters/src/builtin_provider_appconfig.py" + ``` ### Create your own provider @@ -368,60 +290,27 @@ You can create your own custom parameter store provider by inheriting the `BaseP All transformation and caching logic is handled by the `get()` and `get_multiple()` methods from the base provider class. -Here is an example implementation using S3 as a custom parameter store: - -```python hl_lines="3 6 17 27" title="Creating a S3 Provider to fetch parameters" -import copy - -from aws_lambda_powertools.utilities import BaseProvider -import boto3 - -class S3Provider(BaseProvider): - bucket_name = None - client = None - - def __init__(self, bucket_name: str): - # Initialize the client to your custom parameter store - # E.g.: - - self.bucket_name = bucket_name - self.client = boto3.client("s3") - - def _get(self, name: str, **sdk_options) -> str: - # Retrieve a single value - # E.g.: - - sdk_options["Bucket"] = self.bucket_name - sdk_options["Key"] = name - - response = self.client.get_object(**sdk_options) - return - - def _get_multiple(self, path: str, **sdk_options) -> Dict[str, str]: - # Retrieve multiple values - # E.g.: +Here are two examples of implementing a custom parameter store. One using an external service like [Hashicorp Vault](https://www.vaultproject.io/), a widely popular key-value and secret storage and the other one using [Amazon S3](https://aws.amazon.com/s3/?nc1=h_ls), a popular object storage. - list_sdk_options = copy.deepcopy(sdk_options) - - list_sdk_options["Bucket"] = self.bucket_name - list_sdk_options["Prefix"] = path - - list_response = self.client.list_objects_v2(**list_sdk_options) - - parameters = {} - - for obj in list_response.get("Contents", []): - get_sdk_options = copy.deepcopy(sdk_options) - - get_sdk_options["Bucket"] = self.bucket_name - get_sdk_options["Key"] = obj["Key"] +=== "working_with_own_provider_vault.py" + ```python hl_lines="5 13 20 24" + --8<-- "examples/parameters/src/working_with_own_provider_vault.py" + ``` - get_response = self.client.get_object(**get_sdk_options) +=== "custom_provider_vault.py" + ```python hl_lines="6 9 17 24" + --8<-- "examples/parameters/src/custom_provider_vault.py" + ``` - parameters[obj["Key"]] = get_response["Body"].read().decode() +=== "working_with_own_provider_s3.py" + ```python hl_lines="4 11 18 21" + --8<-- "examples/parameters/src/working_with_own_provider_s3.py" + ``` - return parameters -``` +=== "custom_provider_s3.py" + ```python hl_lines="6 9 19 29" + --8<-- "examples/parameters/src/custom_provider_s3.py" + ``` ### Deserializing values with transform parameter @@ -430,28 +319,14 @@ For parameters stored in JSON or Base64 format, you can use the `transform` argu ???+ info The `transform` argument is available across all providers, including the high level functions. -=== "High level functions" - - ```python hl_lines="4" - from aws_lambda_powertools.utilities import parameters - - def handler(event, context): - value_from_json = parameters.get_parameter("/my/json/parameter", transform="json") +=== "working_with_transform_high_level.py" + ```python hl_lines="5 12" + --8<-- "examples/parameters/src/working_with_transform_high_level.py" ``` -=== "Providers" - - ```python hl_lines="7 10" - from aws_lambda_powertools.utilities import parameters - - ssm_provider = parameters.SSMProvider() - - def handler(event, context): - # Transform a JSON string - value_from_json = ssm_provider.get("/my/json/parameter", transform="json") - - # Transform a Base64 encoded string - value_from_binary = ssm_provider.get("/my/binary/parameter", transform="binary") +=== "working_with_transform_provider.py" + ```python hl_lines="6 9 16" + --8<-- "examples/parameters/src/working_with_transform_provider.py" ``` #### Partial transform failures with `get_multiple()` @@ -462,26 +337,10 @@ You can override this by setting the `raise_on_transform_error` argument to `Tru For example, if you have three parameters, */param/a*, */param/b* and */param/c*, but */param/c* is malformed: -```python hl_lines="9 16" title="Raising TransformParameterError at first malformed parameter" -from aws_lambda_powertools.utilities import parameters - -ssm_provider = parameters.SSMProvider() - -def handler(event, context): - # This will display: - # /param/a: [some value] - # /param/b: [some value] - # /param/c: None - values = ssm_provider.get_multiple("/param", transform="json") - for k, v in values.items(): - print(f"{k}: {v}") - - try: - # This will raise a TransformParameterError exception - values = ssm_provider.get_multiple("/param", transform="json", raise_on_transform_error=True) - except parameters.exceptions.TransformParameterError: - ... -``` +=== "handling_error_transform.py" + ```python hl_lines="3 14 20" + --8<-- "examples/parameters/src/handling_error_transform.py" + ``` #### Auto-transform values on suffix @@ -492,14 +351,10 @@ You can do this with a single request by using `transform="auto"`. This will ins ???+ info `transform="auto"` feature is available across all providers, including the high level functions. -```python hl_lines="6" title="Deserializing parameter values based on their suffix" -from aws_lambda_powertools.utilities import parameters - -ssm_provider = parameters.SSMProvider() - -def handler(event, context): - values = ssm_provider.get_multiple("/param", transform="auto") -``` +=== "working_with_auto_transform.py" + ```python hl_lines="1 4 8" + --8<-- "examples/parameters/src/working_with_auto_transform.py" + ``` For example, if you have two parameters with the following suffixes `.json` and `.binary`: @@ -521,63 +376,42 @@ The return of `ssm_provider.get_multiple("/param", transform="auto")` call will You can use arbitrary keyword arguments to pass it directly to the underlying SDK method. -```python hl_lines="8" title="" -from aws_lambda_powertools.utilities import parameters - -secrets_provider = parameters.SecretsProvider() - -def handler(event, context): - # The 'VersionId' argument will be passed to the underlying get_secret_value() call. - value = secrets_provider.get("my-secret", VersionId="e62ec170-6b01-48c7-94f3-d7497851a8d2") -``` +=== "working_with_sdk_additional_arguments.py" + ```python hl_lines="1 4 9" + --8<-- "examples/parameters/src/working_with_sdk_additional_arguments.py" + ``` Here is the mapping between this utility's functions and methods and the underlying SDK: -| Provider | Function/Method | Client name | Function name | -| ------------------- | ------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| SSM Parameter Store | `get_parameter` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter) | -| SSM Parameter Store | `get_parameters` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path) | -| SSM Parameter Store | `SSMProvider.get` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter) | -| SSM Parameter Store | `SSMProvider.get_multiple` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path) | -| Secrets Manager | `get_secret` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value) | -| Secrets Manager | `SecretsManager.get` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value) | -| DynamoDB | `DynamoDBProvider.get` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table)) | [get_item](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.get_item) | -| DynamoDB | `DynamoDBProvider.get_multiple` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table)) | [query](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.query) | -| App Config | `get_app_config` | `appconfig` | [get_configuration](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfig.html#AppConfig.Client.get_configuration) | +| Provider | Function/Method | Client name | Function name | +| ------------------- | ------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| SSM Parameter Store | `get_parameter` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter) | +| SSM Parameter Store | `get_parameters` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path) | +| SSM Parameter Store | `SSMProvider.get` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter) | +| SSM Parameter Store | `SSMProvider.get_multiple` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path) | +| Secrets Manager | `get_secret` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value) | +| Secrets Manager | `SecretsManager.get` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value) | +| DynamoDB | `DynamoDBProvider.get` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table)) | [get_item](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.get_item) | +| DynamoDB | `DynamoDBProvider.get_multiple` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table)) | [query](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.query) | +| App Config | `get_app_config` | `appconfigdata` | [start_configuration_session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.start_configuration_session) and [get_latest_configuration](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.get_latest_configuration) | ### Bring your own boto client You can use `boto3_client` parameter via any of the available [Provider Classes](#built-in-provider-class). Some providers expect a low level boto3 client while others expect a high level boto3 client, here is the mapping for each of them: -| Provider | Type | Boto client construction | -| --------------------------------------- | ---------- | ---------------------------- | -| [SSMProvider](#ssmprovider) | low level | `boto3.client("ssm")` | -| [SecretsProvider](#secretsprovider) | low level | `boto3.client("secrets")` | -| [AppConfigProvider](#appconfigprovider) | low level | `boto3.client("appconfig")` | -| [DynamoDBProvider](#dynamodbprovider) | high level | `boto3.resource("dynamodb")` | +| Provider | Type | Boto client construction | +| --------------------------------------- | ---------- | ------------------------------- | +| [SSMProvider](#ssmprovider) | low level | `boto3.client("ssm")` | +| [SecretsProvider](#secretsprovider) | low level | `boto3.client("secrets")` | +| [AppConfigProvider](#appconfigprovider) | low level | `boto3.client("appconfigdata")` | +| [DynamoDBProvider](#dynamodbprovider) | high level | `boto3.resource("dynamodb")` | Bringing them together in a single code snippet would look like this: -```python title="Example: passing a custom boto3 client for each provider" -import boto3 -from botocore.config import Config - -from aws_lambda_powertools.utilities import parameters - -config = Config(region_name="us-west-1") - -# construct boto clients with any custom configuration -ssm = boto3.client("ssm", config=config) -secrets = boto3.client("secrets", config=config) -appconfig = boto3.client("appconfig", config=config) -dynamodb = boto3.resource("dynamodb", config=config) - -ssm_provider = parameters.SSMProvider(boto3_client=ssm) -secrets_provider = parameters.SecretsProvider(boto3_client=secrets) -appconf_provider = parameters.AppConfigProvider(boto3_client=appconfig, environment="my_env", application="my_app") -dynamodb_provider = parameters.DynamoDBProvider(boto3_client=dynamodb, table_name="my-table") - -``` +=== "custom_boto3_all_providers.py" + ```python hl_lines="4 6" + --8<-- "examples/parameters/src/custom_boto3_all_providers.py" + ``` ???+ question "When is this useful?" Injecting a custom boto3 client can make unit/snapshot testing easier, including SDK customizations. @@ -591,49 +425,20 @@ The **`config`** , **`boto3_session`**, and **`boto3_client`** parameters enabl When using VPC private endpoints, you can pass a custom client altogether. It's also useful for testing when injecting fake instances. -=== "Custom session" - - ```python hl_lines="2 4 5" - from aws_lambda_powertools.utilities import parameters - import boto3 - - boto3_session = boto3.session.Session() - ssm_provider = parameters.SSMProvider(boto3_session=boto3_session) - - def handler(event, context): - # Retrieve a single parameter - value = ssm_provider.get("/my/parameter") - ... - ``` -=== "Custom config" - - ```python hl_lines="2 4 5" - from aws_lambda_powertools.utilities import parameters - from botocore.config import Config - - boto_config = Config() - ssm_provider = parameters.SSMProvider(config=boto_config) - - def handler(event, context): - # Retrieve a single parameter - value = ssm_provider.get("/my/parameter") - ... - ``` - -=== "Custom client" - - ```python hl_lines="2 4 5" - from aws_lambda_powertools.utilities import parameters - import boto3 +=== "custom_boto_session.py" + ```python hl_lines="5 6" + --8<-- "examples/parameters/src/custom_boto_session.py" + ``` - boto3_client= boto3.client("ssm") - ssm_provider = parameters.SSMProvider(boto3_client=boto3_client) +=== "custom_boto_config.py" + ```python hl_lines="5 6" + --8<-- "examples/parameters/src/custom_boto_config.py" + ``` - def handler(event, context): - # Retrieve a single parameter - value = ssm_provider.get("/my/parameter") - ... - ``` +=== "custom_boto_client.py" + ```python hl_lines="5 6" + --8<-- "examples/parameters/src/custom_boto_client.py" + ``` ## Testing your code @@ -641,72 +446,32 @@ The **`config`** , **`boto3_session`**, and **`boto3_client`** parameters enabl For unit testing your applications, you can mock the calls to the parameters utility to avoid calling AWS APIs. This can be achieved in a number of ways - in this example, we use the [pytest monkeypatch fixture](https://docs.pytest.org/en/latest/how-to/monkeypatch.html) to patch the `parameters.get_parameter` method: -=== "tests.py" - ```python - from src import index - - def test_handler(monkeypatch): - - def mockreturn(name): - return "mock_value" - - monkeypatch.setattr(index.parameters, "get_parameter", mockreturn) - return_val = index.handler({}, {}) - assert return_val.get('message') == 'mock_value' - ``` - -=== "src/index.py" - ```python - from aws_lambda_powertools.utilities import parameters +=== "test_single_mock.py" + ```python hl_lines="4 8" + --8<-- "examples/parameters/tests/test_single_mock.py" + ``` - def handler(event, context): - # Retrieve a single parameter - value = parameters.get_parameter("my-parameter-name") - return {"message": value} - ``` +=== "single_mock.py" + ```python + --8<-- "examples/parameters/tests/src/single_mock.py" + ``` If we need to use this pattern across multiple tests, we can avoid repetition by refactoring to use our own pytest fixture: -=== "tests.py" - ```python - import pytest - - from src import index - - @pytest.fixture - def mock_parameter_response(monkeypatch): - def mockreturn(name): - return "mock_value" - - monkeypatch.setattr(index.parameters, "get_parameter", mockreturn) - - # Pass our fixture as an argument to all tests where we want to mock the get_parameter response - def test_handler(mock_parameter_response): - return_val = index.handler({}, {}) - assert return_val.get('message') == 'mock_value' - - ``` +=== "test_with_fixture.py" + ```python hl_lines="5 10" + --8<-- "examples/parameters/tests/test_with_fixture.py" + ``` Alternatively, if we need more fully featured mocking (for example checking the arguments passed to `get_parameter`), we can use [unittest.mock](https://docs.python.org/3/library/unittest.mock.html) from the python stdlib instead of pytest's `monkeypatch` fixture. In this example, we use the [patch](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch) decorator to replace the `aws_lambda_powertools.utilities.parameters.get_parameter` function with a [MagicMock](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock) object named `get_parameter_mock`. -=== "tests.py" - ```python - from unittest.mock import patch - from src import index - - # Replaces "aws_lambda_powertools.utilities.parameters.get_parameter" with a Mock object - @patch("aws_lambda_powertools.utilities.parameters.get_parameter") - def test_handler(get_parameter_mock): - get_parameter_mock.return_value = 'mock_value' - - return_val = index.handler({}, {}) - get_parameter_mock.assert_called_with("my-parameter-name") - assert return_val.get('message') == 'mock_value' - - ``` +=== "test_with_monkeypatch.py" + ```python hl_lines="7 12" + --8<-- "examples/parameters/tests/test_with_monkeypatch.py" + ``` ### Clearing cache @@ -714,66 +479,17 @@ Parameters utility caches all parameter values for performance and cost reasons. Within your tests, you can use `clear_cache` method available in [every provider](#built-in-provider-class). When using multiple providers or higher level functions like `get_parameter`, use `clear_caches` standalone function to clear cache globally. -=== "clear_cache method" - ```python hl_lines="9" - import pytest - - from src import app - - - @pytest.fixture(scope="function", autouse=True) - def clear_parameters_cache(): - yield - app.ssm_provider.clear_cache() # This will clear SSMProvider cache - - @pytest.fixture - def mock_parameter_response(monkeypatch): - def mockreturn(name): - return "mock_value" - - monkeypatch.setattr(app.ssm_provider, "get", mockreturn) - - # Pass our fixture as an argument to all tests where we want to mock the get_parameter response - def test_handler(mock_parameter_response): - return_val = app.handler({}, {}) - assert return_val.get('message') == 'mock_value' - ``` - -=== "global clear_caches" - ```python hl_lines="10" - import pytest - - from aws_lambda_powertools.utilities import parameters - from src import app - - - @pytest.fixture(scope="function", autouse=True) - def clear_parameters_cache(): - yield - parameters.clear_caches() # This will clear all providers cache - - @pytest.fixture - def mock_parameter_response(monkeypatch): - def mockreturn(name): - return "mock_value" - - monkeypatch.setattr(app.ssm_provider, "get", mockreturn) +=== "test_clear_cache_method.py" + ```python hl_lines="8" + --8<-- "examples/parameters/tests/test_clear_cache_method.py" + ``` - # Pass our fixture as an argument to all tests where we want to mock the get_parameter response - def test_handler(mock_parameter_response): - return_val = app.handler({}, {}) - assert return_val.get('message') == 'mock_value' - ``` +=== "test_clear_cache_global.py" + ```python hl_lines="10" + --8<-- "examples/parameters/tests/test_clear_cache_global.py" + ``` === "app.py" - ```python - from aws_lambda_powertools.utilities import parameters - from botocore.config import Config - - ssm_provider = parameters.SSMProvider(config=Config(region_name="us-west-1")) - - - def handler(event, context): - value = ssm_provider.get("/my/parameter") - return {"message": value} - ``` + ```python + --8<-- "examples/parameters/tests/src/app.py" + ``` diff --git a/examples/parameters/sam/sam_dynamodb_custom_fields.yaml b/examples/parameters/sam/sam_dynamodb_custom_fields.yaml new file mode 100644 index 00000000000..1c864a0e747 --- /dev/null +++ b/examples/parameters/sam/sam_dynamodb_custom_fields.yaml @@ -0,0 +1,22 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: 'DynamoDB Table example' +Resources: + ParameterTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: ParameterTable + AttributeDefinitions: + - AttributeName: IdKeyAttr + AttributeType: S + - AttributeName: SkKeyAttr + AttributeType: S + KeySchema: + - AttributeName: IdKeyAttr + KeyType: HASH + - AttributeName: SkKeyAttr + KeyType: RANGE + TimeToLiveSpecification: + AttributeName: expiration + Enabled: true + BillingMode: PAY_PER_REQUEST diff --git a/examples/parameters/sam/sam_dynamodb_table_recursive.yaml b/examples/parameters/sam/sam_dynamodb_table_recursive.yaml new file mode 100644 index 00000000000..6e02c2f8f6d --- /dev/null +++ b/examples/parameters/sam/sam_dynamodb_table_recursive.yaml @@ -0,0 +1,22 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: 'DynamoDB Table example' +Resources: + ParameterTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: ParameterTable + AttributeDefinitions: + - AttributeName: id + AttributeType: S + - AttributeName: sk + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + - AttributeName: sk + KeyType: RANGE + TimeToLiveSpecification: + AttributeName: expiration + Enabled: true + BillingMode: PAY_PER_REQUEST diff --git a/examples/parameters/sam/sam_dynamodb_table_single.yaml b/examples/parameters/sam/sam_dynamodb_table_single.yaml new file mode 100644 index 00000000000..17d25553fa7 --- /dev/null +++ b/examples/parameters/sam/sam_dynamodb_table_single.yaml @@ -0,0 +1,18 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: 'DynamoDB Table example' +Resources: + ParameterTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: ParameterTable + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + TimeToLiveSpecification: + AttributeName: expiration + Enabled: true + BillingMode: PAY_PER_REQUEST diff --git a/examples/parameters/src/appconfig_force_fetch.py b/examples/parameters/src/appconfig_force_fetch.py new file mode 100644 index 00000000000..3cf5cbda6fd --- /dev/null +++ b/examples/parameters/src/appconfig_force_fetch.py @@ -0,0 +1,21 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter + endpoint_comments: Any = parameters.get_app_config( + name="config", environment="dev", application="comments", force_fetch=True + ) + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/appconfig_with_cache.py b/examples/parameters/src/appconfig_with_cache.py new file mode 100644 index 00000000000..55514e12ea7 --- /dev/null +++ b/examples/parameters/src/appconfig_with_cache.py @@ -0,0 +1,21 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter + endpoint_comments: Any = parameters.get_app_config( + name="config", environment="dev", application="comments", max_age=20 + ) + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_appconfig.py b/examples/parameters/src/builtin_provider_appconfig.py new file mode 100644 index 00000000000..cf734e29af8 --- /dev/null +++ b/examples/parameters/src/builtin_provider_appconfig.py @@ -0,0 +1,23 @@ +from typing import Any + +import requests +from botocore.config import Config + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +config = Config(region_name="sa-east-1") +appconf_provider = parameters.AppConfigProvider(environment="dev", application="comments", config=config) + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter + endpoint_comments: Any = appconf_provider.get("config") + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_dynamodb_custom_endpoint.py b/examples/parameters/src/builtin_provider_dynamodb_custom_endpoint.py new file mode 100644 index 00000000000..e77506f27d7 --- /dev/null +++ b/examples/parameters/src/builtin_provider_dynamodb_custom_endpoint.py @@ -0,0 +1,22 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +dynamodb_provider = parameters.DynamoDBProvider(table_name="ParameterTable", endpoint_url="http://localhost:8000") + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Usually an endpoint is not sensitive data, so we store it in DynamoDB Table + endpoint_comments: Any = dynamodb_provider.get("comments_endpoint") + + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + # general exception + except Exception as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_dynamodb_custom_fields.py b/examples/parameters/src/builtin_provider_dynamodb_custom_fields.py new file mode 100644 index 00000000000..6936f7f0a19 --- /dev/null +++ b/examples/parameters/src/builtin_provider_dynamodb_custom_fields.py @@ -0,0 +1,24 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +dynamodb_provider = parameters.DynamoDBProvider( + table_name="ParameterTable", key_attr="IdKeyAttr", sort_attr="SkKeyAttr", value_attr="ValueAttr" +) + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Usually an endpoint is not sensitive data, so we store it in DynamoDB Table + endpoint_comments: Any = dynamodb_provider.get("comments_endpoint") + + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + # general exception + except Exception as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_dynamodb_recursive_parameter.py b/examples/parameters/src/builtin_provider_dynamodb_recursive_parameter.py new file mode 100644 index 00000000000..7db0d4d913a --- /dev/null +++ b/examples/parameters/src/builtin_provider_dynamodb_recursive_parameter.py @@ -0,0 +1,33 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +dynamodb_provider = parameters.DynamoDBProvider(table_name="ParameterTable") + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Retrieve multiple parameters using HASH KEY + all_parameters: Any = dynamodb_provider.get_multiple("config") + endpoint_comments = "https://jsonplaceholder.typicode.com/noexists/" + limit = 2 + + for parameter, value in all_parameters.items(): + + if parameter == "endpoint_comments": + endpoint_comments = value + + if parameter == "limit": + limit = int(value) + + # the value of parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[limit]} + # general exception + except Exception as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_dynamodb_single_parameter.py b/examples/parameters/src/builtin_provider_dynamodb_single_parameter.py new file mode 100644 index 00000000000..036058f2b33 --- /dev/null +++ b/examples/parameters/src/builtin_provider_dynamodb_single_parameter.py @@ -0,0 +1,22 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +dynamodb_provider = parameters.DynamoDBProvider(table_name="ParameterTable") + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Usually an endpoint is not sensitive data, so we store it in DynamoDB Table + endpoint_comments: Any = dynamodb_provider.get("comments_endpoint") + + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + # general exception + except Exception as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_secret.py b/examples/parameters/src/builtin_provider_secret.py new file mode 100644 index 00000000000..449664c1863 --- /dev/null +++ b/examples/parameters/src/builtin_provider_secret.py @@ -0,0 +1,27 @@ +from typing import Any + +import requests +from botocore.config import Config + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +config = Config(region_name="sa-east-1", connect_timeout=1, retries={"total_max_attempts": 2, "max_attempts": 5}) +ssm_provider = parameters.SecretsProvider(config=config) + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Usually an endpoint is not sensitive data, so we store it in SSM Parameters + endpoint_comments: Any = parameters.get_parameter("/lambda-powertools/endpoint_comments") + # An API-KEY is a sensitive data and should be stored in SecretsManager + api_key: Any = ssm_provider.get("/lambda-powertools/api-key") + + headers: dict = {"X-API-Key": api_key} + + comments: requests.Response = requests.get(endpoint_comments, headers=headers) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_ssm_recursive_parameter.py b/examples/parameters/src/builtin_provider_ssm_recursive_parameter.py new file mode 100644 index 00000000000..ae6c6a29a87 --- /dev/null +++ b/examples/parameters/src/builtin_provider_ssm_recursive_parameter.py @@ -0,0 +1,44 @@ +from typing import Any + +import boto3 +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +# assuming role from another account to get parameter there +# see: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html +sts_client = boto3.client("sts") +assumed_role_object = sts_client.assume_role( + RoleArn="arn:aws:iam::account-of-role-to-assume:role/name-of-role", RoleSessionName="RoleAssume1" +) +credentials = assumed_role_object["Credentials"] + +# using temporary credentials in your SSMProvider provider +# see: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#module-boto3.session +boto3_session = boto3.session.Session( + region_name="us-east-1", + aws_access_key_id=credentials["AccessKeyId"], + aws_secret_access_key=credentials["SecretAccessKey"], + aws_session_token=credentials["SessionToken"], +) +ssm_provider = parameters.SSMProvider(boto3_session=boto3_session) + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve multiple parameters from a path prefix + all_parameters: Any = ssm_provider.get_multiple("/lambda-powertools/") + endpoint_comments = "https://jsonplaceholder.typicode.com/noexists/" + + for parameter, value in all_parameters.items(): + + if parameter == "endpoint_comments": + endpoint_comments = value + + # the value of parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10]} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_ssm_single_parameter.py b/examples/parameters/src/builtin_provider_ssm_single_parameter.py new file mode 100644 index 00000000000..28217b4deb2 --- /dev/null +++ b/examples/parameters/src/builtin_provider_ssm_single_parameter.py @@ -0,0 +1,25 @@ +from typing import Any + +import requests +from botocore.config import Config + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +# changing region_name, connect_timeout and retrie configurations +# see: https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html +config = Config(region_name="sa-east-1", connect_timeout=1, retries={"total_max_attempts": 2, "max_attempts": 5}) +ssm_provider = parameters.SSMProvider(config=config) + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter + endpoint_comments: Any = ssm_provider.get("/lambda-powertools/endpoint_comments") + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/builtin_provider_ssm_with_decrypt.py b/examples/parameters/src/builtin_provider_ssm_with_decrypt.py new file mode 100644 index 00000000000..1bb4444726a --- /dev/null +++ b/examples/parameters/src/builtin_provider_ssm_with_decrypt.py @@ -0,0 +1,28 @@ +from typing import Any +from uuid import uuid4 + +import boto3 + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +ec2 = boto3.resource("ec2") +ssm_provider = parameters.SSMProvider() + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve the key pair from secure string parameter + ec2_pem: Any = ssm_provider.get("/lambda-powertools/ec2_pem", decrypt=True) + + name_key_pair = f"kp_{uuid4()}" + + ec2.import_key_pair(KeyName=name_key_pair, PublicKeyMaterial=ec2_pem) + + ec2.create_instances( + ImageId="ami-026b57f3c383c2eec", InstanceType="t2.micro", MinCount=1, MaxCount=1, KeyName=name_key_pair + ) + + return {"message": "EC2 created", "success": True} + except parameters.exceptions.GetParameterError as error: + return {"message": f"Error creating EC2 => {str(error)}", "success": False} diff --git a/examples/parameters/src/builtin_provider_ssm_with_no_recursive.py b/examples/parameters/src/builtin_provider_ssm_with_no_recursive.py new file mode 100644 index 00000000000..0f92d27bfbc --- /dev/null +++ b/examples/parameters/src/builtin_provider_ssm_with_no_recursive.py @@ -0,0 +1,39 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +ssm_provider = parameters.SSMProvider() + + +class ConfigNotFound(Exception): + ... + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve multiple parameters from a path prefix + # /config = root + # /config/endpoint = url + # /config/endpoint/query = querystring + all_parameters: Any = ssm_provider.get_multiple("/config", recursive=False) + endpoint_comments = "https://jsonplaceholder.typicode.com/comments/" + + for parameter, value in all_parameters.items(): + + # query parameter is used to query endpoint + if "query" in parameter: + endpoint_comments = f"{endpoint_comments}{value}" + break + else: + # scheme config was not found because get_multiple is not recursive + raise ConfigNotFound("URL query parameter was not found") + + # the value of parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/custom_boto3_all_providers.py b/examples/parameters/src/custom_boto3_all_providers.py new file mode 100644 index 00000000000..629eba6e5c6 --- /dev/null +++ b/examples/parameters/src/custom_boto3_all_providers.py @@ -0,0 +1,17 @@ +import boto3 +from botocore.config import Config + +from aws_lambda_powertools.utilities import parameters + +config = Config(region_name="us-west-1") + +# construct boto clients with any custom configuration +ssm = boto3.client("ssm", config=config) +secrets = boto3.client("secrets", config=config) +appconfig = boto3.client("appconfigdata", config=config) +dynamodb = boto3.resource("dynamodb", config=config) + +ssm_provider = parameters.SSMProvider(boto3_client=ssm) +secrets_provider = parameters.SecretsProvider(boto3_client=secrets) +appconf_provider = parameters.AppConfigProvider(boto3_client=appconfig, environment="my_env", application="my_app") +dynamodb_provider = parameters.DynamoDBProvider(boto3_client=dynamodb, table_name="my-table") diff --git a/examples/parameters/src/custom_boto_client.py b/examples/parameters/src/custom_boto_client.py new file mode 100644 index 00000000000..be81bb574a3 --- /dev/null +++ b/examples/parameters/src/custom_boto_client.py @@ -0,0 +1,13 @@ +import boto3 + +from aws_lambda_powertools.utilities import parameters + +boto3_client = boto3.client("ssm") +ssm_provider = parameters.SSMProvider(boto3_client=boto3_client) + + +def handler(event, context): + # Retrieve a single parameter + value = ssm_provider.get("/my/parameter") + + return value diff --git a/examples/parameters/src/custom_boto_config.py b/examples/parameters/src/custom_boto_config.py new file mode 100644 index 00000000000..8401a9bab89 --- /dev/null +++ b/examples/parameters/src/custom_boto_config.py @@ -0,0 +1,13 @@ +from botocore.config import Config + +from aws_lambda_powertools.utilities import parameters + +boto_config = Config() +ssm_provider = parameters.SSMProvider(config=boto_config) + + +def handler(event, context): + # Retrieve a single parameter + value = ssm_provider.get("/my/parameter") + + return value diff --git a/examples/parameters/src/custom_boto_session.py b/examples/parameters/src/custom_boto_session.py new file mode 100644 index 00000000000..c65481aa305 --- /dev/null +++ b/examples/parameters/src/custom_boto_session.py @@ -0,0 +1,13 @@ +import boto3 + +from aws_lambda_powertools.utilities import parameters + +boto3_session = boto3.session.Session() +ssm_provider = parameters.SSMProvider(boto3_session=boto3_session) + + +def handler(event, context): + # Retrieve a single parameter + value = ssm_provider.get("/my/parameter") + + return value diff --git a/examples/parameters/src/custom_provider_s3.py b/examples/parameters/src/custom_provider_s3.py new file mode 100644 index 00000000000..7233ac0b307 --- /dev/null +++ b/examples/parameters/src/custom_provider_s3.py @@ -0,0 +1,52 @@ +import copy +from typing import Dict + +import boto3 + +from aws_lambda_powertools.utilities.parameters import BaseProvider + + +class S3Provider(BaseProvider): + def __init__(self, bucket_name: str): + # Initialize the client to your custom parameter store + # E.g.: + + super().__init__() + + self.bucket_name = bucket_name + self.client = boto3.client("s3") + + def _get(self, name: str, **sdk_options) -> str: + # Retrieve a single value + # E.g.: + + sdk_options["Bucket"] = self.bucket_name + sdk_options["Key"] = name + + response = self.client.get_object(**sdk_options) + return response["Body"].read().decode() + + def _get_multiple(self, path: str, **sdk_options) -> Dict[str, str]: + # Retrieve multiple values + # E.g.: + + list_sdk_options = copy.deepcopy(sdk_options) + + list_sdk_options["Bucket"] = self.bucket_name + list_sdk_options["Prefix"] = path + + list_response = self.client.list_objects_v2(**list_sdk_options) + + parameters = {} + + for obj in list_response.get("Contents", []): + get_sdk_options = copy.deepcopy(sdk_options) + + get_sdk_options["Bucket"] = self.bucket_name + get_sdk_options["Key"] = obj["Key"] + + get_response = self.client.get_object(**get_sdk_options) + + parameters[obj["Key"]] = get_response["Body"].read().decode() + + return parameters diff --git a/examples/parameters/src/custom_provider_vault.py b/examples/parameters/src/custom_provider_vault.py new file mode 100644 index 00000000000..06d0a929fff --- /dev/null +++ b/examples/parameters/src/custom_provider_vault.py @@ -0,0 +1,36 @@ +import json +from typing import Dict + +from hvac import Client + +from aws_lambda_powertools.utilities.parameters import BaseProvider + + +class VaultProvider(BaseProvider): + def __init__(self, vault_url: str, vault_token: str) -> None: + + super().__init__() + + self.vault_client = Client(url=vault_url, verify=False, timeout=10) + self.vault_client.token = vault_token + + def _get(self, name: str, **sdk_options) -> str: + + # for example proposal, the mountpoint is always /secret + kv_configuration = self.vault_client.secrets.kv.v2.read_secret(path=name) + + return json.dumps(kv_configuration["data"]["data"]) + + def _get_multiple(self, path: str, **sdk_options) -> Dict[str, str]: + + list_secrets = {} + all_secrets = self.vault_client.secrets.kv.v2.list_secrets(path=path) + + # for example proposal, the mountpoint is always /secret + for secret in all_secrets["data"]["keys"]: + kv_configuration = self.vault_client.secrets.kv.v2.read_secret(path=secret) + + for key, value in kv_configuration["data"]["data"].items(): + list_secrets[key] = value + + return list_secrets diff --git a/examples/parameters/src/get_parameter_by_name_error_handling.py b/examples/parameters/src/get_parameter_by_name_error_handling.py new file mode 100644 index 00000000000..7cae4525e83 --- /dev/null +++ b/examples/parameters/src/get_parameter_by_name_error_handling.py @@ -0,0 +1,21 @@ +from typing import Any + +from aws_lambda_powertools.utilities.parameters.ssm import get_parameters_by_name + +parameters = { + "/develop/service/commons/telemetry/config": {"max_age": 300, "transform": "json"}, + # it would fail by default + "/this/param/does/not/exist": {}, +} + + +def handler(event, context): + values: dict[str, Any] = get_parameters_by_name(parameters=parameters, raise_on_error=False) + errors: list[str] = values.get("_errors", []) + + # Handle gracefully, since '/this/param/does/not/exist' will only be available in `_errors` + if errors: + ... + + for parameter, value in values.items(): + print(f"{parameter}: {value}") diff --git a/examples/parameters/src/getting_started_appconfig.py b/examples/parameters/src/getting_started_appconfig.py new file mode 100644 index 00000000000..fdb0c91d631 --- /dev/null +++ b/examples/parameters/src/getting_started_appconfig.py @@ -0,0 +1,19 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter + endpoint_comments: Any = parameters.get_app_config(name="config", environment="dev", application="comments") + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/getting_started_parameter_by_name.py b/examples/parameters/src/getting_started_parameter_by_name.py new file mode 100644 index 00000000000..95d63937ab7 --- /dev/null +++ b/examples/parameters/src/getting_started_parameter_by_name.py @@ -0,0 +1,17 @@ +from typing import Any + +from aws_lambda_powertools.utilities.parameters.ssm import get_parameters_by_name + +parameters = { + "/develop/service/commons/telemetry/config": {"max_age": 300, "transform": "json"}, + "/no_cache_param": {"max_age": 0}, + # inherit default values + "/develop/service/payment/api/capture/url": {}, +} + + +def handler(event, context): + # This returns a dict with the parameter name as key + response: dict[str, Any] = get_parameters_by_name(parameters=parameters, max_age=60) + for parameter, value in response.items(): + print(f"{parameter}: {value}") diff --git a/examples/parameters/src/getting_started_recursive_ssm_parameter.py b/examples/parameters/src/getting_started_recursive_ssm_parameter.py new file mode 100644 index 00000000000..5325a7fba96 --- /dev/null +++ b/examples/parameters/src/getting_started_recursive_ssm_parameter.py @@ -0,0 +1,26 @@ +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve multiple parameters from a path prefix + all_parameters: dict = parameters.get_parameters("/lambda-powertools/", max_age=20) + endpoint_comments = None + + for parameter, value in all_parameters.items(): + + if parameter == "endpoint_comments": + endpoint_comments = value + + if endpoint_comments is None: + return {"comments": None} + + # the value of parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10]} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/getting_started_secret.py b/examples/parameters/src/getting_started_secret.py new file mode 100644 index 00000000000..1f10394e834 --- /dev/null +++ b/examples/parameters/src/getting_started_secret.py @@ -0,0 +1,23 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Usually an endpoint is not sensitive data, so we store it in SSM Parameters + endpoint_comments: Any = parameters.get_parameter("/lambda-powertools/endpoint_comments") + # An API-KEY is a sensitive data and should be stored in SecretsManager + api_key: Any = parameters.get_secret("/lambda-powertools/api-key") + + headers: dict = {"X-API-Key": api_key} + + comments: requests.Response = requests.get(endpoint_comments, headers=headers) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/getting_started_single_ssm_parameter.py b/examples/parameters/src/getting_started_single_ssm_parameter.py new file mode 100644 index 00000000000..d31c7a180f1 --- /dev/null +++ b/examples/parameters/src/getting_started_single_ssm_parameter.py @@ -0,0 +1,17 @@ +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + try: + # Retrieve a single parameter + endpoint_comments: str = parameters.get_parameter("/lambda-powertools/endpoint_comments") # type: ignore[assignment] # noqa: E501 + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/handling_error_transform.py b/examples/parameters/src/handling_error_transform.py new file mode 100644 index 00000000000..e81a9e81809 --- /dev/null +++ b/examples/parameters/src/handling_error_transform.py @@ -0,0 +1,22 @@ +from typing import Any + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +ssm_provider = parameters.SSMProvider() + + +def lambda_handler(event: dict, context: LambdaContext): + # This will display: + # /param/a: [some value] + # /param/b: [some value] + # /param/c: None + values: Any = ssm_provider.get_multiple("/param", transform="json") + for key, value in values.items(): + print(f"{key}: {value}") + + try: + # This will raise a TransformParameterError exception + values = ssm_provider.get_multiple("/param", transform="json", raise_on_transform_error=True) + except parameters.exceptions.TransformParameterError: + ... diff --git a/examples/parameters/src/recursive_ssm_parameter_force_fetch.py b/examples/parameters/src/recursive_ssm_parameter_force_fetch.py new file mode 100644 index 00000000000..6082a0173d4 --- /dev/null +++ b/examples/parameters/src/recursive_ssm_parameter_force_fetch.py @@ -0,0 +1,25 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve multiple parameters from a path prefix + all_parameters: Any = parameters.get_parameters("/lambda-powertools/", force_fetch=True) + endpoint_comments = "https://jsonplaceholder.typicode.com/noexists/" + + for parameter, value in all_parameters.items(): + + if parameter == "endpoint_comments": + endpoint_comments = value + + # the value of parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10]} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/recursive_ssm_parameter_with_cache.py b/examples/parameters/src/recursive_ssm_parameter_with_cache.py new file mode 100644 index 00000000000..9cf48b39dde --- /dev/null +++ b/examples/parameters/src/recursive_ssm_parameter_with_cache.py @@ -0,0 +1,25 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve multiple parameters from a path prefix + all_parameters: Any = parameters.get_parameters("/lambda-powertools/", max_age=20) + endpoint_comments = "https://jsonplaceholder.typicode.com/noexists/" + + for parameter, value in all_parameters.items(): + + if parameter == "endpoint_comments": + endpoint_comments = value + + # the value of parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10]} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/secret_force_fetch.py b/examples/parameters/src/secret_force_fetch.py new file mode 100644 index 00000000000..121d9f57bfb --- /dev/null +++ b/examples/parameters/src/secret_force_fetch.py @@ -0,0 +1,23 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Usually an endpoint is not sensitive data, so we store it in SSM Parameters + endpoint_comments: Any = parameters.get_parameter("/lambda-powertools/endpoint_comments") + # An API-KEY is a sensitive data and should be stored in SecretsManager + api_key: Any = parameters.get_secret("/lambda-powertools/api-key", force_fetch=True) + + headers: dict = {"X-API-Key": api_key} + + comments: requests.Response = requests.get(endpoint_comments, headers=headers) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/secret_with_cache.py b/examples/parameters/src/secret_with_cache.py new file mode 100644 index 00000000000..8d3ed927107 --- /dev/null +++ b/examples/parameters/src/secret_with_cache.py @@ -0,0 +1,23 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Usually an endpoint is not sensitive data, so we store it in SSM Parameters + endpoint_comments: Any = parameters.get_parameter("/lambda-powertools/endpoint_comments") + # An API-KEY is a sensitive data and should be stored in SecretsManager + api_key: Any = parameters.get_secret("/lambda-powertools/api-key", max_age=20) + + headers: dict = {"X-API-Key": api_key} + + comments: requests.Response = requests.get(endpoint_comments, headers=headers) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/single_ssm_parameter_force_fetch.py b/examples/parameters/src/single_ssm_parameter_force_fetch.py new file mode 100644 index 00000000000..7b45c1be216 --- /dev/null +++ b/examples/parameters/src/single_ssm_parameter_force_fetch.py @@ -0,0 +1,19 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter with 20s cache + endpoint_comments: Any = parameters.get_parameter("/lambda-powertools/endpoint_comments", force_fetch=True) + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/single_ssm_parameter_with_cache.py b/examples/parameters/src/single_ssm_parameter_with_cache.py new file mode 100644 index 00000000000..1be8632bc00 --- /dev/null +++ b/examples/parameters/src/single_ssm_parameter_with_cache.py @@ -0,0 +1,19 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter with 20s cache + endpoint_comments: Any = parameters.get_parameter("/lambda-powertools/endpoint_comments", max_age=20) + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/working_with_auto_transform.py b/examples/parameters/src/working_with_auto_transform.py new file mode 100644 index 00000000000..fc29d376606 --- /dev/null +++ b/examples/parameters/src/working_with_auto_transform.py @@ -0,0 +1,10 @@ +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +ssm_provider = parameters.SSMProvider() + + +def lambda_handler(event: dict, context: LambdaContext): + values = ssm_provider.get_multiple("/param", transform="auto") + + return values diff --git a/examples/parameters/src/working_with_own_provider_s3.py b/examples/parameters/src/working_with_own_provider_s3.py new file mode 100644 index 00000000000..d4f011a9e23 --- /dev/null +++ b/examples/parameters/src/working_with_own_provider_s3.py @@ -0,0 +1,30 @@ +from typing import Any + +import requests +from custom_provider_s3 import S3Provider + +from aws_lambda_powertools import Logger +from aws_lambda_powertools.utilities.typing import LambdaContext + +logger = Logger() + +s3_provider = S3Provider(bucket_name="bucket_name") + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Retrieve a single parameter using key + endpoint_comments: Any = s3_provider.get("comments_endpoint") + # you can get all parameters using get_multiple and specifying a bucket prefix + # # for testing purposes we will not use it + all_parameters: Any = s3_provider.get_multiple("/") + logger.info(all_parameters) + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + # general exception + except Exception as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/working_with_own_provider_vault.py b/examples/parameters/src/working_with_own_provider_vault.py new file mode 100644 index 00000000000..7be9ea60242 --- /dev/null +++ b/examples/parameters/src/working_with_own_provider_vault.py @@ -0,0 +1,35 @@ +from typing import Any + +import hvac +import requests +from custom_provider_vault import VaultProvider + +from aws_lambda_powertools import Logger +from aws_lambda_powertools.utilities.typing import LambdaContext + +logger = Logger() + +# In production you must use Vault over HTTPS and certificates. +vault_provider = VaultProvider(vault_url="http://192.168.68.105:8200/", vault_token="YOUR_TOKEN") + + +def lambda_handler(event: dict, context: LambdaContext): + + try: + # Retrieve a single parameter + endpoint_comments: Any = vault_provider.get("comments_endpoint", transform="json") + + # you can get all parameters using get_multiple and specifying vault mount point + # # for testing purposes we will not use it + all_parameters: Any = vault_provider.get_multiple("/") + logger.info(all_parameters) + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments["url"]) + + return {"comments": comments.json()[:10], "statusCode": 200} + except hvac.exceptions.InvalidPath as error: + return {"comments": None, "message": str(error), "statusCode": 400} + # general exception + except Exception as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/working_with_sdk_additional_arguments.py b/examples/parameters/src/working_with_sdk_additional_arguments.py new file mode 100644 index 00000000000..4f99714d817 --- /dev/null +++ b/examples/parameters/src/working_with_sdk_additional_arguments.py @@ -0,0 +1,11 @@ +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +secrets_provider = parameters.SecretsProvider() + + +def lambda_handler(event: dict, context: LambdaContext): + # The 'VersionId' argument will be passed to the underlying get_secret_value() call. + value = secrets_provider.get("my-secret", VersionId="e62ec170-6b01-48c7-94f3-d7497851a8d2") + + return value diff --git a/examples/parameters/src/working_with_transform_high_level.py b/examples/parameters/src/working_with_transform_high_level.py new file mode 100644 index 00000000000..ee00862bf72 --- /dev/null +++ b/examples/parameters/src/working_with_transform_high_level.py @@ -0,0 +1,19 @@ +from typing import Any + +import requests + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + try: + # Retrieve a single parameter + endpoint_comments: Any = parameters.get_parameter("/lambda-powertools/endpoint_comments", transform="json") + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/src/working_with_transform_provider.py b/examples/parameters/src/working_with_transform_provider.py new file mode 100644 index 00000000000..948ae1710b3 --- /dev/null +++ b/examples/parameters/src/working_with_transform_provider.py @@ -0,0 +1,23 @@ +from typing import Any + +import requests +from botocore.config import Config + +from aws_lambda_powertools.utilities import parameters +from aws_lambda_powertools.utilities.typing import LambdaContext + +config = Config(region_name="sa-east-1") +appconf_provider = parameters.AppConfigProvider(environment="dev", application="comments", config=config) + + +def lambda_handler(event: dict, context: LambdaContext): + try: + # Retrieve a single parameter + endpoint_comments: Any = appconf_provider.get("config", transform="json") + + # the value of this parameter is https://jsonplaceholder.typicode.com/comments/ + comments: requests.Response = requests.get(endpoint_comments) + + return {"comments": comments.json()[:10], "statusCode": 200} + except parameters.exceptions.GetParameterError as error: + return {"comments": None, "message": str(error), "statusCode": 400} diff --git a/examples/parameters/tests/src/__init__.py b/examples/parameters/tests/src/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/parameters/tests/src/app.py b/examples/parameters/tests/src/app.py new file mode 100644 index 00000000000..b505749e31b --- /dev/null +++ b/examples/parameters/tests/src/app.py @@ -0,0 +1,10 @@ +from botocore.config import Config + +from aws_lambda_powertools.utilities import parameters + +ssm_provider = parameters.SSMProvider(config=Config(region_name="us-west-1")) + + +def handler(event, context): + value = ssm_provider.get("/my/parameter") + return {"message": value} diff --git a/examples/parameters/tests/src/single_mock.py b/examples/parameters/tests/src/single_mock.py new file mode 100644 index 00000000000..ef94df54f25 --- /dev/null +++ b/examples/parameters/tests/src/single_mock.py @@ -0,0 +1,7 @@ +from aws_lambda_powertools.utilities import parameters + + +def handler(event, context): + # Retrieve a single parameter + value = parameters.get_parameter("my-parameter-name") + return {"message": value} diff --git a/examples/parameters/tests/test_clear_cache_global.py b/examples/parameters/tests/test_clear_cache_global.py new file mode 100644 index 00000000000..5b07f40caed --- /dev/null +++ b/examples/parameters/tests/test_clear_cache_global.py @@ -0,0 +1,24 @@ +import pytest +import src.app as app + +from aws_lambda_powertools.utilities import parameters + + +@pytest.fixture(scope="function", autouse=True) +def clear_parameters_cache(): + yield + parameters.clear_caches() # This will clear all providers cache + + +@pytest.fixture +def mock_parameter_response(monkeypatch): + def mockreturn(name): + return "mock_value" + + monkeypatch.setattr(app.ssm_provider, "get", mockreturn) + + +# Pass our fixture as an argument to all tests where we want to mock the get_parameter response +def test_handler(mock_parameter_response): + return_val = app.handler({}, {}) + assert return_val.get("message") == "mock_value" diff --git a/examples/parameters/tests/test_clear_cache_method.py b/examples/parameters/tests/test_clear_cache_method.py new file mode 100644 index 00000000000..da1eb181c68 --- /dev/null +++ b/examples/parameters/tests/test_clear_cache_method.py @@ -0,0 +1,22 @@ +import pytest +import src.app as app + + +@pytest.fixture(scope="function", autouse=True) +def clear_parameters_cache(): + yield + app.ssm_provider.clear_cache() # This will clear SSMProvider cache + + +@pytest.fixture +def mock_parameter_response(monkeypatch): + def mockreturn(name): + return "mock_value" + + monkeypatch.setattr(app.ssm_provider, "get", mockreturn) + + +# Pass our fixture as an argument to all tests where we want to mock the get_parameter response +def test_handler(mock_parameter_response): + return_val = app.handler({}, {}) + assert return_val.get("message") == "mock_value" diff --git a/examples/parameters/tests/test_single_mock.py b/examples/parameters/tests/test_single_mock.py new file mode 100644 index 00000000000..c4d045be499 --- /dev/null +++ b/examples/parameters/tests/test_single_mock.py @@ -0,0 +1,10 @@ +import src.single_mock as single_mock + + +def test_handler(monkeypatch): + def mockreturn(name): + return "mock_value" + + monkeypatch.setattr(single_mock.parameters, "get_parameter", mockreturn) + return_val = single_mock.handler({}, {}) + assert return_val.get("message") == "mock_value" diff --git a/examples/parameters/tests/test_with_fixture.py b/examples/parameters/tests/test_with_fixture.py new file mode 100644 index 00000000000..0d29ad28030 --- /dev/null +++ b/examples/parameters/tests/test_with_fixture.py @@ -0,0 +1,16 @@ +import pytest +import src.single_mock as single_mock + + +@pytest.fixture +def mock_parameter_response(monkeypatch): + def mockreturn(name): + return "mock_value" + + monkeypatch.setattr(single_mock.parameters, "get_parameter", mockreturn) + + +# Pass our fixture as an argument to all tests where we want to mock the get_parameter response +def test_handler(mock_parameter_response): + return_val = single_mock.handler({}, {}) + assert return_val.get("message") == "mock_value" diff --git a/examples/parameters/tests/test_with_monkeypatch.py b/examples/parameters/tests/test_with_monkeypatch.py new file mode 100644 index 00000000000..71ac4b406ed --- /dev/null +++ b/examples/parameters/tests/test_with_monkeypatch.py @@ -0,0 +1,13 @@ +from unittest.mock import patch + +import src.single_mock as single_mock + + +# Replaces "aws_lambda_powertools.utilities.parameters.get_parameter" with a Mock object +@patch("aws_lambda_powertools.utilities.parameters.get_parameter") +def test_handler(get_parameter_mock): + get_parameter_mock.return_value = "mock_value" + + return_val = single_mock.handler({}, {}) + get_parameter_mock.assert_called_with("my-parameter-name") + assert return_val.get("message") == "mock_value" diff --git a/mypy.ini b/mypy.ini index 6ab4cb0de32..fd14881dfb1 100644 --- a/mypy.ini +++ b/mypy.ini @@ -53,5 +53,8 @@ ignore_missing_imports = True [mypy-snappy] ignore_missing_imports = True +[mypy-hvac] +ignore_missing_imports = True + [mypy-ijson] ignore_missing_imports = True diff --git a/poetry.lock b/poetry.lock index b06738c5b3a..ee2d038ae92 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,36 +2,37 @@ [[package]] name = "attrs" -version = "22.1.0" +version = "22.2.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, - {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, ] [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] +tests = ["attrs[tests-no-zope]", "zope.interface"] +tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] [[package]] name = "aws-cdk-asset-awscli-v1" -version = "2.2.49" +version = "2.2.52" description = "A library that contains the AWS CLI for use in Lambda Layers" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.asset-awscli-v1-2.2.49.tar.gz", hash = "sha256:d367da8bdc83357792b1ef16b6166d400ef15f2389cf0032b607b6327768a41a"}, - {file = "aws_cdk.asset_awscli_v1-2.2.49-py3-none-any.whl", hash = "sha256:28df4487e2fa5314d5c39c114e12d366714a1fab2de3269d55c4e544876cae44"}, + {file = "aws-cdk.asset-awscli-v1-2.2.52.tar.gz", hash = "sha256:ab04beec8e267e363931df2caf48a24100cb5799d7fd8db51efe881d117efa7a"}, + {file = "aws_cdk.asset_awscli_v1-2.2.52-py3-none-any.whl", hash = "sha256:6e9d686bb0b00242e869e91d57b65b619ffb42e99abe482436e3a6692485dbfe"}, ] [package.dependencies] -jsii = ">=1.72.0,<2.0.0" +jsii = ">=1.73.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" @@ -54,57 +55,57 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-asset-node-proxy-agent-v5" -version = "2.0.38" +version = "2.0.42" description = "@aws-cdk/asset-node-proxy-agent-v5" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.asset-node-proxy-agent-v5-2.0.38.tar.gz", hash = "sha256:eb80e0098899bd29e4f0938c68802cc022a8e39af8c05de4053f9a209e63bb7c"}, - {file = "aws_cdk.asset_node_proxy_agent_v5-2.0.38-py3-none-any.whl", hash = "sha256:0add1debe24e566b8d2cf713ca85eb5e82c42de00f737dfbf02e18e22220a41b"}, + {file = "aws-cdk.asset-node-proxy-agent-v5-2.0.42.tar.gz", hash = "sha256:ae1b615be42e78681e05b145460603f171c06b671a2d1caa060a159b94b06366"}, + {file = "aws_cdk.asset_node_proxy_agent_v5-2.0.42-py3-none-any.whl", hash = "sha256:6e0174802097d558daa1be5c4e6e7f309eeba626392955e596bf967ee37865d3"}, ] [package.dependencies] -jsii = ">=1.72.0,<2.0.0" +jsii = ">=1.73.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-alpha" -version = "2.53.0a0" +version = "2.62.2a0" description = "The CDK Construct Library for AWS::APIGatewayv2" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-alpha-2.53.0a0.tar.gz", hash = "sha256:7bfd688d3c22676266ff161012f11ff3f60e11e50ba0d39d18a313ff07f69bbd"}, - {file = "aws_cdk.aws_apigatewayv2_alpha-2.53.0a0-py3-none-any.whl", hash = "sha256:6864d15ea12c903ae6ca679aaec49dd6c65fc1b537cd317c62cd334f7a382683"}, + {file = "aws-cdk.aws-apigatewayv2-alpha-2.62.2a0.tar.gz", hash = "sha256:63c191fdcb8b20d1afd34af84ae465740b14009a06af7bdc8e78475614f85a23"}, + {file = "aws_cdk.aws_apigatewayv2_alpha-2.62.2a0-py3-none-any.whl", hash = "sha256:32ff5d8745b71ef30ba009de4d8d9f12bd34a4f3c940500ba34367211f05c9f4"}, ] [package.dependencies] -aws-cdk-lib = ">=2.53.0,<3.0.0" +aws-cdk-lib = ">=2.62.2,<3.0.0" constructs = ">=10.0.0,<11.0.0" -jsii = ">=1.71.0,<2.0.0" +jsii = ">=1.73.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-integrations-alpha" -version = "2.53.0a0" +version = "2.62.2a0" description = "Integrations for AWS APIGateway V2" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.53.0a0.tar.gz", hash = "sha256:fb8bf5812908787a776a9dc5a13bbacec0b39f07517f9a57ebba33d9585ab131"}, - {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.53.0a0-py3-none-any.whl", hash = "sha256:4419283b9a0f41c0cfc5e4a8ba0b0236ca948d874c1c165f058c2c1677ffe6d1"}, + {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.62.2a0.tar.gz", hash = "sha256:4ae06b6585664c659eb6b88ff70eaa628a96ffb4728ab0d0eb7ff1f23913565b"}, + {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.62.2a0-py3-none-any.whl", hash = "sha256:497e93d193895b1b38545d5ca152e31f575b971ce371ad655aeb3bbed7fc6052"}, ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.53.0.a0" -aws-cdk-lib = ">=2.53.0,<3.0.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.62.2.a0" +aws-cdk-lib = ">=2.62.2,<3.0.0" constructs = ">=10.0.0,<11.0.0" -jsii = ">=1.71.0,<2.0.0" +jsii = ">=1.73.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" @@ -131,23 +132,25 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-sam-translator" -version = "1.55.0" +version = "1.58.1" description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates" category = "dev" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "aws-sam-translator-1.55.0.tar.gz", hash = "sha256:08e182e76d6fabc13ce2f38b8a3932b3131407c6ad29ec2849ef3d9a41576b94"}, - {file = "aws_sam_translator-1.55.0-py2-none-any.whl", hash = "sha256:e86a67b87329a0de7d531d33257d1a448d0d6ecd84aee058d084957f28a8e4b1"}, - {file = "aws_sam_translator-1.55.0-py3-none-any.whl", hash = "sha256:93dc74614ab291c86be681e025679d08f4fa685ed6b55d410f62f2f235012205"}, + {file = "aws-sam-translator-1.58.1.tar.gz", hash = "sha256:cd60a19085d432bc00769b597bc2e6854f546ff9928f8067fc5fbcb5a1ed74ff"}, + {file = "aws_sam_translator-1.58.1-py2-none-any.whl", hash = "sha256:c4e261e450d574572d389edcafab04d1fe337615f867610410390c2435cb1f26"}, + {file = "aws_sam_translator-1.58.1-py3-none-any.whl", hash = "sha256:ca47d6eb04d8cf358bea9160411193da40a80dc3e79bb0c5bace0c21f0e4c888"}, ] [package.dependencies] boto3 = ">=1.19.5,<2.0.0" -jsonschema = ">=3.2,<4.0" +jsonschema = ">=3.2,<5" +pydantic = ">=1.10.2,<1.11.0" +typing-extensions = ">=4.4.0,<4.5.0" [package.extras] -dev = ["black (==20.8b1)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.0.0)", "click (>=7.1,<8.0)", "coverage (>=5.3,<6.0)", "dateparser (>=0.7,<1.0)", "docopt (>=0.6.2,<0.7.0)", "flake8 (>=3.8.4,<3.9.0)", "mypy (==0.971)", "parameterized (>=0.7.4,<0.8.0)", "pylint (>=2.15.0,<2.16.0)", "pytest (>=6.2.5,<6.3.0)", "pytest-cov (>=2.10.1,<2.11.0)", "pytest-env (>=0.6.2,<0.7.0)", "pytest-rerunfailures (>=9.1.1,<9.2.0)", "pytest-xdist (>=2.5,<3.0)", "pyyaml (>=5.4,<6.0)", "requests (>=2.24.0,<2.25.0)", "ruamel.yaml (==0.17.21)", "tenacity (>=7.0.0,<7.1.0)", "tox (>=3.24,<4.0)", "types-PyYAML (>=5.4,<6.0)", "types-jsonschema (>=3.2,<4.0)"] +dev = ["black (==20.8b1)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.0.0)", "click (>=7.1,<8.0)", "coverage (>=5.3,<6.0)", "dateparser (>=0.7,<1.0)", "docopt (>=0.6.2,<0.7.0)", "flake8 (>=3.8.4,<3.9.0)", "mypy (==0.971)", "parameterized (>=0.7.4,<0.8.0)", "pylint (>=2.15.0,<2.16.0)", "pytest (>=6.2.5,<6.3.0)", "pytest-cov (>=2.10.1,<2.11.0)", "pytest-env (>=0.6.2,<0.7.0)", "pytest-rerunfailures (>=9.1.1,<9.2.0)", "pytest-xdist (>=2.5,<3.0)", "pyyaml (>=5.4,<6.0)", "requests (>=2.25.0,<2.26.0)", "ruamel.yaml (==0.17.21)", "tenacity (>=7.0.0,<7.1.0)", "tox (>=3.24,<4.0)", "types-PyYAML (>=5.4,<6.0)", "types-jsonschema (>=3.2,<4.0)"] [[package]] name = "aws-xray-sdk" @@ -227,18 +230,18 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.26.18" +version = "1.26.60" description = "The AWS SDK for Python" category = "main" optional = false python-versions = ">= 3.7" files = [ - {file = "boto3-1.26.18-py3-none-any.whl", hash = "sha256:933c88b189112a5fdd82d49ef00f95b9dd649d195e557a81aecb773a3e01c517"}, - {file = "boto3-1.26.18.tar.gz", hash = "sha256:3c7315da16eb0b41823965e5ce55f99cb07e94680e0ed7830c581f505fb5bd15"}, + {file = "boto3-1.26.60-py3-none-any.whl", hash = "sha256:5fd2810217a74a38078a19fb85a9e5d6934d0c146eb060967a3ffd7ab33cdf00"}, + {file = "boto3-1.26.60.tar.gz", hash = "sha256:f0824b3bcf803800d3ecef903b4840427e4b3d37a069f6fc9a86310f7e036ad5"}, ] [package.dependencies] -botocore = ">=1.29.18,<1.30.0" +botocore = ">=1.29.60,<1.30.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.6.0,<0.7.0" @@ -247,14 +250,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.29.18" +version = "1.29.60" description = "Low-level, data-driven core of boto 3." category = "main" optional = false python-versions = ">= 3.7" files = [ - {file = "botocore-1.29.18-py3-none-any.whl", hash = "sha256:2aba44433b6eac6d3a12cf93f2985e2d7a843307c1a527042fc48dd09b273992"}, - {file = "botocore-1.29.18.tar.gz", hash = "sha256:26e86fce95049f6cc18b5611901549943c4c22522fa8a3b6b265404f673977b2"}, + {file = "botocore-1.29.60-py3-none-any.whl", hash = "sha256:c4ae251e7df0cf01d893eb945bc8f23c14989ed349775a8e16c949f08a068f9a"}, + {file = "botocore-1.29.60.tar.gz", hash = "sha256:a21217ccf4613c9ebbe4c3192e13ba91d46be642560e39a16406662a398a107b"}, ] [package.dependencies] @@ -263,7 +266,7 @@ python-dateutil = ">=2.1,<3.0.0" urllib3 = ">=1.25.4,<1.27" [package.extras] -crt = ["awscrt (==0.14.0)"] +crt = ["awscrt (==0.15.3)"] [[package]] name = "cattrs" @@ -318,19 +321,102 @@ sarif-om = ">=1.0.4,<1.1.0" [[package]] name = "charset-normalizer" -version = "2.1.1" +version = "3.0.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "dev" optional = false -python-versions = ">=3.6.0" +python-versions = "*" files = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, + {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"}, + {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"}, ] -[package.extras] -unicode-backport = ["unicodedata2"] - [[package]] name = "checksumdir" version = "1.2.0" @@ -373,18 +459,18 @@ files = [ [[package]] name = "constructs" -version = "10.1.174" +version = "10.1.236" description = "A programming model for software-defined state" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "constructs-10.1.174-py3-none-any.whl", hash = "sha256:6968efd5f837f3a43d5a93808424744cdcd03f53df764be78123f60e81b39b0a"}, - {file = "constructs-10.1.174.tar.gz", hash = "sha256:af9bd1f0bd6882a6a608bc335a4f8a230f498072bff83d9126d43c486e30305b"}, + {file = "constructs-10.1.236-py3-none-any.whl", hash = "sha256:e51d8fac38b12a88359d5d2bedb535987eaa54e68631add29726652be66490e9"}, + {file = "constructs-10.1.236.tar.gz", hash = "sha256:10b3c5ed3d4c6fd930bd8f59c8a5926028dafe8a5bf703fba5bcc53c89fce002"}, ] [package.dependencies] -jsii = ">=1.71.0,<2.0.0" +jsii = ">=1.74.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" @@ -481,14 +567,14 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.0.4" +version = "1.1.0" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, - {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, + {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, + {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, ] [package.extras] @@ -766,6 +852,22 @@ files = [ gitdb = ">=4.0.1,<5" typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} +[[package]] +name = "hvac" +version = "1.0.2" +description = "HashiCorp Vault API client" +category = "dev" +optional = false +python-versions = ">=3.6.2,<4.0.0" +files = [ + {file = "hvac-1.0.2-py3-none-any.whl", hash = "sha256:e8256343de2576b18bc8d49f09a04c728f2a8f3a866825bb413aa4f9ebab1fea"}, + {file = "hvac-1.0.2.tar.gz", hash = "sha256:e4028c5c0ecc7b7fcf6a54d290f99240e5abcdb9ffe442d1c14f061310d4c61c"}, +] + +[package.dependencies] +pyhcl = ">=0.4.4,<0.5.0" +requests = ">=2.27.1,<3.0.0" + [[package]] name = "idna" version = "3.4" @@ -887,16 +989,35 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker perf = ["ipython"] testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +[[package]] +name = "importlib-resources" +version = "5.10.2" +description = "Read resources from Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "importlib_resources-5.10.2-py3-none-any.whl", hash = "sha256:7d543798b0beca10b6a01ac7cafda9f822c54db9e8376a6bf57e0cbd74d486b6"}, + {file = "importlib_resources-5.10.2.tar.gz", hash = "sha256:e4a96c8cc0339647ff9a5e0550d9f276fc5a01ffa276012b58ec108cfd7b8484"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] + [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] @@ -966,14 +1087,14 @@ pbr = "*" [[package]] name = "jsii" -version = "1.73.0" +version = "1.74.0" description = "Python client for jsii runtime" category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "jsii-1.73.0-py3-none-any.whl", hash = "sha256:13e8496c3afee70d85401ad1eef2ddedbdb88e7e7abb3e68302dd6e61527191e"}, - {file = "jsii-1.73.0.tar.gz", hash = "sha256:be6458236e787be0b02c2fe869b6f4ed906398b6cc537190d61a60d2b5c9dfbb"}, + {file = "jsii-1.74.0-py3-none-any.whl", hash = "sha256:ee76781fe66106c367fbb3bb383db4f5e9b8ff3d3c4c0f34624c050211f040be"}, + {file = "jsii-1.74.0.tar.gz", hash = "sha256:575131396ad34f8f6e9f2604953ecbf4f3368625656a828b13089e4abb81b443"}, ] [package.dependencies] @@ -1001,14 +1122,14 @@ jsonpointer = ">=1.9" [[package]] name = "jsonpickle" -version = "2.2.0" +version = "3.0.1" description = "Python library for serializing any arbitrary object graph into JSON" category = "dev" optional = false -python-versions = ">=2.7" +python-versions = ">=3.7" files = [ - {file = "jsonpickle-2.2.0-py2.py3-none-any.whl", hash = "sha256:de7f2613818aa4f234138ca11243d6359ff83ae528b2185efdd474f62bcf9ae1"}, - {file = "jsonpickle-2.2.0.tar.gz", hash = "sha256:7b272918b0554182e53dc340ddd62d9b7f902fec7e7b05620c04f3ccef479a0e"}, + {file = "jsonpickle-3.0.1-py2.py3-none-any.whl", hash = "sha256:130d8b293ea0add3845de311aaba55e6d706d0bb17bc123bd2c8baf8a39ac77c"}, + {file = "jsonpickle-3.0.1.tar.gz", hash = "sha256:032538804795e73b94ead410800ac387fdb6de98f8882ac957fcd247e3a85200"}, ] [package.dependencies] @@ -1016,8 +1137,8 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [package.extras] docs = ["jaraco.packaging (>=3.2)", "rst.linker (>=1.9)", "sphinx"] -testing = ["ecdsa", "enum34", "feedparser", "jsonlib", "numpy", "pandas", "pymongo", "pytest (>=3.5,!=3.7.3)", "pytest-black-multipy", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-flake8 (<1.1.0)", "pytest-flake8 (>=1.1.1)", "scikit-learn", "sqlalchemy"] -testing-libs = ["simplejson", "ujson", "yajl"] +testing = ["ecdsa", "feedparser", "gmpy2", "numpy", "pandas", "pymongo", "pytest (>=3.5,!=3.7.3)", "pytest-black-multipy", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-flake8 (>=1.1.1)", "scikit-learn", "sqlalchemy"] +testing-libs = ["simplejson", "ujson"] [[package]] name = "jsonpointer" @@ -1033,26 +1154,27 @@ files = [ [[package]] name = "jsonschema" -version = "3.2.0" +version = "4.17.3" description = "An implementation of JSON Schema validation for Python" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, + {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, + {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, ] [package.dependencies] attrs = ">=17.4.0" importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -pyrsistent = ">=0.14.0" -setuptools = "*" -six = ">=1.11.0" +importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} +pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] -format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] -format-nongpl = ["idna", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "webcolors"] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] [[package]] name = "junit-xml" @@ -1062,7 +1184,6 @@ category = "dev" optional = false python-versions = "*" files = [ - {file = "junit-xml-1.9.tar.gz", hash = "sha256:de16a051990d4e25a3982b2dd9e89d671067548718866416faec14d9de56db9f"}, {file = "junit_xml-1.9-py2.py3-none-any.whl", hash = "sha256:ec5ca1a55aefdd76d28fcc0b135251d156c7106fa979686a4b48d62b761b4732"}, ] @@ -1128,52 +1249,62 @@ testing = ["coverage", "pyyaml"] [[package]] name = "markupsafe" -version = "2.1.1" +version = "2.1.2" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, - {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"}, + {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"}, ] [[package]] @@ -1282,14 +1413,14 @@ mkdocs = ">=0.17" [[package]] name = "mkdocs-material" -version = "9.0.8" +version = "9.0.9" description = "Documentation that simply works" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mkdocs_material-9.0.8-py3-none-any.whl", hash = "sha256:03f8a2249627efb91a57d9f4a4e298d2d61d6e65fe2a864cc5961dc540bdd540"}, - {file = "mkdocs_material-9.0.8.tar.gz", hash = "sha256:268e7aab0b8585352400b4e93bfe4efd0ca213005d7bae1a0ec69b7ded205fcd"}, + {file = "mkdocs_material-9.0.9-py3-none-any.whl", hash = "sha256:29ebb2aa81e8cfb39e497bdafcacf4cc4aaa20ae31ce334f520c317c5bead1ba"}, + {file = "mkdocs_material-9.0.9.tar.gz", hash = "sha256:c8fa9b1f0fded744a42317e594e5c21f4e3b56f1a0497e7d16951b3bd47784bf"}, ] [package.dependencies] @@ -1392,14 +1523,14 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-cloudformation" -version = "1.26.57" -description = "Type annotations for boto3.CloudFormation 1.26.57 service generated with mypy-boto3-builder 7.12.3" +version = "1.26.60" +description = "Type annotations for boto3.CloudFormation 1.26.60 service generated with mypy-boto3-builder 7.12.3" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudformation-1.26.57.tar.gz", hash = "sha256:c1659cf032825293b3eef1acca1a29fb82a7149b6c3ce06bbf405f54b78d3172"}, - {file = "mypy_boto3_cloudformation-1.26.57-py3-none-any.whl", hash = "sha256:4a45872b0fc1d503fa1147560fd842d3bcbec38aad4ca3516b51c33e6dfa05f2"}, + {file = "mypy-boto3-cloudformation-1.26.60.tar.gz", hash = "sha256:1966b0f521e73d8d043e2499f33e252c71a7dba79bf79d89cb4a0bd8a79180a0"}, + {file = "mypy_boto3_cloudformation-1.26.60-py3-none-any.whl", hash = "sha256:30305e6055076acc48e4346f599b6b24e1b1281d95aabb4d8b335f3915a001fa"}, ] [package.dependencies] @@ -1558,41 +1689,38 @@ test = ["codecov (>=2.1)", "pytest (>=6.2)", "pytest-cov (>=2.12)"] [[package]] name = "packaging" -version = "21.3" +version = "23.0" description = "Core utilities for Python packages" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, ] -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" - [[package]] name = "pathspec" -version = "0.10.2" +version = "0.11.0" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, - {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, + {file = "pathspec-0.11.0-py3-none-any.whl", hash = "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229"}, + {file = "pathspec-0.11.0.tar.gz", hash = "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"}, ] [[package]] name = "pbr" -version = "5.11.0" +version = "5.11.1" description = "Python Build Reasonableness" category = "dev" optional = false python-versions = ">=2.6" files = [ - {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, - {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, + {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, + {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, ] [[package]] @@ -1611,21 +1739,36 @@ files = [ mako = "*" markdown = ">=3.0" +[[package]] +name = "pkgutil-resolve-name" +version = "1.3.10" +description = "Resolve a name to an object." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, + {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, +] + [[package]] name = "platformdirs" -version = "2.5.4" +version = "2.6.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, - {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, + {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, + {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""} + [package.extras] -docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] -test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -1711,7 +1854,7 @@ name = "pydantic" version = "1.10.4" description = "Data validation and settings management using python type hints" category = "main" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "pydantic-1.10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5635de53e6686fe7a44b5cf25fcc419a0d5e5c1a1efe73d49d48fe7586db854"}, @@ -1799,65 +1942,66 @@ files = [ plugins = ["importlib-metadata"] [[package]] -name = "pymdown-extensions" -version = "9.9.1" -description = "Extension pack for Python Markdown." +name = "pyhcl" +version = "0.4.4" +description = "HCL configuration parser for python" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = "*" files = [ - {file = "pymdown_extensions-9.9.1-py3-none-any.whl", hash = "sha256:8a8973933ab45b6fe8f5f8da1de25766356b1f91dee107bf4a34efd158dc340b"}, - {file = "pymdown_extensions-9.9.1.tar.gz", hash = "sha256:abed29926960bbb3b40f5ed5fa6375e29724d4e3cb86ced7c2bbd37ead1afeea"}, + {file = "pyhcl-0.4.4.tar.gz", hash = "sha256:2d9b9dcdf1023d812bfed561ba72c99104c5b3f52e558d595130a44ce081b003"}, ] -[package.dependencies] -markdown = ">=3.2" - [[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" +name = "pymdown-extensions" +version = "9.9.2" +description = "Extension pack for Python Markdown." category = "dev" optional = false -python-versions = ">=3.6.8" +python-versions = ">=3.7" files = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, + {file = "pymdown_extensions-9.9.2-py3-none-any.whl", hash = "sha256:c3d804eb4a42b85bafb5f36436342a5ad38df03878bb24db8855a4aa8b08b765"}, + {file = "pymdown_extensions-9.9.2.tar.gz", hash = "sha256:ebb33069bafcb64d5f5988043331d4ea4929325dc678a6bcf247ddfcf96499f8"}, ] -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] +[package.dependencies] +markdown = ">=3.2" [[package]] name = "pyrsistent" -version = "0.19.2" +version = "0.19.3" description = "Persistent/Functional/Immutable data structures" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pyrsistent-0.19.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d6982b5a0237e1b7d876b60265564648a69b14017f3b5f908c5be2de3f9abb7a"}, - {file = "pyrsistent-0.19.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:187d5730b0507d9285a96fca9716310d572e5464cadd19f22b63a6976254d77a"}, - {file = "pyrsistent-0.19.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:055ab45d5911d7cae397dc418808d8802fb95262751872c841c170b0dbf51eed"}, - {file = "pyrsistent-0.19.2-cp310-cp310-win32.whl", hash = "sha256:456cb30ca8bff00596519f2c53e42c245c09e1a4543945703acd4312949bfd41"}, - {file = "pyrsistent-0.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:b39725209e06759217d1ac5fcdb510e98670af9e37223985f330b611f62e7425"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aede922a488861de0ad00c7630a6e2d57e8023e4be72d9d7147a9fcd2d30712"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879b4c2f4d41585c42df4d7654ddffff1239dc4065bc88b745f0341828b83e78"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c43bec251bbd10e3cb58ced80609c5c1eb238da9ca78b964aea410fb820d00d6"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-win32.whl", hash = "sha256:d690b18ac4b3e3cab73b0b7aa7dbe65978a172ff94970ff98d82f2031f8971c2"}, - {file = "pyrsistent-0.19.2-cp37-cp37m-win_amd64.whl", hash = "sha256:3ba4134a3ff0fc7ad225b6b457d1309f4698108fb6b35532d015dca8f5abed73"}, - {file = "pyrsistent-0.19.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a178209e2df710e3f142cbd05313ba0c5ebed0a55d78d9945ac7a4e09d923308"}, - {file = "pyrsistent-0.19.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e371b844cec09d8dc424d940e54bba8f67a03ebea20ff7b7b0d56f526c71d584"}, - {file = "pyrsistent-0.19.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111156137b2e71f3a9936baf27cb322e8024dac3dc54ec7fb9f0bcf3249e68bb"}, - {file = "pyrsistent-0.19.2-cp38-cp38-win32.whl", hash = "sha256:e5d8f84d81e3729c3b506657dddfe46e8ba9c330bf1858ee33108f8bb2adb38a"}, - {file = "pyrsistent-0.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:9cd3e9978d12b5d99cbdc727a3022da0430ad007dacf33d0bf554b96427f33ab"}, - {file = "pyrsistent-0.19.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f1258f4e6c42ad0b20f9cfcc3ada5bd6b83374516cd01c0960e3cb75fdca6770"}, - {file = "pyrsistent-0.19.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21455e2b16000440e896ab99e8304617151981ed40c29e9507ef1c2e4314ee95"}, - {file = "pyrsistent-0.19.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd880614c6237243ff53a0539f1cb26987a6dc8ac6e66e0c5a40617296a045e"}, - {file = "pyrsistent-0.19.2-cp39-cp39-win32.whl", hash = "sha256:71d332b0320642b3261e9fee47ab9e65872c2bd90260e5d225dabeed93cbd42b"}, - {file = "pyrsistent-0.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:dec3eac7549869365fe263831f576c8457f6c833937c68542d08fde73457d291"}, - {file = "pyrsistent-0.19.2-py3-none-any.whl", hash = "sha256:ea6b79a02a28550c98b6ca9c35b9f492beaa54d7c5c9e9949555893c8a9234d0"}, - {file = "pyrsistent-0.19.2.tar.gz", hash = "sha256:bfa0351be89c9fcbcb8c9879b826f4353be10f58f8a677efab0c017bf7137ec2"}, + {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, + {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, + {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, + {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, + {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, + {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, ] [[package]] @@ -2239,19 +2383,19 @@ files = [ [[package]] name = "requests" -version = "2.28.1" +version = "2.28.2" description = "Python HTTP for Humans." category = "dev" optional = false python-versions = ">=3.7, <4" files = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, + {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, + {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, ] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" +charset-normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" @@ -2309,23 +2453,6 @@ files = [ attrs = "*" pbr = "*" -[[package]] -name = "setuptools" -version = "65.6.3" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"}, - {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "six" version = "1.16.0" @@ -2481,14 +2608,14 @@ files = [ [[package]] name = "urllib3" -version = "1.26.13" +version = "1.26.14" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, - {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, + {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"}, + {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"}, ] [package.extras] @@ -2513,37 +2640,40 @@ test = ["coverage", "flake8 (>=3.7)", "mypy", "pretend", "pytest"] [[package]] name = "watchdog" -version = "2.1.9" +version = "2.2.1" description = "Filesystem events monitoring" category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"}, - {file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d"}, - {file = "watchdog-2.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658"}, - {file = "watchdog-2.1.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591"}, - {file = "watchdog-2.1.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd"}, - {file = "watchdog-2.1.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3"}, - {file = "watchdog-2.1.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d"}, - {file = "watchdog-2.1.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_armv7l.whl", hash = "sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_i686.whl", hash = "sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64.whl", hash = "sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_s390x.whl", hash = "sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6"}, - {file = "watchdog-2.1.9-py3-none-win32.whl", hash = "sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1"}, - {file = "watchdog-2.1.9-py3-none-win_amd64.whl", hash = "sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c"}, - {file = "watchdog-2.1.9-py3-none-win_ia64.whl", hash = "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428"}, - {file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"}, + {file = "watchdog-2.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a09483249d25cbdb4c268e020cb861c51baab2d1affd9a6affc68ffe6a231260"}, + {file = "watchdog-2.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5100eae58133355d3ca6c1083a33b81355c4f452afa474c2633bd2fbbba398b3"}, + {file = "watchdog-2.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e618a4863726bc7a3c64f95c218437f3349fb9d909eb9ea3a1ed3b567417c661"}, + {file = "watchdog-2.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:102a60093090fc3ff76c983367b19849b7cc24ec414a43c0333680106e62aae1"}, + {file = "watchdog-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:748ca797ff59962e83cc8e4b233f87113f3cf247c23e6be58b8a2885c7337aa3"}, + {file = "watchdog-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ccd8d84b9490a82b51b230740468116b8205822ea5fdc700a553d92661253a3"}, + {file = "watchdog-2.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6e01d699cd260d59b84da6bda019dce0a3353e3fcc774408ae767fe88ee096b7"}, + {file = "watchdog-2.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8586d98c494690482c963ffb24c49bf9c8c2fe0589cec4dc2f753b78d1ec301d"}, + {file = "watchdog-2.2.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:adaf2ece15f3afa33a6b45f76b333a7da9256e1360003032524d61bdb4c422ae"}, + {file = "watchdog-2.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83a7cead445008e880dbde833cb9e5cc7b9a0958edb697a96b936621975f15b9"}, + {file = "watchdog-2.2.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8ac23ff2c2df4471a61af6490f847633024e5aa120567e08d07af5718c9d092"}, + {file = "watchdog-2.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d0f29fd9f3f149a5277929de33b4f121a04cf84bb494634707cfa8ea8ae106a8"}, + {file = "watchdog-2.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:967636031fa4c4955f0f3f22da3c5c418aa65d50908d31b73b3b3ffd66d60640"}, + {file = "watchdog-2.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96cbeb494e6cbe3ae6aacc430e678ce4b4dd3ae5125035f72b6eb4e5e9eb4f4e"}, + {file = "watchdog-2.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:61fdb8e9c57baf625e27e1420e7ca17f7d2023929cd0065eb79c83da1dfbeacd"}, + {file = "watchdog-2.2.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cb5ecc332112017fbdb19ede78d92e29a8165c46b68a0b8ccbd0a154f196d5e"}, + {file = "watchdog-2.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a480d122740debf0afac4ddd583c6c0bb519c24f817b42ed6f850e2f6f9d64a8"}, + {file = "watchdog-2.2.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:978a1aed55de0b807913b7482d09943b23a2d634040b112bdf31811a422f6344"}, + {file = "watchdog-2.2.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:8c28c23972ec9c524967895ccb1954bc6f6d4a557d36e681a36e84368660c4ce"}, + {file = "watchdog-2.2.1-py3-none-manylinux2014_i686.whl", hash = "sha256:c27d8c1535fd4474e40a4b5e01f4ba6720bac58e6751c667895cbc5c8a7af33c"}, + {file = "watchdog-2.2.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d6b87477752bd86ac5392ecb9eeed92b416898c30bd40c7e2dd03c3146105646"}, + {file = "watchdog-2.2.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:cece1aa596027ff56369f0b50a9de209920e1df9ac6d02c7f9e5d8162eb4f02b"}, + {file = "watchdog-2.2.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:8b5cde14e5c72b2df5d074774bdff69e9b55da77e102a91f36ef26ca35f9819c"}, + {file = "watchdog-2.2.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:e038be858425c4f621900b8ff1a3a1330d9edcfeaa1c0468aeb7e330fb87693e"}, + {file = "watchdog-2.2.1-py3-none-win32.whl", hash = "sha256:bc43c1b24d2f86b6e1cc15f68635a959388219426109233e606517ff7d0a5a73"}, + {file = "watchdog-2.2.1-py3-none-win_amd64.whl", hash = "sha256:17f1708f7410af92ddf591e94ae71a27a13974559e72f7e9fde3ec174b26ba2e"}, + {file = "watchdog-2.2.1-py3-none-win_ia64.whl", hash = "sha256:195ab1d9d611a4c1e5311cbf42273bc541e18ea8c32712f2fb703cfc6ff006f9"}, + {file = "watchdog-2.2.1.tar.gz", hash = "sha256:cdcc23c9528601a8a293eb4369cbd14f6b4f34f07ae8769421252e9c22718b6f"}, ] [package.extras] @@ -2642,18 +2772,18 @@ requests = ">=2.0,<3.0" [[package]] name = "zipp" -version = "3.11.0" +version = "3.12.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, - {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, + {file = "zipp-3.12.0-py3-none-any.whl", hash = "sha256:9eb0a4c5feab9b08871db0d672745b53450d7f26992fd1e4653aa43345e97b86"}, + {file = "zipp-3.12.0.tar.gz", hash = "sha256:73efd63936398aac78fd92b6f4865190119d6c91b531532e798977ea8dd402eb"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] [extras] @@ -2666,4 +2796,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "56cd214c7cf052567ee4dc5829d2801b57dc8b484e185ccccac149275695619e" +content-hash = "3a1013eb7ad5ff7a4a1bcf3be36eda55135bae69aae74cd91c1fde062805e154" diff --git a/pyproject.toml b/pyproject.toml index e9aed57ce76..04c5255c81e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,6 +80,7 @@ mypy-boto3-appconfigdata = "^1.26.0" importlib-metadata = "^6.0" ijson = "^3.2.0" typed-ast = { version = "^1.5.4", python = "< 3.8"} +hvac = "^1.0.2" [tool.poetry.extras] parser = ["pydantic"] From 83b8bd948b9622c03da22e6a1b31a614922f15b5 Mon Sep 17 00:00:00 2001 From: Release bot Date: Tue, 31 Jan 2023 13:40:29 +0000 Subject: [PATCH 23/30] update changelog with latest changes --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ba5029602d..55e9305bbac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,18 +9,28 @@ * parallel_run should fail when e2e tests fail * bump aws-cdk version * **ci:** scope e2e tests by python version +* **tests:** make logs fetching more robust ([#1878](https://github.com/awslabs/aws-lambda-powertools-python/issues/1878)) +* **tests:** remove custom workers +* **tests:** make sure multiple e2e tests run concurrently ([#1861](https://github.com/awslabs/aws-lambda-powertools-python/issues/1861)) ## Documentation * **event-source:** fix incorrect method in example CloudWatch Logs ([#1857](https://github.com/awslabs/aws-lambda-powertools-python/issues/1857)) +* **parameters:** snippets split, improved, and lint ([#1564](https://github.com/awslabs/aws-lambda-powertools-python/issues/1564)) ## Maintenance +* **deps:** bump docker/setup-buildx-action from 2.0.0 to 2.4.0 ([#1873](https://github.com/awslabs/aws-lambda-powertools-python/issues/1873)) * **deps:** bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 ([#1855](https://github.com/awslabs/aws-lambda-powertools-python/issues/1855)) +* **deps-dev:** bump flake8-bugbear from 22.12.6 to 23.1.20 ([#1854](https://github.com/awslabs/aws-lambda-powertools-python/issues/1854)) +* **deps-dev:** bump mkdocs-material from 9.0.6 to 9.0.8 ([#1874](https://github.com/awslabs/aws-lambda-powertools-python/issues/1874)) +* **deps-dev:** bump isort from 5.11.4 to 5.11.5 ([#1875](https://github.com/awslabs/aws-lambda-powertools-python/issues/1875)) +* **deps-dev:** bump mypy-boto3-s3 from 1.26.0.post1 to 1.26.58 ([#1868](https://github.com/awslabs/aws-lambda-powertools-python/issues/1868)) * **deps-dev:** bump aws-cdk-lib from 2.62.0 to 2.62.1 ([#1866](https://github.com/awslabs/aws-lambda-powertools-python/issues/1866)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.26.35.post1 to 1.26.57 ([#1865](https://github.com/awslabs/aws-lambda-powertools-python/issues/1865)) * **deps-dev:** bump coverage from 7.0.5 to 7.1.0 ([#1862](https://github.com/awslabs/aws-lambda-powertools-python/issues/1862)) * **deps-dev:** bump aws-cdk-lib from 2.61.1 to 2.62.0 ([#1863](https://github.com/awslabs/aws-lambda-powertools-python/issues/1863)) +* **deps-dev:** bump aws-cdk-lib from 2.62.1 to 2.62.2 ([#1869](https://github.com/awslabs/aws-lambda-powertools-python/issues/1869)) * **deps-dev:** bump mypy-boto3-lambda from 1.26.49 to 1.26.55 ([#1856](https://github.com/awslabs/aws-lambda-powertools-python/issues/1856)) From bc3d046485657e4ab46abe9367a4c34c607b8e96 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 1 Feb 2023 10:07:08 +0100 Subject: [PATCH 24/30] fix(license): add MIT-0 license header (#1871) --- LICENSE | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LICENSE b/LICENSE index 9e30e05ab6d..fcdede53dc8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,5 @@ +MIT No Attribution + Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of From 971f09515c2e60178b59bd817d394eb224d3041e Mon Sep 17 00:00:00 2001 From: Ruben Fonseca Date: Wed, 1 Feb 2023 13:33:50 +0100 Subject: [PATCH 25/30] fix(ci): add auth to API HTTP Gateway and Lambda Function Url (#1882) --- poetry.lock | 37 ++++++++++++++++++- pyproject.toml | 2 + tests/e2e/event_handler/infrastructure.py | 10 ++++- .../event_handler/test_header_serializer.py | 3 ++ .../test_paths_ending_with_slash.py | 5 +++ tests/e2e/utils/auth.py | 13 +++++++ 6 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/e2e/utils/auth.py diff --git a/poetry.lock b/poetry.lock index ee2d038ae92..379a24bb5e5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -89,6 +89,26 @@ jsii = ">=1.73.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" +[[package]] +name = "aws-cdk-aws-apigatewayv2-authorizers-alpha" +version = "2.62.2a0" +description = "Authorizers for AWS APIGateway V2" +category = "dev" +optional = false +python-versions = "~=3.7" +files = [ + {file = "aws-cdk.aws-apigatewayv2-authorizers-alpha-2.62.2a0.tar.gz", hash = "sha256:9a4ba121c49e4ba866b985495b87e9ecaec50c1f26e0d8cb116e15492196c042"}, + {file = "aws_cdk.aws_apigatewayv2_authorizers_alpha-2.62.2a0-py3-none-any.whl", hash = "sha256:9cfb1495b618880b395d6ecbd45c3c524c67013f2567eae6e19e6f06586b9a38"}, +] + +[package.dependencies] +"aws-cdk.aws-apigatewayv2-alpha" = "2.62.2.a0" +aws-cdk-lib = ">=2.62.2,<3.0.0" +constructs = ">=10.0.0,<11.0.0" +jsii = ">=1.73.0,<2.0.0" +publication = ">=0.0.3" +typeguard = ">=2.13.3,<2.14.0" + [[package]] name = "aws-cdk-aws-apigatewayv2-integrations-alpha" version = "2.62.2a0" @@ -130,6 +150,21 @@ jsii = ">=1.73.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" +[[package]] +name = "aws-requests-auth" +version = "0.4.3" +description = "AWS signature version 4 signing process for the python requests module" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "aws-requests-auth-0.4.3.tar.gz", hash = "sha256:33593372018b960a31dbbe236f89421678b885c35f0b6a7abfae35bb77e069b2"}, + {file = "aws_requests_auth-0.4.3-py2.py3-none-any.whl", hash = "sha256:646bc37d62140ea1c709d20148f5d43197e6bd2d63909eb36fa4bb2345759977"}, +] + +[package.dependencies] +requests = ">=0.14.0" + [[package]] name = "aws-sam-translator" version = "1.58.1" @@ -2796,4 +2831,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "3a1013eb7ad5ff7a4a1bcf3be36eda55135bae69aae74cd91c1fde062805e154" +content-hash = "b897ddb6a5d83dd5acce3c612c912af40b6c6c7821abc4804a93037e2f26639b" diff --git a/pyproject.toml b/pyproject.toml index 04c5255c81e..541ac06db4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ pytest-xdist = "^3.1.0" aws-cdk-lib = "^2.62.2" "aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" +"aws-cdk.aws-apigatewayv2-authorizers-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" python-snappy = "^0.6.1" mypy-boto3-appconfig = "^1.26.0" @@ -81,6 +82,7 @@ importlib-metadata = "^6.0" ijson = "^3.2.0" typed-ast = { version = "^1.5.4", python = "< 3.8"} hvac = "^1.0.2" +aws-requests-auth = "^0.4.3" [tool.poetry.extras] parser = ["pydantic"] diff --git a/tests/e2e/event_handler/infrastructure.py b/tests/e2e/event_handler/infrastructure.py index da456038a25..ca0d1ad8378 100644 --- a/tests/e2e/event_handler/infrastructure.py +++ b/tests/e2e/event_handler/infrastructure.py @@ -3,6 +3,7 @@ from aws_cdk import CfnOutput from aws_cdk import aws_apigateway as apigwv1 from aws_cdk import aws_apigatewayv2_alpha as apigwv2 +from aws_cdk import aws_apigatewayv2_authorizers_alpha as apigwv2authorizers from aws_cdk import aws_apigatewayv2_integrations_alpha as apigwv2integrations from aws_cdk import aws_ec2 as ec2 from aws_cdk import aws_elasticloadbalancingv2 as elbv2 @@ -57,7 +58,12 @@ def _create_alb_listener( CfnOutput(self.stack, f"ALB{name}ListenerPort", value=str(port)) def _create_api_gateway_http(self, function: Function): - apigw = apigwv2.HttpApi(self.stack, "APIGatewayHTTP", create_default_stage=True) + apigw = apigwv2.HttpApi( + self.stack, + "APIGatewayHTTP", + create_default_stage=True, + default_authorizer=apigwv2authorizers.HttpIamAuthorizer(), + ) apigw.add_routes( path="/todos", methods=[apigwv2.HttpMethod.POST], @@ -76,5 +82,5 @@ def _create_api_gateway_rest(self, function: Function): def _create_lambda_function_url(self, function: Function): # Maintenance: move auth to IAM when we create sigv4 builders - function_url = function.add_function_url(auth_type=FunctionUrlAuthType.NONE) + function_url = function.add_function_url(auth_type=FunctionUrlAuthType.AWS_IAM) CfnOutput(self.stack, "LambdaFunctionUrl", value=function_url.url) diff --git a/tests/e2e/event_handler/test_header_serializer.py b/tests/e2e/event_handler/test_header_serializer.py index 5026bf6aa4a..a1ce643d993 100644 --- a/tests/e2e/event_handler/test_header_serializer.py +++ b/tests/e2e/event_handler/test_header_serializer.py @@ -5,6 +5,7 @@ from aws_lambda_powertools.shared.cookies import Cookie from tests.e2e.utils import data_fetcher +from tests.e2e.utils.auth import build_iam_auth @pytest.fixture @@ -168,6 +169,7 @@ def test_api_gateway_http_headers_serializer(apigw_http_endpoint): method="POST", url=url, json={"body": body, "status_code": status_code, "headers": headers, "cookies": list(map(str, cookies))}, + auth=build_iam_auth(url=url, aws_service="execute-api"), ) ) @@ -204,6 +206,7 @@ def test_lambda_function_url_headers_serializer(lambda_function_url_endpoint): method="POST", url=url, json={"body": body, "status_code": status_code, "headers": headers, "cookies": list(map(str, cookies))}, + auth=build_iam_auth(url=url, aws_service="lambda"), ) ) diff --git a/tests/e2e/event_handler/test_paths_ending_with_slash.py b/tests/e2e/event_handler/test_paths_ending_with_slash.py index 1944768c2ff..d871edbb98e 100644 --- a/tests/e2e/event_handler/test_paths_ending_with_slash.py +++ b/tests/e2e/event_handler/test_paths_ending_with_slash.py @@ -2,6 +2,7 @@ from requests import HTTPError, Request from tests.e2e.utils import data_fetcher +from tests.e2e.utils.auth import build_iam_auth @pytest.fixture @@ -45,6 +46,7 @@ def test_api_gateway_rest_trailing_slash(apigw_rest_endpoint): method="POST", url=url, json={"body": body}, + auth=build_iam_auth(url=url, aws_service="lambda"), ) ) @@ -65,6 +67,7 @@ def test_api_gateway_http_trailing_slash(apigw_http_endpoint): method="POST", url=url, json={"body": body}, + auth=build_iam_auth(url=url, aws_service="lambda"), ) ) @@ -82,6 +85,7 @@ def test_lambda_function_url_trailing_slash(lambda_function_url_endpoint): method="POST", url=url, json={"body": body}, + auth=build_iam_auth(url=url, aws_service="lambda"), ) ) @@ -99,5 +103,6 @@ def test_alb_url_trailing_slash(alb_multi_value_header_listener_endpoint): method="POST", url=url, json={"body": body}, + auth=build_iam_auth(url=url, aws_service="lambda"), ) ) diff --git a/tests/e2e/utils/auth.py b/tests/e2e/utils/auth.py new file mode 100644 index 00000000000..8f50bfb9aef --- /dev/null +++ b/tests/e2e/utils/auth.py @@ -0,0 +1,13 @@ +from urllib.parse import urlparse + +import boto3 +from aws_requests_auth.boto_utils import BotoAWSRequestsAuth + + +def build_iam_auth(url: str, aws_service: str) -> BotoAWSRequestsAuth: + """Generates IAM auth keys for a given hostname and service. + This can be directly passed on to the requests library to authenticate the request. + """ + hostname = urlparse(url).hostname + region = boto3.Session().region_name + return BotoAWSRequestsAuth(aws_host=hostname, aws_region=region, aws_service=aws_service) From 26ea6e0e4a8111817920b14327b28e5a7384c5b8 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 1 Feb 2023 13:50:21 +0100 Subject: [PATCH 26/30] fix(license): correction to MIT + MIT-0 (no proprietary anymore) (#1883) --- pyproject.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 541ac06db4a..c7256d1c34c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", + "License :: OSI Approved :: MIT No Attribution License (MIT-0)", "Natural Language :: English", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", @@ -16,7 +16,9 @@ classifiers=[ repository="https://github.com/awslabs/aws-lambda-powertools-python" readme = "README.md" keywords = ["aws_lambda_powertools", "aws", "tracing", "logging", "lambda", "powertools", "feature_flags", "idempotency", "middleware"] -license = "MIT-0" +# MIT-0 is not recognized as an existing license from poetry. +# By using `MIT` as a license value, a `License :: OSI Approved :: MIT License` classifier is added to the classifiers list. +license = "MIT" [tool.poetry.dependencies] python = "^3.7.4" From b0b160252aa62b4c4e328f3a1530b46e5dc74825 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 1 Feb 2023 13:02:05 +0000 Subject: [PATCH 27/30] docs(homepage): add banner for end-of-support v1 (#1879) --- docs/overrides/main.html | 5 +++++ docs/upgrade.md | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 0af326afb24..10b02d3a905 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -1,5 +1,10 @@ {% extends "base.html" %} +{% block announce %} +👋 Powertools for Python v1 will no longer receive updates or releases after 31/03/2023! +We encourage you to read our upgrade guide on how to migrate to v2. +{% endblock %} + {% block outdated %} You're not viewing the latest version. diff --git a/docs/upgrade.md b/docs/upgrade.md index e16acded572..369daca1832 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -5,6 +5,12 @@ description: Guide to update between major Powertools versions +## End of support v1 + +On March 31st, AWS Lambda Powertools for Python v1 will reach end of support. After that, Powertools v1 will no longer receive updates or releases. If you are still using v1, we encourage you to read our upgrade guide and update to the latest version. + +Given our commitment to all of our customers using AWS Lambda Powertools for Python, we will keep [Pypi](https://pypi.org/project/aws-lambda-powertools/) v1 releases and documentation 1.x versions to prevent any disruption. + ## Migrate to v2 from v1 We've made minimal breaking changes to make your transition to v2 as smooth as possible. From 6b7b886bbc1761c03e55af7fdf22ee7d99df1ed5 Mon Sep 17 00:00:00 2001 From: Release bot Date: Wed, 1 Feb 2023 13:02:28 +0000 Subject: [PATCH 28/30] update changelog with latest changes --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55e9305bbac..bde94fa2806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ * parallel_run should fail when e2e tests fail * bump aws-cdk version * **ci:** scope e2e tests by python version +* **ci:** add auth to API HTTP Gateway and Lambda Function Url ([#1882](https://github.com/awslabs/aws-lambda-powertools-python/issues/1882)) +* **license:** correction to MIT + MIT-0 (no proprietary anymore) ([#1883](https://github.com/awslabs/aws-lambda-powertools-python/issues/1883)) +* **license:** add MIT-0 license header ([#1871](https://github.com/awslabs/aws-lambda-powertools-python/issues/1871)) * **tests:** make logs fetching more robust ([#1878](https://github.com/awslabs/aws-lambda-powertools-python/issues/1878)) * **tests:** remove custom workers * **tests:** make sure multiple e2e tests run concurrently ([#1861](https://github.com/awslabs/aws-lambda-powertools-python/issues/1861)) @@ -16,6 +19,7 @@ ## Documentation * **event-source:** fix incorrect method in example CloudWatch Logs ([#1857](https://github.com/awslabs/aws-lambda-powertools-python/issues/1857)) +* **homepage:** add banner for end-of-support v1 ([#1879](https://github.com/awslabs/aws-lambda-powertools-python/issues/1879)) * **parameters:** snippets split, improved, and lint ([#1564](https://github.com/awslabs/aws-lambda-powertools-python/issues/1564)) ## Maintenance From 366ac8e428fb699b054d68530665ec7d2a9bbaac Mon Sep 17 00:00:00 2001 From: Release bot Date: Wed, 1 Feb 2023 13:14:53 +0000 Subject: [PATCH 29/30] bump version to 2.7.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c7256d1c34c..da3333be635 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "2.7.0" +version = "2.7.1" description = "A suite of utilities for AWS Lambda functions to ease adopting best practices such as tracing, structured logging, custom metrics, batching, idempotency, feature flags, and more." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From 21c1b2b6a1cfb9ea400120605af8eb35b11ef376 Mon Sep 17 00:00:00 2001 From: Release bot Date: Wed, 1 Feb 2023 13:42:07 +0000 Subject: [PATCH 30/30] chore: update v2 layer ARN on documentation --- docs/index.md | 120 +++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/docs/index.md b/docs/index.md index 58e4322da00..36b6906ceb3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,8 +26,8 @@ A suite of utilities for AWS Lambda functions to ease adopting best practices su Powertools is available in the following formats: -* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:19**](#){: .copyMe}:clipboard: -* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19**](#){: .copyMe}:clipboard: +* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:20**](#){: .copyMe}:clipboard: +* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20**](#){: .copyMe}:clipboard: * **PyPi**: **`pip install "aws-lambda-powertools"`** ???+ info "Some utilities require additional dependencies" @@ -67,55 +67,55 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:19](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:20](#){: .copyMe}:clipboard: | === "arm64" | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20](#){: .copyMe}:clipboard: | ??? note "Note: Click to expand and copy code snippets for popular frameworks" @@ -128,7 +128,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. Type: AWS::Serverless::Function Properties: Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:19 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:20 ``` === "Serverless framework" @@ -138,7 +138,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. hello: handler: lambda_function.lambda_handler layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:19 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:20 ``` === "CDK" @@ -154,7 +154,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:19" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:20" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -203,7 +203,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:19"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:20"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } @@ -256,7 +256,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. ? 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:AWSLambdaPowertoolsPythonV2:19 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20 ❯ amplify push -y @@ -267,7 +267,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. - 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:AWSLambdaPowertoolsPythonV2:19 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:20 ? Do you want to edit the local lambda function now? No ``` @@ -276,7 +276,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. Change {region} to your AWS region, e.g. `eu-west-1` ```bash title="AWS CLI" - aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:19 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:20 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key. @@ -291,7 +291,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. Properties: Architectures: [arm64] Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20 ``` === "Serverless framework" @@ -302,7 +302,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20 ``` === "CDK" @@ -318,7 +318,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -368,7 +368,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") @@ -424,7 +424,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. ? 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:AWSLambdaPowertoolsPythonV2-Arm64:19 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20 ❯ amplify push -y @@ -435,7 +435,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. - 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:AWSLambdaPowertoolsPythonV2-Arm64:19 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20 ? Do you want to edit the local lambda function now? No ``` @@ -443,7 +443,7 @@ You can include Powertools Lambda Layer using [AWS Lambda Console](https://docs. Change {region} to your AWS region, e.g. `eu-west-1` ```bash title="AWS CLI" - aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:19 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:20 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key.