From fffe68d90a179c4fd2e8329c946685bbfb3e4d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Fonseca?= Date: Mon, 24 Oct 2022 10:17:45 +0200 Subject: [PATCH 01/38] chore(docs): remove v2 banner on top of the docs --- docs/overrides/main.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/overrides/main.html b/docs/overrides/main.html index e7908bbfa32..0af326afb24 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -1,10 +1,5 @@ {% extends "base.html" %} -{% block announce %} - 👋 Powertools for Python v2 is coming soon! - We encourage you to add your feedback and follow the progress on the RFC. -{% endblock %} - {% block outdated %} You're not viewing the latest version. From 5665843ec26bb091f7adb0763b2fbc0fd377ef9b Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 24 Oct 2022 08:18:37 +0000 Subject: [PATCH 02/38] update changelog with latest changes --- CHANGELOG.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ae140f037a..ca6cfc538e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ # Unreleased +## Maintenance + +* **docs:** remove v2 banner on top of the docs + + + +## [v2.0.0] - 2022-10-24 ## Bug Fixes * lock dependencies @@ -52,19 +59,20 @@ ## Maintenance -* bump pyproject version to 2.0 * update v2 layer ARN on documentation * update v2 layer ARN on documentation -* merge v2 branch * update v2 layer ARN on documentation +* update v2 layer ARN on documentation +* merge v2 branch +* bump pyproject version to 2.0 * **ci:** make release process manual * **ci:** migrate E2E tests to CDK CLI and off Docker ([#1501](https://github.com/awslabs/aws-lambda-powertools-python/issues/1501)) * **ci:** remove v1 workflows ([#1617](https://github.com/awslabs/aws-lambda-powertools-python/issues/1617)) * **core:** expose modules in the Top-level package ([#1517](https://github.com/awslabs/aws-lambda-powertools-python/issues/1517)) * **dep:** add cfn-lint as a dev dependency; pre-commit ([#1612](https://github.com/awslabs/aws-lambda-powertools-python/issues/1612)) +* **deps:** remove email-validator; use Str over EmailStr in SES model ([#1608](https://github.com/awslabs/aws-lambda-powertools-python/issues/1608)) * **deps:** bump release-drafter/release-drafter from 5.21.0 to 5.21.1 ([#1611](https://github.com/awslabs/aws-lambda-powertools-python/issues/1611)) * **deps:** lock importlib to 4.x -* **deps:** remove email-validator; use Str over EmailStr in SES model ([#1608](https://github.com/awslabs/aws-lambda-powertools-python/issues/1608)) * **deps-dev:** bump mypy-boto3-s3 from 1.24.76 to 1.24.94 ([#1622](https://github.com/awslabs/aws-lambda-powertools-python/issues/1622)) * **deps-dev:** bump aws-cdk-lib from 2.46.0 to 2.47.0 ([#1629](https://github.com/awslabs/aws-lambda-powertools-python/issues/1629)) * **layer:** bump to 1.31.1 (v39) @@ -2491,7 +2499,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/v1.31.1...HEAD +[Unreleased]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v2.0.0...HEAD +[v2.0.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.31.1...v2.0.0 [v1.31.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.31.0...v1.31.1 [v1.31.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.30.0...v1.31.0 [v1.30.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.29.2...v1.30.0 From b872aec15dcefbcffdcc79a8cd54ab3cf4eda9cc Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 24 Oct 2022 11:01:23 +0200 Subject: [PATCH 03/38] docs(index): add quotes to pip for zsh customers --- docs/index.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/index.md b/docs/index.md index f1ef5a54a7f..0cdd026b068 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,12 +16,12 @@ Powertools is available in the following formats: * **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11**](#){: .copyMe}:clipboard: * **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11**](#){: .copyMe}:clipboard: -* **PyPi**: **`pip install aws-lambda-powertools`** +* **PyPi**: **`pip install "aws-lambda-powertools"`** ???+ info "Some utilities require additional dependencies" You can stop reading if you're using Lambda Layer. - [Tracer](./core/tracer.md){target="_blank"}, [Validation](./utilities/validation.md){target="_blank"} and [Parser](./utilities/parser.md){target="_blank"} require additional dependencies. If you prefer to install all of them, use `pip install aws-lambda-powertools[all]`. + [Tracer](./core/tracer.md){target="_blank"}, [Validation](./utilities/validation.md){target="_blank"} and [Parser](./utilities/parser.md){target="_blank"} require additional dependencies. If you prefer to install all of them, use `pip install "aws-lambda-powertools[all]"`. ???+ hint "Support this project by using Lambda Layers :heart:" Lambda Layers allow us to understand who uses this library in a non-intrusive way. This helps us justify and gain future investments for other Lambda Powertools languages. @@ -34,8 +34,8 @@ Powertools relies on the AWS SDK bundled in the Lambda runtime. This helps us ac This means you need to add AWS SDK as a development dependency (not as a production dependency). -* **Pip**: `pip install aws-lambda-powertools[aws-sdk]` -* **Poetry**: `poetry add aws-lambda-powertools[aws-sdk] --dev` +* **Pip**: `pip install "aws-lambda-powertools[aws-sdk]"` +* **Poetry**: `poetry add "aws-lambda-powertools[aws-sdk]" --dev` * **Pipenv**: `pipenv install --dev "aws-lambda-powertools[aws-sdk]"` ???+ note "Local emulation" @@ -51,8 +51,8 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: === "x86_64" - | Region | Layer ARN | - | ---------------- | --------------------------------------------------------------------------------------------------------- | + | Region | Layer ARN | + | ---------------- | ---------------------------------------------------------------------------------------------------------- | | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | @@ -78,8 +78,8 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: === "arm64" - | Region | Layer ARN | - | ---------------- | --------------------------------------------------------------------------------------------------------------- | + | Region | Layer ARN | + | ---------------- | ---------------------------------------------------------------------------------------------------------------- | | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | From 192555fb246026d6316a395b56a3aaf54ef75f3f Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 24 Oct 2022 09:01:47 +0000 Subject: [PATCH 04/38] update changelog with latest changes --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca6cfc538e5..79b070517b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ # Unreleased +## Documentation + +* **index:** add quotes to pip for zsh customers + ## Maintenance * **docs:** remove v2 banner on top of the docs From 08f366c558c8512778807d9505775ad27097ca08 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 24 Oct 2022 11:02:32 +0200 Subject: [PATCH 05/38] chore(ci): fix typo on version description --- .github/workflows/rebuild_latest_docs.yml | 6 +++--- .github/workflows/reusable_publish_docs.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rebuild_latest_docs.yml b/.github/workflows/rebuild_latest_docs.yml index 1e8333d4540..aa3b2216289 100644 --- a/.github/workflows/rebuild_latest_docs.yml +++ b/.github/workflows/rebuild_latest_docs.yml @@ -4,14 +4,14 @@ name: Rebuild latest docs # === Documentation hotfix === # # 1. Trigger "Rebuild latest docs" workflow manually: https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow -# 2. Use the latest version released under Releases e.g. v1.22.0 +# 2. Use the latest version released under Releases e.g. 2.0.0 on: workflow_dispatch: inputs: latest_published_version: - description: "Latest PyPi published version to rebuild latest docs for, e.g. v2.0.0" - default: "v2.0.0" + description: "Latest PyPi published version to rebuild latest docs for, e.g. 2.0.0" + default: "2.0.0" required: true jobs: diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index a157783abf4..8e5590d5a5c 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -8,7 +8,7 @@ on: workflow_call: inputs: version: - description: "Version to build and publish docs (v1.28.0, develop)" + description: "Version to build and publish docs (1.28.0, develop)" required: true type: string alias: From bc2d2e523baab1113575b5c21d9c729495b08b76 Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 24 Oct 2022 09:07:30 +0000 Subject: [PATCH 06/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79b070517b6..b2c6acc2226 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ## Maintenance +* **ci:** fix typo on version description * **docs:** remove v2 banner on top of the docs From 19b6309f7fe3482b631b72a9cdad161bd3039447 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 24 Oct 2022 15:45:09 +0200 Subject: [PATCH 07/38] docs(install): address early v2 feedback on installation and project support --- docs/core/tracer.md | 6 +- docs/index.md | 743 ++++++++++++++++++----------------- docs/upgrade.md | 4 +- docs/utilities/parser.md | 10 +- docs/utilities/validation.md | 14 +- 5 files changed, 395 insertions(+), 382 deletions(-) diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 018af91797b..ac0b73c9e27 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -21,11 +21,9 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github. ### Install -!!! info "This is not necessary if you're installing Powertools via [Lambda Layer](../index.md#lambda-layer){target="_blank"}" +!!! info "This is not necessary if you're installing Powertools via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" -Add `aws-lambda-powertools[tracer]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. - -This will ensure you have the required dependencies before using Tracer. +Add `aws-lambda-powertools[tracer]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using Tracer. ### Permissions diff --git a/docs/index.md b/docs/index.md index 0cdd026b068..3b414f708b1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,13 +3,25 @@ title: Homepage description: AWS Lambda Powertools for Python --- - + -A suite of utilities for AWS Lambda functions to ease adopting best practices such as tracing, structured logging, custom metrics, idempotency, batching, and more. +A suite of utilities for AWS Lambda functions to ease adopting best practices such as tracing, structured logging, custom metrics, idempotency, batching, [**and more**](#features). -???+ note +???+ tip Powertools is also available for [Java](https://awslabs.github.io/aws-lambda-powertools-java/){target="_blank"}, [TypeScript](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/){target="_blank"}, and [.NET](https://awslabs.github.io/aws-lambda-powertools-dotnet/){target="_blank"} +???+ hint "Support this project by becoming a reference customer, sharing your work, or using Layers/SAR :heart:" + + You can choose to support us in three ways: + + 1) [**Become a reference customers**](https://github.com/awslabs/aws-lambda-powertools-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E). This gives us permission to list your company in our documentation. + + 2) [**Share your work**](https://github.com/awslabs/aws-lambda-powertools-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E). Blog posts, video, sample projects you used Powertools! + + 3) Use [**Lambda Layers**](#lambda-layer) or [**SAR**](#sar), if possible. This helps us understand who uses Powertools in a non-intrusive way, and helps us gain future investments for other Lambda Powertools languages. + + When using Layers, you can add Lambda Powertools as a dev dependency (or as part of your virtual env) to not impact the development process. + ## Install Powertools is available in the following formats: @@ -23,10 +35,12 @@ Powertools is available in the following formats: [Tracer](./core/tracer.md){target="_blank"}, [Validation](./utilities/validation.md){target="_blank"} and [Parser](./utilities/parser.md){target="_blank"} require additional dependencies. If you prefer to install all of them, use `pip install "aws-lambda-powertools[all]"`. -???+ hint "Support this project by using Lambda Layers :heart:" - Lambda Layers allow us to understand who uses this library in a non-intrusive way. This helps us justify and gain future investments for other Lambda Powertools languages. + For example: - When using Layers, you can add Lambda Powertools as a dev dependency (or as part of your virtual env) to not impact the development process. + * [Tracer](./core/tracer.md#install){target="_blank"}: **`pip install "aws-lambda-powertools[tracer]"`** + * [Validation](./utilities/validation.md#install){target="_blank"}: **`pip install "aws-lambda-powertools[validation]"`** + * [Parser](./utilities/parser.md#install){target="_blank"}: **`pip install "aws-lambda-powertools[parser]"`** + * [Tracer](./core/tracer.md#install){target="_blank"} and [Parser](./utilities/parser.md#install){target="_blank"}: **`pip install "aws-lambda-powertools[tracer,parser]"`** ### Local development @@ -47,7 +61,7 @@ This means you need to add AWS SDK as a development dependency (not as a product You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html#invocation-layers-using){target="_blank"}, or your preferred deployment framework. -??? note "Note: Expand to copy any regional Lambda Layer ARN" +??? note "Note: Click to expand and copy any regional Lambda Layer ARN" === "x86_64" @@ -103,409 +117,410 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | -=== "x86_64" +??? note "Note: Click to expand and copy code snippets for popular frameworks" - === "SAM" + === "x86_64" - ```yaml hl_lines="5" - MyLambdaFunction: - Type: AWS::Serverless::Function - Properties: - Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 - ``` + === "SAM" + + ```yaml hl_lines="5" + MyLambdaFunction: + Type: AWS::Serverless::Function + Properties: + Layers: + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 + ``` + + === "Serverless framework" + + ```yaml hl_lines="5" + functions: + hello: + handler: lambda_function.lambda_handler + layers: + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 + ``` + + === "CDK" + + ```python hl_lines="11 16" + from aws_cdk import core, aws_lambda + + class SampleApp(core.Construct): + + def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> None: + super().__init__(scope, id_) + + 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:11" + ) + aws_lambda.Function(self, + 'sample-app-lambda', + runtime=aws_lambda.Runtime.PYTHON_3_9, + layers=[powertools_layer] + # other props... + ) + ``` + + === "Terraform" + + ```terraform hl_lines="9 38" + terraform { + required_version = "~> 1.0.5" + required_providers { + aws = "~> 3.50.0" + } + } - === "Serverless framework" + provider "aws" { + region = "{region}" + } - ```yaml hl_lines="5" - functions: - hello: - handler: lambda_function.lambda_handler - layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 - ``` + resource "aws_iam_role" "iam_for_lambda" { + name = "iam_for_lambda" - === "CDK" + assume_role_policy = < + ? Choose the runtime that you want to use: Python + ? 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:11 + ❯ amplify push -y - def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> None: - super().__init__(scope, id_) - 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:11" - ) - aws_lambda.Function(self, - 'sample-app-lambda', - runtime=aws_lambda.Runtime.PYTHON_3_9, - layers=[powertools_layer] - # other props... - ) - ``` + # Updating an existing function and add the layer + ❯ amplify update function + ? Select the Lambda function you want to update test2 + General information + - Name: + ? Which setting do you want to update? Lambda layers configuration + ? Do you want to enable Lambda layers for this function? Yes + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 + ? Do you want to edit the local lambda function now? No + ``` - === "Terraform" + === "Get the Layer .zip contents" - ```terraform hl_lines="9 38" - terraform { - required_version = "~> 1.0.5" - required_providers { - aws = "~> 3.50.0" - } - } + Change {region} to your AWS region, e.g. `eu-west-1` - provider "aws" { - region = "{region}" - } + ```bash title="AWS CLI" + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 --region {region} + ``` - resource "aws_iam_role" "iam_for_lambda" { - name = "iam_for_lambda" + The pre-signed URL to download this Lambda Layer will be within `Location` key. + + === "arm64" + + === "SAM" + + ```yaml hl_lines="6" + MyLambdaFunction: + Type: AWS::Serverless::Function + Properties: + Architectures: [arm64] + Layers: + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 + ``` + + === "Serverless framework" + + ```yaml hl_lines="6" + functions: + hello: + handler: lambda_function.lambda_handler + architecture: arm64 + layers: + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 + ``` + + === "CDK" + + ```python hl_lines="11 17" + from aws_cdk import core, aws_lambda + + class SampleApp(core.Construct): + + def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> None: + super().__init__(scope, id_) + + 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:11" + ) + aws_lambda.Function(self, + 'sample-app-lambda', + runtime=aws_lambda.Runtime.PYTHON_3_9, + architecture=aws_lambda.Architecture.ARM_64, + layers=[powertools_layer] + # other props... + ) + ``` + + === "Terraform" + + ```terraform hl_lines="9 37" + terraform { + required_version = "~> 1.0.5" + required_providers { + aws = "~> 3.50.0" + } + } - assume_role_policy = < - ? Choose the runtime that you want to use: Python - ? 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:11 - ❯ amplify push -y - - - # Updating an existing function and add the layer - ❯ amplify update function - ? Select the Lambda function you want to update test2 - General information - - Name: - ? Which setting do you want to update? Lambda layers configuration - ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 - ? Do you want to edit the local lambda function now? No - ``` - === "Get the Layer .zip contents" + ``` - Change {region} to your AWS region, e.g. `eu-west-1` + === "Amplify" + + ```zsh + # Create a new one with the layer + ❯ amplify add function + ? Select which capability you want to add: Lambda function (serverless function) + ? Provide an AWS Lambda function name: + ? Choose the runtime that you want to use: Python + ? 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:11 + ❯ amplify push -y - ```bash title="AWS CLI" - aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 --region {region} - ``` - The pre-signed URL to download this Lambda Layer will be within `Location` key. + # Updating an existing function and add the layer + ❯ amplify update function + ? Select the Lambda function you want to update test2 + General information + - Name: + ? Which setting do you want to update? Lambda layers configuration + ? Do you want to enable Lambda layers for this function? Yes + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 + ? Do you want to edit the local lambda function now? No + ``` -=== "arm64" + === "Get the Layer .zip contents" + 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:11 --region {region} + ``` + + The pre-signed URL to download this Lambda Layer will be within `Location` key. + +???+ warning "Warning: Limitations" + + Container Image deployment (OCI) or inline Lambda functions do not support Lambda Layers. + + Lambda Powertools Lambda Layer do not include `pydantic` library - required dependency for the `parser` utility. See [SAR](#sar) option instead. + +#### SAR + +Serverless Application Repository (SAR) App deploys a CloudFormation stack with a copy of our Lambda Layer in your AWS account and region. + +Compared with the [public Layer ARN](#lambda-layer) option, SAR allows you to choose a semantic version and deploys a Layer in your target account. + +| App | ARN | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | +| [aws-lambda-powertools-python-layer](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer) | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). | +| [aws-lambda-powertools-python-layer-arm64](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer-arm64) | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer-arm64](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). For arm64 functions. | + +??? note "Click to expand and copy SAR code snippets for popular frameworks" + + You can create a shared Lambda Layers stack and make this along with other account level layers stack. === "SAM" - ```yaml hl_lines="6" + ```yaml hl_lines="5-6 12-13" + AwsLambdaPowertoolsPythonLayer: + Type: AWS::Serverless::Application + Properties: + Location: + ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer + SemanticVersion: 2.0.0 # change to latest semantic version available in SAR + MyLambdaFunction: Type: AWS::Serverless::Function Properties: - Architectures: [arm64] Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 + # fetch Layer ARN from SAR App stack output + - !GetAtt AwsLambdaPowertoolsPythonLayer.Outputs.LayerVersionArn ``` === "Serverless framework" - ```yaml hl_lines="6" - functions: - hello: - handler: lambda_function.lambda_handler - architecture: arm64 - layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 + ```yaml hl_lines="5 8 10-11" + functions: + main: + handler: lambda_function.lambda_handler + layers: + - !GetAtt AwsLambdaPowertoolsPythonLayer.Outputs.LayerVersionArn + + resources: + Transform: AWS::Serverless-2016-10-31 + Resources:**** + AwsLambdaPowertoolsPythonLayer: + Type: AWS::Serverless::Application + Properties: + Location: + ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer + # Find latest from github.com/awslabs/aws-lambda-powertools-python/releases + SemanticVersion: 2.0.0 ``` === "CDK" - ```python hl_lines="11 17" - from aws_cdk import core, aws_lambda + ```python hl_lines="14 22-23 31" + from aws_cdk import core, aws_sam as sam, aws_lambda + + POWERTOOLS_BASE_NAME = 'AWSLambdaPowertools' + # Find latest from github.com/awslabs/aws-lambda-powertools-python/releases + POWERTOOLS_VER = '2.0.0' + POWERTOOLS_ARN = 'arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer' class SampleApp(core.Construct): - def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> None: + def __init__(self, scope: core.Construct, id_: str) -> None: super().__init__(scope, id_) - 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:11" + # Launches SAR App as CloudFormation nested stack and return Lambda Layer + powertools_app = sam.CfnApplication(self, + f'{POWERTOOLS_BASE_NAME}Application', + location={ + 'applicationId': POWERTOOLS_ARN, + 'semanticVersion': POWERTOOLS_VER + }, ) + + powertools_layer_arn = powertools_app.get_att("Outputs.LayerVersionArn").to_string() + powertools_layer_version = aws_lambda.LayerVersion.from_layer_version_arn(self, f'{POWERTOOLS_BASE_NAME}', powertools_layer_arn) + aws_lambda.Function(self, 'sample-app-lambda', - runtime=aws_lambda.Runtime.PYTHON_3_9, - architecture=aws_lambda.Architecture.ARM_64, - layers=[powertools_layer] - # other props... + runtime=aws_lambda.Runtime.PYTHON_3_8, + function_name='sample-lambda', + code=aws_lambda.Code.asset('./src'), + handler='app.handler', + layers: [powertools_layer_version] ) ``` === "Terraform" - ```terraform hl_lines="9 37" + > Credits to [Dani Comnea](https://github.com/DanyC97) for providing the Terraform equivalent. + + ```terraform hl_lines="12-13 15-20 23-25 40" terraform { - required_version = "~> 1.0.5" + required_version = "~> 0.13" required_providers { aws = "~> 3.50.0" } } provider "aws" { - region = "{region}" + region = "us-east-1" } - resource "aws_iam_role" "iam_for_lambda" { - name = "iam_for_lambda" + resource "aws_serverlessapplicationrepository_cloudformation_stack" "deploy_sar_stack" { + name = "aws-lambda-powertools-python-layer" - assume_role_policy = < - ? Choose the runtime that you want to use: Python - ? 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:11 - ❯ amplify push -y - - - # Updating an existing function and add the layer - ❯ amplify update function - ? Select the Lambda function you want to update test2 - General information - - Name: - ? Which setting do you want to update? Lambda layers configuration - ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 - ? Do you want to edit the local lambda function now? No - ``` + variable "aws_powertools_version" { + type = string + default = "2.0.0" + description = "The AWS Powertools release version" + } - === "Get the Layer .zip contents" - Change {region} to your AWS region, e.g. `eu-west-1` + output "deployed_powertools_sar_version" { + value = data.aws_serverlessapplicationrepository_application.sar_app.semantic_version + } - ```bash title="AWS CLI" - aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 --region {region} + # Fetch Lambda Powertools Layer ARN from deployed SAR App + output "aws_lambda_powertools_layer_arn" { + value = aws_serverlessapplicationrepository_cloudformation_stack.deploy_sar_stack.outputs.LayerVersionArn + } ``` - The pre-signed URL to download this Lambda Layer will be within `Location` key. - -???+ warning "Warning: Limitations" - - Container Image deployment (OCI) or inline Lambda functions do not support Lambda Layers. - - Lambda Powertools Lambda Layer do not include `pydantic` library - required dependency for the `parser` utility. See [SAR](#sar) option instead. - -#### SAR - -Serverless Application Repository (SAR) App deploys a CloudFormation stack with a copy of our Lambda Layer in your AWS account and region. - -Despite having more steps compared to the [public Layer ARN](#lambda-layer) option, the benefit is that you can specify a semantic version you want to use. - -| App | ARN | Description | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | -| [aws-lambda-powertools-python-layer](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer) | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). | -| [aws-lambda-powertools-python-layer-arm64](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer-arm64) | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer-arm64](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). For arm64 functions. | - -???+ tip - You can create a shared Lambda Layers stack and make this along with other account level layers stack. - -If using SAM, you can include this SAR App as part of your shared Layers stack, and lock to a specific semantic version. Once deployed, it'll be available across the account this is deployed to. - -=== "SAM" - - ```yaml hl_lines="5-6 12-13" - AwsLambdaPowertoolsPythonLayer: - Type: AWS::Serverless::Application - Properties: - Location: - ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer - SemanticVersion: 2.0.0 # change to latest semantic version available in SAR - - MyLambdaFunction: - Type: AWS::Serverless::Function - Properties: - Layers: - # fetch Layer ARN from SAR App stack output - - !GetAtt AwsLambdaPowertoolsPythonLayer.Outputs.LayerVersionArn - ``` - -=== "Serverless framework" - - ```yaml hl_lines="5 8 10-11" - functions: - main: - handler: lambda_function.lambda_handler - layers: - - !GetAtt AwsLambdaPowertoolsPythonLayer.Outputs.LayerVersionArn - - resources: - Transform: AWS::Serverless-2016-10-31 - Resources:**** - AwsLambdaPowertoolsPythonLayer: - Type: AWS::Serverless::Application - Properties: - Location: - ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer - # Find latest from github.com/awslabs/aws-lambda-powertools-python/releases - SemanticVersion: 2.0.0 - ``` - -=== "CDK" - - ```python hl_lines="14 22-23 31" - from aws_cdk import core, aws_sam as sam, aws_lambda - - POWERTOOLS_BASE_NAME = 'AWSLambdaPowertools' - # Find latest from github.com/awslabs/aws-lambda-powertools-python/releases - POWERTOOLS_VER = '2.0.0' - POWERTOOLS_ARN = 'arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer' - - class SampleApp(core.Construct): - - def __init__(self, scope: core.Construct, id_: str) -> None: - super().__init__(scope, id_) - - # Launches SAR App as CloudFormation nested stack and return Lambda Layer - powertools_app = sam.CfnApplication(self, - f'{POWERTOOLS_BASE_NAME}Application', - location={ - 'applicationId': POWERTOOLS_ARN, - 'semanticVersion': POWERTOOLS_VER - }, - ) - - powertools_layer_arn = powertools_app.get_att("Outputs.LayerVersionArn").to_string() - powertools_layer_version = aws_lambda.LayerVersion.from_layer_version_arn(self, f'{POWERTOOLS_BASE_NAME}', powertools_layer_arn) - - aws_lambda.Function(self, - 'sample-app-lambda', - runtime=aws_lambda.Runtime.PYTHON_3_8, - function_name='sample-lambda', - code=aws_lambda.Code.asset('./src'), - handler='app.handler', - layers: [powertools_layer_version] - ) - ``` - -=== "Terraform" - - > Credits to [Dani Comnea](https://github.com/DanyC97) for providing the Terraform equivalent. - - ```terraform hl_lines="12-13 15-20 23-25 40" - terraform { - required_version = "~> 0.13" - required_providers { - aws = "~> 3.50.0" - } - } - - provider "aws" { - region = "us-east-1" - } - - resource "aws_serverlessapplicationrepository_cloudformation_stack" "deploy_sar_stack" { - name = "aws-lambda-powertools-python-layer" - - application_id = data.aws_serverlessapplicationrepository_application.sar_app.application_id - semantic_version = data.aws_serverlessapplicationrepository_application.sar_app.semantic_version - capabilities = [ - "CAPABILITY_IAM", - "CAPABILITY_NAMED_IAM" - ] - } - - data "aws_serverlessapplicationrepository_application" "sar_app" { - application_id = "arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer" - semantic_version = var.aws_powertools_version - } - - variable "aws_powertools_version" { - type = string - default = "2.0.0" - description = "The AWS Powertools release version" - } - - output "deployed_powertools_sar_version" { - value = data.aws_serverlessapplicationrepository_application.sar_app.semantic_version - } - - # Fetch Lambda Powertools Layer ARN from deployed SAR App - output "aws_lambda_powertools_layer_arn" { - value = aws_serverlessapplicationrepository_cloudformation_stack.deploy_sar_stack.outputs.LayerVersionArn - } - ``` - ??? example "Example: Least-privileged IAM permissions to deploy Layer" > Credits to [mwarkentin](https://github.com/mwarkentin) for providing the scoped down IAM permissions. @@ -571,12 +586,14 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, - Ref: "PowertoolsLayerIamRole" ``` -You can fetch available versions via SAR ListApplicationVersions API: +??? note "Click to expand and copy an AWS CLI command to list all versions available in SAR" -```bash title="AWS CLI example" -aws serverlessrepo list-application-versions \ - --application-id arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer -``` + You can fetch available versions via SAR ListApplicationVersions API: + + ```bash title="AWS CLI example" + aws serverlessrepo list-application-versions \ + --application-id arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer + ``` ## Quick getting started @@ -588,22 +605,22 @@ sam init --location https://github.com/aws-samples/cookiecutter-aws-sam-python Core utilities such as Tracing, Logging, Metrics, and Event Handler will be available across all Lambda Powertools languages. Additional utilities are subjective to each language ecosystem and customer demand. -| Utility | Description | -| -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Tracing](./core/tracer.md) | Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions | -| [Logger](./core/logger.md) | Structured logging made easier, and decorator to enrich structured logging with key Lambda context details | -| [Metrics](./core/metrics.md) | Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF) | -| [Event handler: AppSync](./core/event_handler/appsync.md) | AppSync event handler for Lambda Direct Resolver and Amplify GraphQL Transformer function | -| [Event handler: API Gateway, ALB and Lambda Function URL](https://awslabs.github.io/aws-lambda-powertools-python/latest/core/event_handler/api_gateway/) | Amazon API Gateway REST/HTTP API and ALB event handler for Lambda functions invoked using Proxy integration, and Lambda Function URL | -| [Middleware factory](./utilities/middleware_factory.md) | Decorator factory to create your own middleware to run logic before, and after each Lambda invocation | -| [Parameters](./utilities/parameters.md) | Retrieve parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, or Amazon DynamoDB, and cache them for a specific amount of time | -| [Batch processing](./utilities/batch.md) | Handle partial failures for AWS SQS batch processing | -| [Typing](./utilities/typing.md) | Static typing classes to speedup development in your IDE | -| [Validation](./utilities/validation.md) | JSON Schema validator for inbound events and responses | -| [Event source data classes](./utilities/data_classes.md) | Data classes describing the schema of common Lambda event triggers | -| [Parser](./utilities/parser.md) | Data parsing and deep validation using Pydantic | -| [Idempotency](./utilities/idempotency.md) | Idempotent Lambda handler | -| [Feature Flags](./utilities/feature_flags.md) | A simple rule engine to evaluate when one or multiple features should be enabled depending on the input | +| Utility | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [**Tracing**](./core/tracer.md) | Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions | +| [**Logger**](./core/logger.md) | Structured logging made easier, and decorator to enrich structured logging with key Lambda context details | +| [**Metrics**](./core/metrics.md) | Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF) | +| [**Event handler: AppSync**](./core/event_handler/appsync.md) | AppSync event handler for Lambda Direct Resolver and Amplify GraphQL Transformer function | +| [**Event handler: API Gateway, ALB and Lambda Function URL**](https://awslabs.github.io/aws-lambda-powertools-python/latest/core/event_handler/api_gateway/) | Amazon API Gateway REST/HTTP API and ALB event handler for Lambda functions invoked using Proxy integration, and Lambda Function URL | +| [**Middleware factory**](./utilities/middleware_factory.md) | Decorator factory to create your own middleware to run logic before, and after each Lambda invocation | +| [**Parameters**](./utilities/parameters.md) | Retrieve parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, or Amazon DynamoDB, and cache them for a specific amount of time | +| [**Batch processing**](./utilities/batch.md) | Handle partial failures for AWS SQS batch processing | +| [**Typing**](./utilities/typing.md) | Static typing classes to speedup development in your IDE | +| [**Validation**](./utilities/validation.md) | JSON Schema validator for inbound events and responses | +| [**Event source data classes**](./utilities/data_classes.md) | Data classes describing the schema of common Lambda event triggers | +| [**Parser**](./utilities/parser.md) | Data parsing and deep validation using Pydantic | +| [**Idempotency**](./utilities/idempotency.md) | Idempotent Lambda handler | +| [**Feature Flags**](./utilities/feature_flags.md) | A simple rule engine to evaluate when one or multiple features should be enabled depending on the input | ## Environment variables diff --git a/docs/upgrade.md b/docs/upgrade.md index 391bc084d7f..e16acded572 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -22,10 +22,12 @@ We've made minimal breaking changes to make your transition to v2 as smooth as p ### First Steps +!!! note "All dependencies are optional now. [Tracer](core/tracer.md#install){target="_blank"}, [Validation](./utilities/validation.md#install){target="_blank"}, and [Parser](./utilities/parser.md){target="_blank"} now require additional dependencies." + Before you start, we suggest making a copy of your current working project or create a new branch with git. 1. **Upgrade** Python to at least v3.7 -2. **Ensure** you have the latest version via [Lambda Layer or PyPi](index.md#install){target="_blank"} +2. **Ensure** you have the latest version via [Lambda Layer or PyPi](index.md#install){target="_blank"}. 3. **Review** the following sections to confirm whether they affect your code ## Legacy SQS Batch Processor diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index fd157482c2c..4afa362f879 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -16,11 +16,9 @@ This utility provides data parsing and deep validation using [Pydantic](https:// ### Install -!!! info "This is not necessary if you're installing Powertools via [Lambda Layer](../index.md#lambda-layer){target="_blank"}" +!!! info "This is not necessary if you're installing Powertools via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" -Add `aws-lambda-powertools[parser]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. - -This will ensure you have the required dependencies before using Parser. +Add `aws-lambda-powertools[parser]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using Parser. ???+ warning This will increase the compressed package size by >10MB due to the Pydantic dependency. @@ -168,7 +166,7 @@ Parser comes with the following built-in models: | **S3Model** | Lambda Event Source payload for Amazon S3 | | **S3ObjectLambdaEvent** | Lambda Event Source payload for Amazon S3 Object Lambda | | **KinesisDataStreamModel** | Lambda Event Source payload for Amazon Kinesis Data Streams | -| **KinesisFirehoseModel** | Lambda Event Source payload for Amazon Kinesis Firehose | +| **KinesisFirehoseModel** | Lambda Event Source payload for Amazon Kinesis Firehose | | **SesModel** | Lambda Event Source payload for Amazon Simple Email Service | | **SnsModel** | Lambda Event Source payload for Amazon Simple Notification Service | | **APIGatewayProxyEventModel** | Lambda Event Source payload for Amazon API Gateway | @@ -325,7 +323,7 @@ Parser comes with the following built-in envelopes, where `Model` in the return | **SqsEnvelope** | 1. Parses data using `SqsModel`.
2. Parses records in `body` key using your model and return them in a list. | `List[Model]` | | **CloudWatchLogsEnvelope** | 1. Parses data using `CloudwatchLogsModel` which will base64 decode and decompress it.
2. Parses records in `message` key using your model and return them in a list. | `List[Model]` | | **KinesisDataStreamEnvelope** | 1. Parses data using `KinesisDataStreamModel` which will base64 decode it.
2. Parses records in in `Records` key using your model and returns them in a list. | `List[Model]` | -| **KinesisFirehoseEnvelope** | 1. Parses data using `KinesisFirehoseModel` which will base64 decode it.
2. Parses records in in `Records` key using your model and returns them in a list. | `List[Model]` | +| **KinesisFirehoseEnvelope** | 1. Parses data using `KinesisFirehoseModel` which will base64 decode it.
2. Parses records in in `Records` key using your model and returns them in a list. | `List[Model]` | | **SnsEnvelope** | 1. Parses data using `SnsModel`.
2. Parses records in `body` key using your model and return them in a list. | `List[Model]` | | **SnsSqsEnvelope** | 1. Parses data using `SqsModel`.
2. Parses SNS records in `body` key using `SnsNotificationModel`.
3. Parses data in `Message` key using your model and return them in a list. | `List[Model]` | | **ApiGatewayEnvelope** | 1. Parses data using `APIGatewayProxyEventModel`.
2. Parses `body` key using your model and returns it. | `Model` | diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index 43086c3d2d5..dcd35b9ab7a 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -18,14 +18,6 @@ This utility provides JSON Schema validation for events and responses, including ???+ 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"}. -### Install - -!!! info "This is not necessary if you're installing Powertools via [Lambda Layer](../index.md#lambda-layer){target="_blank"}" - -Add `aws-lambda-powertools[validation]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. - -This will ensure you have the required dependencies before using Validation. - You can validate inbound and outbound events using [`validator` decorator](#validator-decorator). You can also use the standalone `validate` function, if you want more control over the validation process such as handling a validation error. @@ -38,6 +30,12 @@ You can also use the standalone `validate` function, if you want more control ov ???+ warning Both `validator` decorator and `validate` standalone function expects your JSON Schema to be a **dictionary**, not a filename. +### Install + +!!! info "This is not necessary if you're installing Powertools via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" + +Add `aws-lambda-powertools[validation]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using Validation. + ### Validator decorator **Validator** decorator is typically used to validate either inbound or functions' response. From fc89a07ab0eb868dc04d438f8efb1d56d6a125db Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 24 Oct 2022 13:45:37 +0000 Subject: [PATCH 08/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2c6acc2226..9288b7b1c38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ## Documentation * **index:** add quotes to pip for zsh customers +* **install:** address early v2 feedback on installation and project support ## Maintenance From 77bc8ca223acb2ecf1ecf59af1b83b58b04bc759 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 24 Oct 2022 15:55:49 +0200 Subject: [PATCH 09/38] docs(index): fold support us banner --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 3b414f708b1..8da0f26f870 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ A suite of utilities for AWS Lambda functions to ease adopting best practices su ???+ tip Powertools is also available for [Java](https://awslabs.github.io/aws-lambda-powertools-java/){target="_blank"}, [TypeScript](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/){target="_blank"}, and [.NET](https://awslabs.github.io/aws-lambda-powertools-dotnet/){target="_blank"} -???+ hint "Support this project by becoming a reference customer, sharing your work, or using Layers/SAR :heart:" +??? hint "Support this project by becoming a reference customer, sharing your work, or using Layers/SAR :heart:" You can choose to support us in three ways: From 83e216a443caa6b3ca8c522319776961b907d7ab Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 24 Oct 2022 13:56:15 +0000 Subject: [PATCH 10/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9288b7b1c38..4d0b0503e0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ## Documentation +* **index:** fold support us banner * **index:** add quotes to pip for zsh customers * **install:** address early v2 feedback on installation and project support From 557a700af9342b4caceebeb18affbb09144732ff Mon Sep 17 00:00:00 2001 From: Ruben Fonseca Date: Mon, 24 Oct 2022 16:16:20 +0200 Subject: [PATCH 11/38] feat(layers): add layer balancer script (#1643) Co-authored-by: Leandro Damascena --- layer/scripts/layer-balancer/README.md | 37 ++++ layer/scripts/layer-balancer/go.mod | 24 ++ layer/scripts/layer-balancer/go.sum | 37 ++++ layer/scripts/layer-balancer/main.go | 292 +++++++++++++++++++++++++ 4 files changed, 390 insertions(+) create mode 100644 layer/scripts/layer-balancer/README.md create mode 100644 layer/scripts/layer-balancer/go.mod create mode 100644 layer/scripts/layer-balancer/go.sum create mode 100644 layer/scripts/layer-balancer/main.go diff --git a/layer/scripts/layer-balancer/README.md b/layer/scripts/layer-balancer/README.md new file mode 100644 index 00000000000..001f2833d7e --- /dev/null +++ b/layer/scripts/layer-balancer/README.md @@ -0,0 +1,37 @@ + +# Layer balancer + +This folder contains a Go project that balances the layer version of Lambda Powertools across all regions, so +every region has the same layer version. + +Before: + +```text +arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 +... +arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:9 +``` + +After: + +```text +arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 +... +arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 +``` + +## What's happening under the hood? + +1. Query all regions to find the greatest version number +2. Download the latest layer from eu-central-1 +3. Use the layer contents to bump the version on each region until it matches 1 + +## Requirements + +* go >= 1.18 + +## How to use + +1. Set your AWS_PROFILE to the correct profile +2. `go run .` +3. Profit :-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod new file mode 100644 index 00000000000..219d4d46736 --- /dev/null +++ b/layer/scripts/layer-balancer/go.mod @@ -0,0 +1,24 @@ +module layerbalancer + +go 1.18 + +require ( + github.com/aws/aws-sdk-go-v2 v1.16.16 + github.com/aws/aws-sdk-go-v2/config v1.17.8 + github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6 + golang.org/x/sync v0.1.0 +) + +require ( + github.com/aws/aws-sdk-go-v2/credentials v1.12.21 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect + github.com/aws/smithy-go v1.13.3 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect +) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum new file mode 100644 index 00000000000..9bcb7428e79 --- /dev/null +++ b/layer/scripts/layer-balancer/go.sum @@ -0,0 +1,37 @@ +github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= +github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= +github.com/aws/aws-sdk-go-v2/config v1.17.8 h1:b9LGqNnOdg9vR4Q43tBTVWk4J6F+W774MSchvKJsqnE= +github.com/aws/aws-sdk-go-v2/config v1.17.8/go.mod h1:UkCI3kb0sCdvtjiXYiU4Zx5h07BOpgBTtkPu/49r+kA= +github.com/aws/aws-sdk-go-v2/credentials v1.12.21 h1:4tjlyCD0hRGNQivh5dN8hbP30qQhMLBE/FgQR1vHHWM= +github.com/aws/aws-sdk-go-v2/credentials v1.12.21/go.mod h1:O+4XyAt4e+oBAoIwNUYkRg3CVMscaIJdmZBOcPgJ8D8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= +github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6 h1:N7RkXX2SJbN+TCp295J3LdMR0KRFd2Bhi5nIO+svLQY= +github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6/go.mod h1:oTJIIluTaJCRT6xP1AZpuU3JwRHBC0Q5O4Hg+SUxFHw= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 h1:OwhhKc1P9ElfWbMKPIbMMZBV6hzJlL2JKD76wNNVzgQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= +github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= +github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/layer/scripts/layer-balancer/main.go b/layer/scripts/layer-balancer/main.go new file mode 100644 index 00000000000..889675e5f71 --- /dev/null +++ b/layer/scripts/layer-balancer/main.go @@ -0,0 +1,292 @@ +package main + +import ( + "context" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "os/signal" + "sort" + "sync" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" + "golang.org/x/sync/errgroup" +) + +type LayerInfo struct { + Name string + Description string + Architecture types.Architecture + + LayerContentOnce sync.Once + LayerContent []byte +} + +// canonicalLayers are the layers that we want to keep in sync across all regions +var canonicalLayers = []LayerInfo{ + { + Name: "AWSLambdaPowertoolsPythonV2", + Description: "Lambda Powertools for Python [x86_64] with extra dependencies version bump", + Architecture: types.ArchitectureX8664, + }, + { + Name: "AWSLambdaPowertoolsPythonV2-Arm64", + Description: "Lambda Powertools for Python [arm64] with extra dependencies version bump", + Architecture: types.ArchitectureArm64, + }, +} + +// regions are the regions that we want to keep in sync +var regions = []string{ + "af-south-1", + "eu-central-1", + "us-east-1", + "us-east-2", + "us-west-1", + "us-west-2", + "ap-east-1", + "ap-south-1", + "ap-northeast-1", + "ap-northeast-2", + "ap-southeast-1", + "ap-southeast-2", + "ca-central-1", + "eu-west-1", + "eu-west-2", + "eu-west-3", + "eu-south-1", + "eu-north-1", + "sa-east-1", + "ap-southeast-3", + "ap-northeast-3", + "me-south-1", +} + +// getLayerVersion returns the latest version of a layer in a region +func getLayerVersion(ctx context.Context, layerName string, region string) (int64, error) { + cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) + if err != nil { + return 0, err + } + + lambdaSvc := lambda.NewFromConfig(cfg) + + layerVersionsResult, err := lambdaSvc.ListLayerVersions(ctx, &lambda.ListLayerVersionsInput{ + LayerName: aws.String(layerName), + MaxItems: aws.Int32(1), + }) + if err != nil { + return 0, err + } + + if len(layerVersionsResult.LayerVersions) == 0 { + return 0, fmt.Errorf("no layer meets the search criteria %s - %s", layerName, region) + } + return layerVersionsResult.LayerVersions[0].Version, nil +} + +// getGreatestVersion returns the greatest version of a layer across all regions +func getGreatestVersion(ctx context.Context) (int64, error) { + var versions []int64 + + g, ctx := errgroup.WithContext(ctx) + + for idx := range canonicalLayers { + layer := &canonicalLayers[idx] + + for _, region := range regions { + layerName := layer.Name + ctx := ctx + region := region + + g.Go(func() error { + version, err := getLayerVersion(ctx, layerName, region) + if err != nil { + return err + } + + log.Printf("[%s] %s -> %d", layerName, region, version) + + versions = append(versions, version) + return nil + }) + } + } + + if err := g.Wait(); err != nil { + return 0, err + } + + // Find the maximum version by reverse sorting the versions array + sort.Slice(versions, func(i, j int) bool { return versions[i] > versions[j] }) + return versions[0], nil +} + +// balanceRegionToVersion creates a new layer version in a region with the same contents as the canonical layer, until it matches the maxVersion +func balanceRegionToVersion(ctx context.Context, region string, layer *LayerInfo, maxVersion int64) error { + currentLayerVersion, err := getLayerVersion(ctx, layer.Name, region) + if err != nil { + return fmt.Errorf("error getting layer version: %w", err) + } + + cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) + if err != nil { + return err + } + + lambdaSvc := lambda.NewFromConfig(cfg) + + for i := currentLayerVersion; i < maxVersion; i++ { + log.Printf("[%s] Bumping %s to version %d (max %d)", layer.Name, region, i, maxVersion) + + payload, err := downloadCanonicalLayerZip(ctx, layer) + if err != nil { + return fmt.Errorf("error downloading canonical zip: %w", err) + } + + layerVersionResponse, err := lambdaSvc.PublishLayerVersion(ctx, &lambda.PublishLayerVersionInput{ + Content: &types.LayerVersionContentInput{ + ZipFile: payload, + }, + LayerName: aws.String(layer.Name), + CompatibleArchitectures: []types.Architecture{layer.Architecture}, + CompatibleRuntimes: []types.Runtime{types.RuntimePython37, types.RuntimePython38, types.RuntimePython39}, + Description: aws.String(layer.Description), + LicenseInfo: aws.String("MIT-0"), + }) + if err != nil { + return fmt.Errorf("error publishing layer version: %w", err) + } + + _, err = lambdaSvc.AddLayerVersionPermission(ctx, &lambda.AddLayerVersionPermissionInput{ + Action: aws.String("lambda:GetLayerVersion"), + LayerName: aws.String(layer.Name), + Principal: aws.String("*"), + StatementId: aws.String("PublicLayerAccess"), + VersionNumber: layerVersionResponse.Version, + }) + if err != nil { + return fmt.Errorf("error making layer public: %w", err) + } + } + + return nil +} + +// balanceRegions creates new layer versions in all regions with the same contents as the canonical layer, until they match the maxVersion +func balanceRegions(ctx context.Context, maxVersion int64) error { + g, ctx := errgroup.WithContext(ctx) + + for idx := range canonicalLayers { + layer := &canonicalLayers[idx] + + for _, region := range regions { + ctx := ctx + region := region + layer := layer + version := maxVersion + + g.Go(func() error { + return balanceRegionToVersion(ctx, region, layer, version) + }) + } + } + + if err := g.Wait(); err != nil { + return err + } + + return nil +} + +// downloadCanonicalLayerZip downloads the canonical layer zip file that will be used to bump the versions later +func downloadCanonicalLayerZip(ctx context.Context, layer *LayerInfo) ([]byte, error) { + var innerErr error + + layer.LayerContentOnce.Do(func() { + // We use eu-central-1 as the canonical region to download the Layer from + cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("eu-central-1")) + if err != nil { + innerErr = err + } + + lambdaSvc := lambda.NewFromConfig(cfg) + + // Gets the latest version of the layer + version, err := getLayerVersion(ctx, layer.Name, "eu-central-1") + if err != nil { + innerErr = fmt.Errorf("error getting eu-central-1 layer version: %w", err) + } + + // Gets the Layer content URL from S3 + getLayerVersionResult, err := lambdaSvc.GetLayerVersion(ctx, &lambda.GetLayerVersionInput{ + LayerName: aws.String(layer.Name), + VersionNumber: version, + }) + if err != nil { + innerErr = fmt.Errorf("error getting eu-central-1 layer download URL: %w", err) + } + + s3LayerUrl := getLayerVersionResult.Content.Location + log.Printf("[%s] Downloading Layer from %s", layer.Name, *s3LayerUrl) + + resp, err := http.Get(*s3LayerUrl) + if err != nil { + innerErr = err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + innerErr = err + } + + layer.LayerContent = body + }) + + return layer.LayerContent, innerErr +} + +func main() { + ctx := context.Background() + + // Cancel everything if interrupted + ctx, cancel := context.WithCancel(ctx) + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + defer func() { + signal.Stop(c) + cancel() + }() + go func() { + select { + case <-c: + cancel() + case <-ctx.Done(): + } + }() + + // Find the greatest layer version across all regions + greatestVersion, err := getGreatestVersion(ctx) + if err != nil { + cancel() + log.Printf("error getting layer version: %s", err) + os.Exit(1) + } + log.Printf("Greatest version is %d. Bumping all versions...", greatestVersion) + + // Elevate all regions to the greatest layer version found + err = balanceRegions(ctx, greatestVersion) + if err != nil { + cancel() + log.Printf("error balancing regions: %s", err) + os.Exit(1) + } + + log.Printf("DONE! All layers should be version %d", greatestVersion) +} From 3aa154cff913edeebd2ecc39c64cbb5250dc4abe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:44:27 +0200 Subject: [PATCH 12/38] chore(deps): bump peaceiris/actions-gh-pages from 3.8.0 to 3.9.0 (#1649) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ruben Fonseca --- .github/workflows/reusable_publish_docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 8e5590d5a5c..6023961a510 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -65,7 +65,7 @@ jobs: poetry run mike set-default --push latest # Maintenance: Migrate to new gh-pages action - name: Release API docs - uses: peaceiris/actions-gh-pages@068dc23d9710f1ba62e86896f84735d869951305 # v3.8.0 + uses: peaceiris/actions-gh-pages@de7ea6f8efb354206b205ef54722213d99067935 # v3.9.0 env: VERSION: ${{ inputs.version }} with: @@ -75,7 +75,7 @@ jobs: destination_dir: ${{ env.VERSION }}/api - name: Release API docs to latest if: ${{ inputs.alias == 'latest' }} - uses: peaceiris/actions-gh-pages@068dc23d9710f1ba62e86896f84735d869951305 # v3.8.0 + uses: peaceiris/actions-gh-pages@de7ea6f8efb354206b205ef54722213d99067935 # v3.9.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./api From 8c0b94c697a989c5c1cefb36dfdd83c02dc3aa15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Oct 2022 11:15:35 +0000 Subject: [PATCH 13/38] chore(deps-dev): bump pytest-asyncio from 0.16.0 to 0.20.1 (#1635) --- poetry.lock | 17 +++++++++-------- pyproject.toml | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7898b732100..fd416f5e3e3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1159,17 +1159,18 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. [[package]] name = "pytest-asyncio" -version = "0.16.0" -description = "Pytest support for asyncio." +version = "0.20.1" +description = "Pytest support for asyncio" category = "dev" optional = false -python-versions = ">= 3.6" +python-versions = ">=3.7" [package.dependencies] -pytest = ">=5.4.0" +pytest = ">=6.1.0" +typing-extensions = {version = ">=3.7.2", markers = "python_version < \"3.8\""} [package.extras] -testing = ["coverage", "hypothesis (>=5.7.1)"] +testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] [[package]] name = "pytest-benchmark" @@ -1528,7 +1529,7 @@ validation = ["fastjsonschema"] [metadata] lock-version = "1.1" python-versions = "^3.7.4" -content-hash = "6f3c081f72eee753bb06a79c43338312fb965c9afbe470675c6d87c27c2cda23" +content-hash = "78d574666c1b004d5469cbdd22acba5c1da5577dac11dae703bdef4f4e6e419a" [metadata.files] attrs = [ @@ -2083,8 +2084,8 @@ pytest = [ {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, ] pytest-asyncio = [ - {file = "pytest-asyncio-0.16.0.tar.gz", hash = "sha256:7496c5977ce88c34379df64a66459fe395cd05543f0a2f837016e7144391fcfb"}, - {file = "pytest_asyncio-0.16.0-py3-none-any.whl", hash = "sha256:5f2a21273c47b331ae6aa5b36087047b4899e40f03f18397c0e65fa5cca54e9b"}, + {file = "pytest-asyncio-0.20.1.tar.gz", hash = "sha256:626699de2a747611f3eeb64168b3575f70439b06c3d0206e6ceaeeb956e65519"}, + {file = "pytest_asyncio-0.20.1-py3-none-any.whl", hash = "sha256:2c85a835df33fda40fe3973b451e0c194ca11bc2c007eabff90bb3d156fc172b"}, ] pytest-benchmark = [ {file = "pytest-benchmark-3.4.1.tar.gz", hash = "sha256:40e263f912de5a81d891619032983557d62a3d85843f9a9f30b98baea0cd7b47"}, diff --git a/pyproject.toml b/pyproject.toml index 3dc94b5c67e..4c1071485bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ isort = "^5.10.1" pytest-cov = "^4.0.0" pytest-mock = "^3.5.1" pdoc3 = "^0.10.0" -pytest-asyncio = "^0.16.0" +pytest-asyncio = "^0.20.1" bandit = "^1.7.1" radon = "^5.1.0" xenon = "^0.9.0" From ac82f61e9b1c69b7678d5c57e902545c5b4bbe67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Oct 2022 11:16:17 +0000 Subject: [PATCH 14/38] chore(deps): bump docker/setup-qemu-action from 2.0.0 to 2.1.0 (#1627) --- .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 653dc4178b2..6d91d908ac0 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -59,7 +59,7 @@ jobs: poetry export --format requirements.txt --output requirements.txt pip install -r requirements.txt - name: Set up QEMU - uses: docker/setup-qemu-action@8b122486cedac8393e77aa9734c3528886e4a1a8 # v2.0.0 + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.0.0 with: platforms: arm64 # NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM) From 8fadc40db30c2884d00be2df4624424cd4871b59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Oct 2022 12:19:51 +0000 Subject: [PATCH 15/38] chore(deps-dev): bump flake8-variables-names from 0.0.4 to 0.0.5 (#1628) --- poetry.lock | 12 +++++------- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index fd416f5e3e3..f3e79d281ce 100644 --- a/poetry.lock +++ b/poetry.lock @@ -443,14 +443,11 @@ test = ["pytest-cov"] [[package]] name = "flake8-variables-names" -version = "0.0.4" +version = "0.0.5" description = "A flake8 extension that helps to make more readable variables names" category = "dev" optional = false -python-versions = "*" - -[package.dependencies] -setuptools = "*" +python-versions = ">=3.7" [[package]] name = "future" @@ -1529,7 +1526,7 @@ validation = ["fastjsonschema"] [metadata] lock-version = "1.1" python-versions = "^3.7.4" -content-hash = "78d574666c1b004d5469cbdd22acba5c1da5577dac11dae703bdef4f4e6e419a" +content-hash = "026b049a610e7643a180c269a4d323b203e9f5737efbeea23f78ca7594010a5d" [metadata.files] attrs = [ @@ -1737,7 +1734,8 @@ flake8-isort = [ {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, ] flake8-variables-names = [ - {file = "flake8_variables_names-0.0.4.tar.gz", hash = "sha256:d6fa0571a807c72940b5773827c5760421ea6f8206595ff0a8ecfa01e42bf2cf"}, + {file = "flake8_variables_names-0.0.5-py3-none-any.whl", hash = "sha256:e3277031696bbe10b5132b49938cde1d70fcae9561533b7bd7ab8e69cb27addb"}, + {file = "flake8_variables_names-0.0.5.tar.gz", hash = "sha256:30133e14ee2300e13a60393a00f74d98110c76070ac67d1ab91606f02824a7e1"}, ] future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, diff --git a/pyproject.toml b/pyproject.toml index 4c1071485bd..becdd1d263c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ flake8-comprehensions = "^3.7.0" flake8-debugger = "^4.0.0" flake8-fixme = "^1.1.1" flake8-isort = "^4.1.2" -flake8-variables-names = "^0.0.4" +flake8-variables-names = "^0.0.5" flake8-black = "^0.3.3" isort = "^5.10.1" pytest-cov = "^4.0.0" From 1e5db6d31d631cef01e4ad841724454aa4693bd5 Mon Sep 17 00:00:00 2001 From: Ruben Fonseca Date: Tue, 25 Oct 2022 15:46:04 +0200 Subject: [PATCH 16/38] fix(deps): update build system to poetry-core (#1651) --- poetry.lock | 182 ++++++++++++++++++++++++------------------------- pyproject.toml | 4 +- 2 files changed, 93 insertions(+), 93 deletions(-) diff --git a/poetry.lock b/poetry.lock index f3e79d281ce..4195693dcc9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,14 +14,14 @@ tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy [[package]] name = "aws-cdk-aws-apigatewayv2-alpha" -version = "2.46.0a0" +version = "2.47.0a0" description = "The CDK Construct Library for AWS::APIGatewayv2" category = "dev" optional = false python-versions = "~=3.7" [package.dependencies] -aws-cdk-lib = ">=2.46.0,<3.0.0" +aws-cdk-lib = ">=2.47.0,<3.0.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.69.0,<2.0.0" publication = ">=0.0.3" @@ -29,15 +29,15 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-integrations-alpha" -version = "2.46.0a0" +version = "2.47.0a0" description = "Integrations for AWS APIGateway V2" category = "dev" optional = false python-versions = "~=3.7" [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.46.0.a0" -aws-cdk-lib = ">=2.46.0,<3.0.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.47.0.a0" +aws-cdk-lib = ">=2.47.0,<3.0.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.69.0,<2.0.0" publication = ">=0.0.3" @@ -128,14 +128,14 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.24.94" +version = "1.25.0" description = "The AWS SDK for Python" category = "main" optional = false python-versions = ">= 3.7" [package.dependencies] -botocore = ">=1.27.94,<1.28.0" +botocore = ">=1.28.0,<1.29.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.6.0,<0.7.0" @@ -144,7 +144,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.27.94" +version = "1.28.0" description = "Low-level, data-driven core of boto 3." category = "main" optional = false @@ -230,15 +230,15 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "constructs" -version = "10.1.134" +version = "10.1.139" description = "A programming model for software-defined state" category = "dev" optional = false @@ -353,18 +353,18 @@ tomli = "*" [[package]] name = "flake8-bugbear" -version = "22.9.23" +version = "22.10.25" 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.6" +python-versions = ">=3.7" [package.dependencies] attrs = ">=19.2.0" flake8 = ">=3.0.0" [package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"] [[package]] name = "flake8-builtins" @@ -785,7 +785,7 @@ mkdocs = ">=0.17" [[package]] name = "mkdocs-material" -version = "8.5.6" +version = "8.5.7" description = "Documentation that simply works" category = "dev" optional = false @@ -802,11 +802,11 @@ requests = ">=2.26" [[package]] name = "mkdocs-material-extensions" -version = "1.0.3" -description = "Extension pack for Python Markdown." +version = "1.1" +description = "Extension pack for Python Markdown and MkDocs Material." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "mypy" @@ -829,8 +829,8 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-appconfig" -version = "1.24.36.post1" -description = "Type annotations for boto3.AppConfig 1.24.36 service generated with mypy-boto3-builder 7.10.0" +version = "1.25.0" +description = "Type annotations for boto3.AppConfig 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -840,8 +840,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-appconfigdata" -version = "1.24.36.post1" -description = "Type annotations for boto3.AppConfigData 1.24.36 service generated with mypy-boto3-builder 7.10.0" +version = "1.25.0" +description = "Type annotations for boto3.AppConfigData 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -851,8 +851,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-cloudformation" -version = "1.24.36.post1" -description = "Type annotations for boto3.CloudFormation 1.24.36 service generated with mypy-boto3-builder 7.10.0" +version = "1.25.0" +description = "Type annotations for boto3.CloudFormation 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -862,8 +862,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-cloudwatch" -version = "1.24.55" -description = "Type annotations for boto3.CloudWatch 1.24.55 service generated with mypy-boto3-builder 7.11.6" +version = "1.25.0" +description = "Type annotations for boto3.CloudWatch 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -873,8 +873,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-dynamodb" -version = "1.24.74" -description = "Type annotations for boto3.DynamoDB 1.24.74 service generated with mypy-boto3-builder 7.11.8" +version = "1.25.0" +description = "Type annotations for boto3.DynamoDB 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -884,8 +884,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-lambda" -version = "1.24.54" -description = "Type annotations for boto3.Lambda 1.24.54 service generated with mypy-boto3-builder 7.11.6" +version = "1.25.0" +description = "Type annotations for boto3.Lambda 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -895,8 +895,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-logs" -version = "1.24.36.post1" -description = "Type annotations for boto3.CloudWatchLogs 1.24.36 service generated with mypy-boto3-builder 7.10.0" +version = "1.25.0" +description = "Type annotations for boto3.CloudWatchLogs 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -906,8 +906,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-s3" -version = "1.24.94" -description = "Type annotations for boto3.S3 1.24.94 service generated with mypy-boto3-builder 7.11.10" +version = "1.25.0" +description = "Type annotations for boto3.S3 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -917,8 +917,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-secretsmanager" -version = "1.24.83" -description = "Type annotations for boto3.SecretsManager 1.24.83 service generated with mypy-boto3-builder 7.11.10" +version = "1.25.0" +description = "Type annotations for boto3.SecretsManager 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -928,8 +928,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-ssm" -version = "1.24.90" -description = "Type annotations for boto3.SSM 1.24.90 service generated with mypy-boto3-builder 7.11.10" +version = "1.25.0" +description = "Type annotations for boto3.SSM 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -939,8 +939,8 @@ typing-extensions = ">=4.1.0" [[package]] name = "mypy-boto3-xray" -version = "1.24.36.post1" -description = "Type annotations for boto3.XRay 1.24.36 service generated with mypy-boto3-builder 7.10.0" +version = "1.25.0" +description = "Type annotations for boto3.XRay 1.25.0 service generated with mypy-boto3-builder 7.11.10" category = "dev" optional = false python-versions = ">=3.7" @@ -1105,7 +1105,7 @@ plugins = ["importlib-metadata"] [[package]] name = "pymdown-extensions" -version = "9.6" +version = "9.7" description = "Extension pack for Python Markdown." category = "dev" optional = false @@ -1135,7 +1135,7 @@ python-versions = ">=3.7" [[package]] name = "pytest" -version = "7.1.3" +version = "7.2.0" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -1144,12 +1144,12 @@ python-versions = ">=3.7" [package.dependencies] attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] @@ -1506,7 +1506,7 @@ requests = ">=2.0,<3.0" [[package]] name = "zipp" -version = "3.9.0" +version = "3.10.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false @@ -1534,12 +1534,12 @@ attrs = [ {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] aws-cdk-aws-apigatewayv2-alpha = [ - {file = "aws-cdk.aws-apigatewayv2-alpha-2.46.0a0.tar.gz", hash = "sha256:10d9324da26db7aeee3a45853a2e249b6b85866fcc8f8f43fa1a0544ce582482"}, - {file = "aws_cdk.aws_apigatewayv2_alpha-2.46.0a0-py3-none-any.whl", hash = "sha256:2cdeac84fb1fe219e5686ee95d9528a1810e9d426b2bb7f305ea07cb43e328a8"}, + {file = "aws-cdk.aws-apigatewayv2-alpha-2.47.0a0.tar.gz", hash = "sha256:b1e32e046bd5ae224c8a962850215ac98e9639c453337fafeffb7a5618d66063"}, + {file = "aws_cdk.aws_apigatewayv2_alpha-2.47.0a0-py3-none-any.whl", hash = "sha256:f2d41b944d7781b9565135e832a416c54e2c1e52f31fefdc7b8b323142814033"}, ] aws-cdk-aws-apigatewayv2-integrations-alpha = [ - {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.46.0a0.tar.gz", hash = "sha256:91a792c94500987b69fd97cb00afec5ace00f2039ffebebd99f91ee6b47c3c8b"}, - {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.46.0a0-py3-none-any.whl", hash = "sha256:c7bbe1c08019cee41c14b6c1513f673d60b337422ef338c67f9a0cb3e17cc963"}, + {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.47.0a0.tar.gz", hash = "sha256:c86f0291c8cac2b8db0391bf52f626e541a82a3c7cbb4a03cd8d5014882862cc"}, + {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.47.0a0-py3-none-any.whl", hash = "sha256:4633c4e020400c7ee5790652f099f02d4f84bab24fff013250e2b41a4ffca1b0"}, ] aws-cdk-lib = [ {file = "aws-cdk-lib-2.47.0.tar.gz", hash = "sha256:c9b1626c7afc42ceaee547558efe88439dd1447b18c7837db153e03fb8186167"}, @@ -1582,12 +1582,12 @@ black = [ {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, ] boto3 = [ - {file = "boto3-1.24.94-py3-none-any.whl", hash = "sha256:f13db0beb3c9fe2cc1ed0f031189f144610d2909b5874a616e77b0bd1ae3b686"}, - {file = "boto3-1.24.94.tar.gz", hash = "sha256:f4842b395d1580454756622069f4ca0408993885ecede967001d2c101201cdfa"}, + {file = "boto3-1.25.0-py3-none-any.whl", hash = "sha256:81139cc9da154a1672c7dd92da1678cae0ea1601a3e1f0394c6cd010eab1acb6"}, + {file = "boto3-1.25.0.tar.gz", hash = "sha256:170eab4a87592741933b6f8a02c3a6a8664162ef33bb12a2c2b4d431490d9ac2"}, ] botocore = [ - {file = "botocore-1.27.94-py3-none-any.whl", hash = "sha256:8237c070d2ab29fac4fbcfe9dd2e84e0ee147402e0fed3ac1629f92459c7f1d2"}, - {file = "botocore-1.27.94.tar.gz", hash = "sha256:572224608a0b7662966fc303b768e2eba61bf53bdbf314481cd9e63a0d8e1a66"}, + {file = "botocore-1.28.0-py3-none-any.whl", hash = "sha256:5bc426647da9f7739b73b1ffb5fce37fb3691c3c66dd772bf541dc19f8da2f43"}, + {file = "botocore-1.28.0.tar.gz", hash = "sha256:75a4082543e2c1b005ccde90af87d0969003db06c3fcbe8a7854ddaa8d68fafb"}, ] cattrs = [ {file = "cattrs-22.2.0-py3-none-any.whl", hash = "sha256:bc12b1f0d000b9f9bee83335887d532a1d3e99a833d1bf0882151c97d3e68c21"}, @@ -1614,12 +1614,12 @@ click = [ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] constructs = [ - {file = "constructs-10.1.134-py3-none-any.whl", hash = "sha256:b3f05ad138af83473cc9bd5f8949558bd31d38fb32c09fcc56d0de9057c2e61d"}, - {file = "constructs-10.1.134.tar.gz", hash = "sha256:4ab253a74e62a2c918456d20dff42ec0abb2e4393a6bab0218c81c09e19c1a41"}, + {file = "constructs-10.1.139-py3-none-any.whl", hash = "sha256:e809549fc4f1cad8ee57eb5a8a31d163f6321374c024a91e04bbb1f5520d53c7"}, + {file = "constructs-10.1.139.tar.gz", hash = "sha256:df319296e2efe699662323dc2b1dcb154439457aaaa036b8c7409975bfc5b43a"}, ] coverage = [ {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, @@ -1706,8 +1706,8 @@ flake8-black = [ {file = "flake8_black-0.3.3-py3-none-any.whl", hash = "sha256:7d667d0059fd1aa468de1669d77cc934b7f1feeac258d57bdae69a8e73c4cd90"}, ] flake8-bugbear = [ - {file = "flake8-bugbear-22.9.23.tar.gz", hash = "sha256:17b9623325e6e0dcdcc80ed9e4aa811287fcc81d7e03313b8736ea5733759937"}, - {file = "flake8_bugbear-22.9.23-py3-none-any.whl", hash = "sha256:cd2779b2b7ada212d7a322814a1e5651f1868ab0d3f24cc9da66169ab8fda474"}, + {file = "flake8-bugbear-22.10.25.tar.gz", hash = "sha256:89e51284eb929fbb7f23fbd428491e7427f7cdc8b45a77248daffe86a039d696"}, + {file = "flake8_bugbear-22.10.25-py3-none-any.whl", hash = "sha256:584631b608dc0d7d3f9201046d5840a45502da4732d5e8df6c7ac1694a91cb9e"}, ] flake8-builtins = [ {file = "flake8-builtins-2.0.0.tar.gz", hash = "sha256:98833fa16139a75cd4913003492a9bd9a61c6f8ac146c3db12a2ebaf420dade3"}, @@ -1877,12 +1877,12 @@ mkdocs-git-revision-date-plugin = [ {file = "mkdocs_git_revision_date_plugin-0.3.2-py3-none-any.whl", hash = "sha256:2e67956cb01823dd2418e2833f3623dee8604cdf223bddd005fe36226a56f6ef"}, ] mkdocs-material = [ - {file = "mkdocs_material-8.5.6-py3-none-any.whl", hash = "sha256:b473162c800321b9760453f301a91f7cb40a120a85a9d0464e1e484e74b76bb2"}, - {file = "mkdocs_material-8.5.6.tar.gz", hash = "sha256:38a21d817265d0c203ab3dad64996e45859c983f72180f6937bd5540a4eb84e4"}, + {file = "mkdocs_material-8.5.7-py3-none-any.whl", hash = "sha256:07fc70dfa325a8019b99a124751c43e4c1c2a739ed1b0b82c00f823f31c9a1e2"}, + {file = "mkdocs_material-8.5.7.tar.gz", hash = "sha256:ff4c7851b2e5f9a6cfa0a8b247e973ebae753b9836a53bd68742827541ab73e5"}, ] mkdocs-material-extensions = [ - {file = "mkdocs-material-extensions-1.0.3.tar.gz", hash = "sha256:bfd24dfdef7b41c312ede42648f9eb83476ea168ec163b613f9abd12bbfddba2"}, - {file = "mkdocs_material_extensions-1.0.3-py3-none-any.whl", hash = "sha256:a82b70e533ce060b2a5d9eb2bc2e1be201cf61f901f93704b4acf6e3d5983a44"}, + {file = "mkdocs_material_extensions-1.1-py3-none-any.whl", hash = "sha256:bcc2e5fc70c0ec50e59703ee6e639d87c7e664c0c441c014ea84461a90f1e902"}, + {file = "mkdocs_material_extensions-1.1.tar.gz", hash = "sha256:96ca979dae66d65c2099eefe189b49d5ac62f76afb59c38e069ffc7cf3c131ec"}, ] mypy = [ {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, @@ -1910,48 +1910,48 @@ mypy = [ {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, ] mypy-boto3-appconfig = [ - {file = "mypy-boto3-appconfig-1.24.36.post1.tar.gz", hash = "sha256:e1916b3754915cb411ef977083500e1f30f81f7b3aea6ff5eed1cec91944dea6"}, - {file = "mypy_boto3_appconfig-1.24.36.post1-py3-none-any.whl", hash = "sha256:a5dbe549dbebf4bc7a6cfcbfa9dff89ceb4983c042b785763ee656504bdb49f6"}, + {file = "mypy-boto3-appconfig-1.25.0.tar.gz", hash = "sha256:a4674c2c616d67a4a5b6cd722a32e24bdd05149c195e66a986657d500dc821c8"}, + {file = "mypy_boto3_appconfig-1.25.0-py3-none-any.whl", hash = "sha256:2137d81caa379db120ded09cbd9263da7e504f83696fa24e3cbb58c10471e1ee"}, ] mypy-boto3-appconfigdata = [ - {file = "mypy-boto3-appconfigdata-1.24.36.post1.tar.gz", hash = "sha256:48c0b29a99f5e5a54a4585a4b3661bc00c7db40e481c5d014a4bfd86d1ae645e"}, - {file = "mypy_boto3_appconfigdata-1.24.36.post1-py3-none-any.whl", hash = "sha256:2bc495e6b6bd358d78d30f84b750d17ac326b2b4356a7786d0d1334812416edd"}, + {file = "mypy-boto3-appconfigdata-1.25.0.tar.gz", hash = "sha256:1ce2bb2bace41a3c8641547b55276a61360b53d38e7572f98cd838657baabee2"}, + {file = "mypy_boto3_appconfigdata-1.25.0-py3-none-any.whl", hash = "sha256:21a332c85080ce2c5416b751f4fc4870e057af85d1aedc33516bde2a86330caa"}, ] mypy-boto3-cloudformation = [ - {file = "mypy-boto3-cloudformation-1.24.36.post1.tar.gz", hash = "sha256:ed7df9ae3a8390a145229122a1489d0a58bbf9986cb54f0d7a65ed54f12c8e63"}, - {file = "mypy_boto3_cloudformation-1.24.36.post1-py3-none-any.whl", hash = "sha256:b39020c13a876bb18908aad22326478d0ac3faec0bdac0d2c11dc318c9dcf149"}, + {file = "mypy-boto3-cloudformation-1.25.0.tar.gz", hash = "sha256:1251b0f24b0a7c21a6e1f7f88fbf6aaa7fcc490b82d6ada46b5778cfd12d112f"}, + {file = "mypy_boto3_cloudformation-1.25.0-py3-none-any.whl", hash = "sha256:469e3cbc0a78003cc3134dece0203d0a0bfa908af34187aa53cd610b5f9bb19f"}, ] mypy-boto3-cloudwatch = [ - {file = "mypy-boto3-cloudwatch-1.24.55.tar.gz", hash = "sha256:f8950de7a93b3db890cd8524514a2245d9b5fd83ce2dd60a37047a2cd42d5dd6"}, - {file = "mypy_boto3_cloudwatch-1.24.55-py3-none-any.whl", hash = "sha256:23faf8fdfe928f9dcce453a60b03bda69177554eb88c2d7e5240ff91b5b14388"}, + {file = "mypy-boto3-cloudwatch-1.25.0.tar.gz", hash = "sha256:d5323ffeafe5144a232e27242c5d2f334f5e7ff10d0733145328888783ffcf12"}, + {file = "mypy_boto3_cloudwatch-1.25.0-py3-none-any.whl", hash = "sha256:e4934d92972f8ea531959593e476a5967b16aed223dc3c076e7e123acc8a2e77"}, ] mypy-boto3-dynamodb = [ - {file = "mypy-boto3-dynamodb-1.24.74.tar.gz", hash = "sha256:7c5b4dc26e05375d3a2cadc28b253a38060c27aa4d6a9394b3d5deea45171f91"}, - {file = "mypy_boto3_dynamodb-1.24.74-py3-none-any.whl", hash = "sha256:1111c2eb8129bf8c09b5423d95ad483943f5fc08d745801c356f6a1b22b04b37"}, + {file = "mypy-boto3-dynamodb-1.25.0.tar.gz", hash = "sha256:a858453090955e29c0ca479ea19f627a2d0dcf916469b104a5c6ad648f1299ba"}, + {file = "mypy_boto3_dynamodb-1.25.0-py3-none-any.whl", hash = "sha256:03437167a084ac0eb718fdaf5931949247b344acc4f75b8b5528f078c8f6f073"}, ] mypy-boto3-lambda = [ - {file = "mypy-boto3-lambda-1.24.54.tar.gz", hash = "sha256:c76d28d84bdf94c8980acd85bc07f2747559ca11a990fd6785c9c2389e13aff1"}, - {file = "mypy_boto3_lambda-1.24.54-py3-none-any.whl", hash = "sha256:231b6aac22b107ebb7afa2ec6dc1311b769dbdd5bfae957cf60db3e8bc3133d7"}, + {file = "mypy-boto3-lambda-1.25.0.tar.gz", hash = "sha256:441ea9b9a6aa94a70e4e69dd9c7148434e7e501decb5cd8e278f8ca878ef77d3"}, + {file = "mypy_boto3_lambda-1.25.0-py3-none-any.whl", hash = "sha256:2564695a40b962a026f6fd642544df7c76ca6ea664d76b13f400e216f09bd78c"}, ] mypy-boto3-logs = [ - {file = "mypy-boto3-logs-1.24.36.post1.tar.gz", hash = "sha256:8b00c2d5328e72023b1d1acd65e7cea7854f07827d23ce21c78391ca74271290"}, - {file = "mypy_boto3_logs-1.24.36.post1-py3-none-any.whl", hash = "sha256:f96257ec06099bfda1ce5f35b410e7fb93fb601bc312e8d7a09b13adaefd23f0"}, + {file = "mypy-boto3-logs-1.25.0.tar.gz", hash = "sha256:21769777f8ae286d9232ec7ebde0c4074de2253f7658df43dcb6835a8aada2e3"}, + {file = "mypy_boto3_logs-1.25.0-py3-none-any.whl", hash = "sha256:fddc937f53a25bb3849e3bbe5b07d0baae504a87f19060308dacee99b76c8f7f"}, ] mypy-boto3-s3 = [ - {file = "mypy-boto3-s3-1.24.94.tar.gz", hash = "sha256:0907df7b0c03a8c158d7d08fcb3c255505efca88347224425a8fc687e4596fa1"}, - {file = "mypy_boto3_s3-1.24.94-py3-none-any.whl", hash = "sha256:58f1861c9dd9037301e0ccacebe8936bf61aba5a6a43223f74bf169c3df504d2"}, + {file = "mypy-boto3-s3-1.25.0.tar.gz", hash = "sha256:68977f744ce3b9c42088467ff66e33e791ca3f27b0dc55f3b550298f03ea1a6f"}, + {file = "mypy_boto3_s3-1.25.0-py3-none-any.whl", hash = "sha256:a597db46fef02232417f6e4c2bd5d4960af0b7dc330b8a5a91ad0538405d46c6"}, ] mypy-boto3-secretsmanager = [ - {file = "mypy-boto3-secretsmanager-1.24.83.tar.gz", hash = "sha256:e39b55ffa05310832544bc4212c5b6fad4f97bf9f60f05827385d266f481a7ff"}, - {file = "mypy_boto3_secretsmanager-1.24.83-py3-none-any.whl", hash = "sha256:9ed3ec38a6c05961cb39a2d9fb891441d4cf22c63e34a6998fbd3d28ba290d9a"}, + {file = "mypy-boto3-secretsmanager-1.25.0.tar.gz", hash = "sha256:8f61d60fbe8a662f2a16a936615724d6d6e0aee7792f613e3be8a397d91de988"}, + {file = "mypy_boto3_secretsmanager-1.25.0-py3-none-any.whl", hash = "sha256:a11c40f1e89273107fdba4b6f219e728a8bfea19e7a46a0aaff9c3b3fe095211"}, ] mypy-boto3-ssm = [ - {file = "mypy-boto3-ssm-1.24.90.tar.gz", hash = "sha256:8fdc65a34958ae89d4ae8ea7748caec46226216b35d75adf87e8ed40a798bf95"}, - {file = "mypy_boto3_ssm-1.24.90-py3-none-any.whl", hash = "sha256:6fc26896e1fb4f84f5bbc04f79ba698e4dd296586ca462c517bc64e78d326fb5"}, + {file = "mypy-boto3-ssm-1.25.0.tar.gz", hash = "sha256:8162d6677c3a1432131ef41b85f339fcf37c106a1916dcb1c54dc0621353be3b"}, + {file = "mypy_boto3_ssm-1.25.0-py3-none-any.whl", hash = "sha256:3fc7fb8b59a57330c7546190002717e094ff57532b6f286707f57f54e9156d03"}, ] mypy-boto3-xray = [ - {file = "mypy-boto3-xray-1.24.36.post1.tar.gz", hash = "sha256:104f1ecf7f1f6278c582201e71a7ab64843d3a3fdc8f23295cf68788cc77e9bb"}, - {file = "mypy_boto3_xray-1.24.36.post1-py3-none-any.whl", hash = "sha256:97b9f0686c717c8be99ac06cb52febaf71712b4e4cd0b61ed2eb5ed012a9b5fd"}, + {file = "mypy-boto3-xray-1.25.0.tar.gz", hash = "sha256:db95b35c7075e610d6e0b4031e8dbdd08314cfc87f5634e14a1981f094a3a9d0"}, + {file = "mypy_boto3_xray-1.25.0-py3-none-any.whl", hash = "sha256:c5e50565bdd4de516b80fc3b3343642e83eeed6ae4779bb199f07af238677eeb"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, @@ -2047,8 +2047,8 @@ pygments = [ {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, ] pymdown-extensions = [ - {file = "pymdown_extensions-9.6-py3-none-any.whl", hash = "sha256:1e36490adc7bfcef1fdb21bb0306e93af99cff8ec2db199bd17e3bf009768c11"}, - {file = "pymdown_extensions-9.6.tar.gz", hash = "sha256:b956b806439bbff10f726103a941266beb03fbe99f897c7d5e774d7170339ad9"}, + {file = "pymdown_extensions-9.7-py3-none-any.whl", hash = "sha256:767d07d9dead0f52f5135545c01f4ed627f9a7918ee86c646d893e24c59db87d"}, + {file = "pymdown_extensions-9.7.tar.gz", hash = "sha256:651b0107bc9ee790aedea3673cb88832c0af27d2569cf45c2de06f1d65292e96"}, ] pyparsing = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, @@ -2078,8 +2078,8 @@ pyrsistent = [ {file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"}, ] pytest = [ - {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, - {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, + {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, + {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, ] pytest-asyncio = [ {file = "pytest-asyncio-0.20.1.tar.gz", hash = "sha256:626699de2a747611f3eeb64168b3575f70439b06c3d0206e6ceaeeb956e65519"}, @@ -2393,6 +2393,6 @@ xenon = [ {file = "xenon-0.9.0.tar.gz", hash = "sha256:d2b9cb6c6260f771a432c1e588e51fddb17858f88f73ef641e7532f7a5f58fb8"}, ] zipp = [ - {file = "zipp-3.9.0-py3-none-any.whl", hash = "sha256:972cfa31bc2fedd3fa838a51e9bc7e64b7fb725a8c00e7431554311f180e9980"}, - {file = "zipp-3.9.0.tar.gz", hash = "sha256:3a7af91c3db40ec72dd9d154ae18e008c69efe8ca88dde4f9a731bb82fe2f9eb"}, + {file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"}, + {file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"}, ] diff --git a/pyproject.toml b/pyproject.toml index becdd1d263c..15a240bddb8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,8 +154,8 @@ markers = [ ] [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["poetry-core>=1.3.2"] +build-backend = "poetry.core.masonry.api" # NOTE # As of now, Feb 2020, flake8 don't support pyproject From 8f1cb7d4891520d82359f9474e4437e71acdb270 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 25 Oct 2022 14:59:56 +0100 Subject: [PATCH 17/38] docs(we-made-this): new community content section (#1650) Co-authored-by: heitorlessa --- docs/we_made_this.md | 117 +++++++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 5 +- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 docs/we_made_this.md diff --git a/docs/we_made_this.md b/docs/we_made_this.md new file mode 100644 index 00000000000..a4409d92a3d --- /dev/null +++ b/docs/we_made_this.md @@ -0,0 +1,117 @@ +--- +title: We Made This (Community) +description: Blog posts, tutorials, and videos about Lambda Powertools created by the Powertools Community. +--- + + + +This space is dedicated to highlight our awesome community content featuring Lambda Powertools 🙏! + +!!! info "[Get your content featured here](https://github.com/awslabs/aws-lambda-powertools-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E){target="_blank"}!" + +## Connect + +[![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET){target="_blank"} + +Join us on [Discord](https://discord.gg/B8zZKbbyET){target="_blank"} to connect with the Powertools community 👋. Ask questions, learn from each other, contribute, hang out with key contributors, and more! + +## Blog posts + +### AWS Lambda Cookbook — Following best practices with Lambda Powertools + +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** + +A collection of articles explaining in detail how Lambda Powertools helps with a Serverless adoption strategy and its challenges. + +* [Part 1 - Logging](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-1-logging){:target="_blank"} + +* [Part 2 - Observability: monitoring and tracing](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-2-observability){:target="_blank"} + +* [Part 3 - Business Domain Observability](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-3-business-domain-observability){:target="_blank"} + +* [Part 4 - Environment Variables](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-environment-variables){:target="_blank"} + +* [Part 5 - Input Validation](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-elevate-your-handler-s-code-part-5-input-validation){:target="_blank"} + +* [Part 6 - Configuration & Feature Flags](https://www.ranthebuilder.cloud/post/aws-lambda-cookbook-part-6-feature-flags-configuration-best-practices){:target="_blank"} + +### Making all your APIs idempotent + +> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank"}** :material-twitter: + +This article dives into what idempotency means for APIs, their use cases, and how to implement them. + +* [blog.walmsles.io/making-all-your-apis-idempotent](https://blog.walmsles.io/making-all-your-apis-idempotent){target="_blank"} + +### Deep dive on Lambda Powertools Idempotency feature + +> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank"}** :material-twitter: + +This article describes how to best calculate your idempotency token, implementation details, and how to handle idempotency in RESTful APIs. + +* [blog.walmsles.io/aws-lambda-powertools-idempotency-a-deeper-dive](https://blog.walmsles.io/aws-lambda-powertools-idempotency-a-deeper-dive){target="_blank"} + +### Developing AWS Lambda functions with AWS Lambda Powertools + +> **Author: [Stephan Huber](https://linkedin.com/in/sthuber90){target="_blank"}** :material-linkedin: + +This article walks through how to add Powertools to an existing project, covers Tracer, Logger, Metrics, and JSON Schema Validation. + +* [globaldatanet.com/tech-blog/develop-lambda-functions-with-aws-lambda-powertools](https://globaldatanet.com/tech-blog/develop-lambda-functions-with-aws-lambda-powertools){target="_blank"} + +### Speed-up event-driven projects + +> **Author: [Joris Conijn](https://www.linkedin.com/in/jorisconijn){target="_blank"}** :material-linkedin: + +This article walks through a sample AWS EventBridge cookiecutter template presented at the AWS Community Day Netherlands 2022. + +* [binx.io/2022/10/11/speedup-event-driven-projects/](https://binx.io/2022/10/11/speedup-event-driven-projects/){target="_blank"} +* [Slides](https://www.slideshare.net/JorisConijn/let-codecommit-work-for-you){target="_blank"} + +## Videos + +#### Building a resilient input handling with Parser + +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** + +When building applications with AWS Lambda it is critical to verify the data structure and validate the input due to the multiple different sources that can trigger them. In this session Ran Isenberg (CyberArk) will present one of the interesting features of AWS Lambda Powertools for python: the parser. + +In this session you will learn how to increase code quality, extensibility and testability, boost you productivity and ship rock solid apps to production. + + + +#### Talk DEV to me | Feature Flags with AWS Lambda Powertools + +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** + +A deep dive in the [Feature Flags](./utilities/feature_flags.md){target="_blank"} feature along with tips and tricks. + + + +## Workshops + +### Introduction to Lambda Powertools + +> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank"}** :material-twitter: + +This repo contains documentation for a live coding workshop for the AWS Programming and Tools Meetup in Melbourne. The workshop will start with the SAM Cli "Hello World" example API project. + +Throughout the labs we will introduce each of the AWS Lambda Powertools Core utilities to showcase how simple they are to use and adopt for all your projects, and how powerful they are at bringing you closer to the Well Architected Serverless Lens. + +* :material-github: [github.com/walmsles/lambda-powertools-coding-workshop](https://github.com/walmsles/lambda-powertools-coding-workshop){target="_blank"} + +**Walk-through video** + + + +## Sample projects + +### Complete Lambda Handler Cookbook + +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** + +This repository provides a working, deployable, open source based, AWS Lambda handler and [AWS CDK](https://aws.amazon.com/cdk/){target="_blank"} Python code. + +This handler embodies Serverless best practices and has all the bells and whistles for a proper production ready handler. It uses many of the AWS Lambda Powertools utilities for Python. + +:material-github: [github.com/ran-isenberg/aws-lambda-handler-cookbook](https://github.com/ran-isenberg/aws-lambda-handler-cookbook){:target="_blank"} diff --git a/mkdocs.yml b/mkdocs.yml index 59fcdfa6a08..65e053ae27c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,6 +11,7 @@ nav: - Roadmap: roadmap.md - API reference: api/" target="_blank - Upgrade guide: upgrade.md + - We Made This (Community): we_made_this.md - Core utilities: - core/tracer.md - core/logger.md @@ -77,7 +78,9 @@ markdown_extensions: permalink: true toc_depth: 4 - attr_list - - pymdownx.emoji + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg - pymdownx.inlinehilite - pymdownx.superfences: custom_fences: From 92353a7d16d6eb3ee63e383bb28d1062648bd868 Mon Sep 17 00:00:00 2001 From: Release bot Date: Tue, 25 Oct 2022 14:00:21 +0000 Subject: [PATCH 18/38] update changelog with latest changes --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d0b0503e0d..5aa7e9cee8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,28 @@ # Unreleased +## Bug Fixes + +* **deps:** update build system to poetry-core ([#1651](https://github.com/awslabs/aws-lambda-powertools-python/issues/1651)) + ## Documentation * **index:** fold support us banner * **index:** add quotes to pip for zsh customers * **install:** address early v2 feedback on installation and project support +* **we-made-this:** new community content section ([#1650](https://github.com/awslabs/aws-lambda-powertools-python/issues/1650)) + +## Features + +* **layers:** add layer balancer script ([#1643](https://github.com/awslabs/aws-lambda-powertools-python/issues/1643)) ## Maintenance * **ci:** fix typo on version description +* **deps:** bump docker/setup-qemu-action from 2.0.0 to 2.1.0 ([#1627](https://github.com/awslabs/aws-lambda-powertools-python/issues/1627)) +* **deps:** bump peaceiris/actions-gh-pages from 3.8.0 to 3.9.0 ([#1649](https://github.com/awslabs/aws-lambda-powertools-python/issues/1649)) +* **deps-dev:** bump flake8-variables-names from 0.0.4 to 0.0.5 ([#1628](https://github.com/awslabs/aws-lambda-powertools-python/issues/1628)) +* **deps-dev:** bump pytest-asyncio from 0.16.0 to 0.20.1 ([#1635](https://github.com/awslabs/aws-lambda-powertools-python/issues/1635)) * **docs:** remove v2 banner on top of the docs From c2c08873e781527fd17011970921d9699cdd708c Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Oct 2022 16:08:14 +0200 Subject: [PATCH 19/38] fix(ci): linting issues after flake8-blackbear,mypy upgrades --- .../utilities/parser/parser.py | 8 +-- poetry.lock | 72 +++++++------------ pyproject.toml | 3 +- tests/e2e/utils/lambda_layer/base.py | 2 +- 4 files changed, 31 insertions(+), 54 deletions(-) diff --git a/aws_lambda_powertools/utilities/parser/parser.py b/aws_lambda_powertools/utilities/parser/parser.py index 9cb0c00f73a..eeaa5612fff 100644 --- a/aws_lambda_powertools/utilities/parser/parser.py +++ b/aws_lambda_powertools/utilities/parser/parser.py @@ -1,11 +1,7 @@ import logging from typing import Any, Callable, Dict, Optional, Type, overload -from aws_lambda_powertools.utilities.parser.types import ( - EnvelopeModel, - EventParserReturnType, - Model, -) +from aws_lambda_powertools.utilities.parser.types import EventParserReturnType, Model from ...middleware_factory import lambda_handler_decorator from ..typing import LambdaContext @@ -94,7 +90,7 @@ def parse(event: Dict[str, Any], model: Type[Model]) -> Model: @overload -def parse(event: Dict[str, Any], model: Type[Model], envelope: Type[Envelope]) -> EnvelopeModel: +def parse(event: Dict[str, Any], model: Type[Model], envelope: Type[Envelope]): ... # pragma: no cover diff --git a/poetry.lock b/poetry.lock index 4195693dcc9..55b3be820ef 100644 --- a/poetry.lock +++ b/poetry.lock @@ -426,21 +426,6 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "flake8-isort" -version = "4.2.0" -description = "flake8 plugin that integrates isort ." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = ">=3.2.1,<6" -isort = ">=4.3.5,<6" - -[package.extras] -test = ["pytest-cov"] - [[package]] name = "flake8-variables-names" version = "0.0.5" @@ -810,11 +795,11 @@ python-versions = ">=3.7" [[package]] name = "mypy" -version = "0.971" +version = "0.982" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] mypy-extensions = ">=0.4.3" @@ -1526,7 +1511,7 @@ validation = ["fastjsonschema"] [metadata] lock-version = "1.1" python-versions = "^3.7.4" -content-hash = "026b049a610e7643a180c269a4d323b203e9f5737efbeea23f78ca7594010a5d" +content-hash = "cd2375547d2f32a8129c1fea82bd2f387950ffe79e2cb79262361eaed7e6a37b" [metadata.files] attrs = [ @@ -1729,10 +1714,6 @@ flake8-fixme = [ {file = "flake8-fixme-1.1.1.tar.gz", hash = "sha256:50cade07d27a4c30d4f12351478df87339e67640c83041b664724bda6d16f33a"}, {file = "flake8_fixme-1.1.1-py2.py3-none-any.whl", hash = "sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac"}, ] -flake8-isort = [ - {file = "flake8-isort-4.2.0.tar.gz", hash = "sha256:26571500cd54976bbc0cf1006ffbcd1a68dd102f816b7a1051b219616ba9fee0"}, - {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, -] flake8-variables-names = [ {file = "flake8_variables_names-0.0.5-py3-none-any.whl", hash = "sha256:e3277031696bbe10b5132b49938cde1d70fcae9561533b7bd7ab8e69cb27addb"}, {file = "flake8_variables_names-0.0.5.tar.gz", hash = "sha256:30133e14ee2300e13a60393a00f74d98110c76070ac67d1ab91606f02824a7e1"}, @@ -1885,29 +1866,30 @@ mkdocs-material-extensions = [ {file = "mkdocs_material_extensions-1.1.tar.gz", hash = "sha256:96ca979dae66d65c2099eefe189b49d5ac62f76afb59c38e069ffc7cf3c131ec"}, ] mypy = [ - {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, - {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, - {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, - {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, - {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, - {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, - {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, - {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, - {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, - {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, - {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, - {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, - {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, - {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, - {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, - {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, - {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, - {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, - {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, + {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, + {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, + {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, + {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, + {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, + {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, + {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, + {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, + {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, + {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, + {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, + {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, + {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, + {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, + {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, + {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, + {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, + {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, + {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, + {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, ] mypy-boto3-appconfig = [ {file = "mypy-boto3-appconfig-1.25.0.tar.gz", hash = "sha256:a4674c2c616d67a4a5b6cd722a32e24bdd05149c195e66a986657d500dc821c8"}, diff --git a/pyproject.toml b/pyproject.toml index 15a240bddb8..8c959d6e043 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,6 @@ flake8-builtins = "^2.0.0" flake8-comprehensions = "^3.7.0" flake8-debugger = "^4.0.0" flake8-fixme = "^1.1.1" -flake8-isort = "^4.1.2" flake8-variables-names = "^0.0.5" flake8-black = "^0.3.3" isort = "^5.10.1" @@ -49,7 +48,6 @@ flake8-eradicate = "^1.2.1" flake8-bugbear = "^22.9.23" mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" -mypy = "^0.971" retry = "^0.9.2" pytest-xdist = "^2.5.0" aws-cdk-lib = "^2.47.0" @@ -85,6 +83,7 @@ aws-sdk = ["boto3"] [tool.poetry.group.dev.dependencies] cfn-lint = "0.67.0" +mypy = "^0.982" [tool.coverage.run] source = ["aws_lambda_powertools"] diff --git a/tests/e2e/utils/lambda_layer/base.py b/tests/e2e/utils/lambda_layer/base.py index 280fe19d4f8..e38e936eefc 100644 --- a/tests/e2e/utils/lambda_layer/base.py +++ b/tests/e2e/utils/lambda_layer/base.py @@ -27,6 +27,6 @@ def before_build(self): # Create missing parent directories if missing self.output_dir.mkdir(parents=True, exist_ok=True) - def after_build(self): + def after_build(self): # noqa: B027 """Any step after a build succeed""" ... From 95340fcee98210fca919b475d7e90d757de53ddd Mon Sep 17 00:00:00 2001 From: Release bot Date: Tue, 25 Oct 2022 14:11:12 +0000 Subject: [PATCH 20/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aa7e9cee8b..4b03095d773 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ## Bug Fixes +* **ci:** linting issues after flake8-blackbear,mypy upgrades * **deps:** update build system to poetry-core ([#1651](https://github.com/awslabs/aws-lambda-powertools-python/issues/1651)) ## Documentation From 5054c26f4162b4b327b31bf1321ef6d5b6d89a09 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Oct 2022 16:17:09 +0200 Subject: [PATCH 21/38] docs(community): fix twitch parent domain for embedded video --- docs/we_made_this.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/we_made_this.md b/docs/we_made_this.md index a4409d92a3d..430b7790921 100644 --- a/docs/we_made_this.md +++ b/docs/we_made_this.md @@ -78,7 +78,7 @@ When building applications with AWS Lambda it is critical to verify the data str In this session you will learn how to increase code quality, extensibility and testability, boost you productivity and ship rock solid apps to production. - + #### Talk DEV to me | Feature Flags with AWS Lambda Powertools @@ -86,7 +86,7 @@ In this session you will learn how to increase code quality, extensibility and t A deep dive in the [Feature Flags](./utilities/feature_flags.md){target="_blank"} feature along with tips and tricks. - + ## Workshops From b6ba0b22db5fb75a903e7e7c488e364323b92b13 Mon Sep 17 00:00:00 2001 From: Release bot Date: Tue, 25 Oct 2022 14:17:57 +0000 Subject: [PATCH 22/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b03095d773..b4e750cbcad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ## Documentation +* **community:** fix twitch parent domain for embedded video * **index:** fold support us banner * **index:** add quotes to pip for zsh customers * **install:** address early v2 feedback on installation and project support From 64cc5cf3d6626ec5e679b3ba7dbf1e3915228593 Mon Sep 17 00:00:00 2001 From: Ran Isenberg <60175085+ran-isenberg@users.noreply.github.com> Date: Tue, 25 Oct 2022 21:55:34 +0300 Subject: [PATCH 23/38] docs(community): fix social handlers for Ran (#1654) --- docs/we_made_this.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/we_made_this.md b/docs/we_made_this.md index 430b7790921..ae6d516c2c8 100644 --- a/docs/we_made_this.md +++ b/docs/we_made_this.md @@ -19,7 +19,7 @@ Join us on [Discord](https://discord.gg/B8zZKbbyET){target="_blank"} to connect ### AWS Lambda Cookbook — Following best practices with Lambda Powertools -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** A collection of articles explaining in detail how Lambda Powertools helps with a Serverless adoption strategy and its challenges. @@ -72,7 +72,7 @@ This article walks through a sample AWS EventBridge cookiecutter template presen #### Building a resilient input handling with Parser -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** When building applications with AWS Lambda it is critical to verify the data structure and validate the input due to the multiple different sources that can trigger them. In this session Ran Isenberg (CyberArk) will present one of the interesting features of AWS Lambda Powertools for python: the parser. @@ -82,7 +82,7 @@ In this session you will learn how to increase code quality, extensibility and t #### Talk DEV to me | Feature Flags with AWS Lambda Powertools -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** A deep dive in the [Feature Flags](./utilities/feature_flags.md){target="_blank"} feature along with tips and tricks. @@ -108,7 +108,7 @@ Throughout the labs we will introduce each of the AWS Lambda Powertools Core uti ### Complete Lambda Handler Cookbook -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/ranthebuilder){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** This repository provides a working, deployable, open source based, AWS Lambda handler and [AWS CDK](https://aws.amazon.com/cdk/){target="_blank"} Python code. From 67532d7c131b93435d9797afc97b3b48205f1427 Mon Sep 17 00:00:00 2001 From: Release bot Date: Tue, 25 Oct 2022 18:56:00 +0000 Subject: [PATCH 24/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4e750cbcad..a96e0f9d8d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ## Documentation +* **community:** fix social handlers for Ran ([#1654](https://github.com/awslabs/aws-lambda-powertools-python/issues/1654)) * **community:** fix twitch parent domain for embedded video * **index:** fold support us banner * **index:** add quotes to pip for zsh customers From 8fd9e0c112bed4ed9663f74ebc5823ddf1bacfb4 Mon Sep 17 00:00:00 2001 From: Piers Karsenbarg Date: Wed, 26 Oct 2022 15:47:13 +0100 Subject: [PATCH 25/38] docs(homepage): add Pulumi code example (#1652) Co-authored-by: Leandro Damascena --- docs/index.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/docs/index.md b/docs/index.md index 8da0f26f870..8f199647e4f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -209,6 +209,42 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: } ``` + === "Pulumi" + + ```python + import json + import pulumi + import pulumi_aws as aws + + role = aws.iam.Role("role", + assume_role_policy=json.dumps({ + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Effect": "Allow" + } + ] + }), + managed_policy_arns=[aws.iam.ManagedPolicy.AWS_LAMBDA_BASIC_EXECUTION_ROLE] + ) + + lambda_function = aws.lambda_.Function("function", + layers=[pulumi.Output.concat("arn:aws:lambda:",aws.get_region_output().name,":017000801446:layer:AWSLambdaPowertoolsPythonV2:11")], + tracing_config={ + "mode": "Active" + }, + runtime=aws.lambda_.Runtime.PYTHON3D9, + handler="index.handler", + role=role.arn, + architectures=["x86_64"], + code=pulumi.FileArchive("lambda_function_payload.zip") + ) + ``` + === "Amplify" ```zsh @@ -341,6 +377,42 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: ``` + === "Pulumi" + + ```python + import json + import pulumi + import pulumi_aws as aws + + role = aws.iam.Role("role", + assume_role_policy=json.dumps({ + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Effect": "Allow" + } + ] + }), + managed_policy_arns=[aws.iam.ManagedPolicy.AWS_LAMBDA_BASIC_EXECUTION_ROLE] + ) + + lambda_function = aws.lambda_.Function("function", + layers=[pulumi.Output.concat("arn:aws:lambda:",aws.get_region_output().name,":017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11")], + tracing_config={ + "mode": "Active" + }, + runtime=aws.lambda_.Runtime.PYTHON3D9, + handler="index.handler", + role=role.arn, + architectures=["arm64"], + code=pulumi.FileArchive("lambda_function_payload.zip") + ) + ``` + === "Amplify" ```zsh From 0c742e066cdaa2b1ccef392ee8e68ac4e5b6519f Mon Sep 17 00:00:00 2001 From: Release bot Date: Wed, 26 Oct 2022 14:47:38 +0000 Subject: [PATCH 26/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a96e0f9d8d1..fd2bf34d8ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * **community:** fix social handlers for Ran ([#1654](https://github.com/awslabs/aws-lambda-powertools-python/issues/1654)) * **community:** fix twitch parent domain for embedded video +* **homepage:** add Pulumi code example ([#1652](https://github.com/awslabs/aws-lambda-powertools-python/issues/1652)) * **index:** fold support us banner * **index:** add quotes to pip for zsh customers * **install:** address early v2 feedback on installation and project support From 87de70c4d82530932bc4f56175def0ecc46363a3 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 26 Oct 2022 19:40:54 +0200 Subject: [PATCH 27/38] feat(logger): accept arbitrary keyword=value for ephemeral metadata (#1658) Co-authored-by: OGoodness --- aws_lambda_powertools/logging/logger.py | 172 +++++++++++++++++- docs/core/logger.md | 25 ++- examples/logger/src/append_keys_kwargs.py | 10 + .../logger/src/append_keys_kwargs_output.json | 8 + tests/functional/test_logger.py | 19 ++ 5 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 examples/logger/src/append_keys_kwargs.py create mode 100644 examples/logger/src/append_keys_kwargs_output.json diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py index a0e24f1dcf9..2b97df75c1f 100644 --- a/aws_lambda_powertools/logging/logger.py +++ b/aws_lambda_powertools/logging/logger.py @@ -1,10 +1,12 @@ import functools import inspect +import io import logging import os import random import sys -from typing import IO, Any, Callable, Dict, Iterable, Optional, TypeVar, Union +import traceback +from typing import IO, Any, Callable, Dict, Iterable, Mapping, Optional, TypeVar, Union import jmespath @@ -235,6 +237,9 @@ def _init_logger(self, **kwargs): self._logger.addHandler(self.logger_handler) self.structure_logs(**kwargs) + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + self._logger.findCaller = self.findCaller + # Pytest Live Log feature duplicates log records for colored output # but we explicitly add a filter for log deduplication. # This flag disables this protection when you explicit want logs to be duplicated (#262) @@ -359,6 +364,126 @@ def decorate(event, context, *args, **kwargs): return decorate + def info( + self, + msg: object, + *args, + exc_info=None, + stack_info: bool = False, + stacklevel: int = 2, + extra: Optional[Mapping[str, object]] = None, + **kwargs, + ): + extra = extra or {} + extra = {**extra, **kwargs} + + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + if sys.version_info < (3, 8): # pragma: no cover + return self._logger.info(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) + return self._logger.info( + msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + ) + + def error( + self, + msg: object, + *args, + exc_info=None, + stack_info: bool = False, + stacklevel: int = 2, + extra: Optional[Mapping[str, object]] = None, + **kwargs, + ): + extra = extra or {} + extra = {**extra, **kwargs} + + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + if sys.version_info < (3, 8): # pragma: no cover + return self._logger.error(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) + return self._logger.error( + msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + ) + + def exception( + self, + msg: object, + *args, + exc_info=True, + stack_info: bool = False, + stacklevel: int = 2, + extra: Optional[Mapping[str, object]] = None, + **kwargs, + ): + extra = extra or {} + extra = {**extra, **kwargs} + + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + if sys.version_info < (3, 8): # pragma: no cover + return self._logger.exception(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) + return self._logger.exception( + msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + ) + + def critical( + self, + msg: object, + *args, + exc_info=None, + stack_info: bool = False, + stacklevel: int = 2, + extra: Optional[Mapping[str, object]] = None, + **kwargs, + ): + extra = extra or {} + extra = {**extra, **kwargs} + + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + if sys.version_info < (3, 8): # pragma: no cover + return self._logger.critical(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) + return self._logger.critical( + msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + ) + + def warning( + self, + msg: object, + *args, + exc_info=None, + stack_info: bool = False, + stacklevel: int = 2, + extra: Optional[Mapping[str, object]] = None, + **kwargs, + ): + extra = extra or {} + extra = {**extra, **kwargs} + + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + if sys.version_info < (3, 8): # pragma: no cover + return self._logger.warning(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) + return self._logger.warning( + msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + ) + + def debug( + self, + msg: object, + *args, + exc_info=None, + stack_info: bool = False, + stacklevel: int = 2, + extra: Optional[Mapping[str, object]] = None, + **kwargs, + ): + extra = extra or {} + extra = {**extra, **kwargs} + + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + if sys.version_info < (3, 8): # pragma: no cover + return self._logger.debug(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra) + return self._logger.debug( + msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra + ) + def append_keys(self, **additional_keys): self.registered_formatter.append_keys(**additional_keys) @@ -462,6 +587,41 @@ def _get_caller_filename(): caller_frame = frame.f_back.f_back.f_back return caller_frame.f_globals["__name__"] + # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work + def findCaller(self, stack_info=False, stacklevel=2): # pragma: no cover + """ + Find the stack frame of the caller so that we can note the source + file name, line number and function name. + """ + f = logging.currentframe() # noqa: VNE001 + # On some versions of IronPython, currentframe() returns None if + # IronPython isn't run with -X:Frames. + if f is None: + return "(unknown file)", 0, "(unknown function)", None + while stacklevel > 0: + next_f = f.f_back + if next_f is None: + ## We've got options here. + ## If we want to use the last (deepest) frame: + break + ## If we want to mimic the warnings module: + # return ("sys", 1, "(unknown function)", None) # noqa: E800 + ## If we want to be pedantic: # noqa: E800 + # raise ValueError("call stack is not deep enough") # noqa: E800 + f = next_f # noqa: VNE001 + if not _is_internal_frame(f): + stacklevel -= 1 + co = f.f_code + sinfo = None + if stack_info: + with io.StringIO() as sio: + sio.write("Stack (most recent call last):\n") + traceback.print_stack(f, file=sio) + sinfo = sio.getvalue() + if sinfo[-1] == "\n": + sinfo = sinfo[:-1] + return co.co_filename, f.f_lineno, co.co_name, sinfo + def set_package_logger( level: Union[str, int] = logging.DEBUG, @@ -500,3 +660,13 @@ def set_package_logger( handler = logging.StreamHandler(stream) handler.setFormatter(formatter) logger.addHandler(handler) + + +# Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work +# The following is based on warnings._is_internal_frame. It makes sure that +# frames of the import mechanism are skipped when logging at module level and +# using a stacklevel value greater than one. +def _is_internal_frame(frame): # pragma: no cover + """Signal whether the frame is a CPython or logging module internal.""" + filename = os.path.normcase(frame.f_code.co_filename) + return filename == logging._srcfile or ("importlib" in filename and "_bootstrap" in filename) diff --git a/docs/core/logger.md b/docs/core/logger.md index f98962a0f5f..8fc9da441ac 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -158,7 +158,7 @@ To ease routine tasks like extracting correlation ID from popular event sources, You can append additional keys using either mechanism: * Persist new keys across all future log messages via `append_keys` method -* Add additional keys on a per log message basis via `extra` parameter +* Add additional keys on a per log message basis as a keyword=value, or via `extra` parameter #### append_keys method @@ -184,14 +184,33 @@ You can append your own keys to your existing Logger via `append_keys(**addition This example will add `order_id` if its value is not empty, and in subsequent invocations where `order_id` might not be present it'll remove it from the Logger. +#### ephemeral metadata + +You can pass an arbitrary number of keyword arguments (kwargs) to all log level's methods, e.g. `logger.info, logger.warning`. + +Two common use cases for this feature is to enrich log statements with additional metadata, or only add certain keys conditionally. + +!!! info "Any keyword argument added will not be persisted in subsequent messages." + +=== "append_keys_kwargs.py" + + ```python hl_lines="8" + --8<-- "examples/logger/src/append_keys_kwargs.py" + ``` + +=== "append_keys_kwargs_output.json" + + ```json hl_lines="7" + --8<-- "examples/logger/src/append_keys_kwargs_output.json" + ``` + #### extra parameter Extra parameter is available for all log levels' methods, as implemented in the standard logging library - e.g. `logger.info, logger.warning`. It accepts any dictionary, and all keyword arguments will be added as part of the root structure of the logs for that log statement. -???+ info - Any keyword argument added using `extra` will not be persisted for subsequent messages. +!!! info "Any keyword argument added using `extra` will not be persisted in subsequent messages." === "append_keys_extra.py" diff --git a/examples/logger/src/append_keys_kwargs.py b/examples/logger/src/append_keys_kwargs.py new file mode 100644 index 00000000000..5885c7e2bd6 --- /dev/null +++ b/examples/logger/src/append_keys_kwargs.py @@ -0,0 +1,10 @@ +from aws_lambda_powertools import Logger +from aws_lambda_powertools.utilities.typing import LambdaContext + +logger = Logger() + + +def handler(event: dict, context: LambdaContext) -> str: + logger.info("Collecting payment", request_id="1123") + + return "hello world" diff --git a/examples/logger/src/append_keys_kwargs_output.json b/examples/logger/src/append_keys_kwargs_output.json new file mode 100644 index 00000000000..cd888e5e2af --- /dev/null +++ b/examples/logger/src/append_keys_kwargs_output.json @@ -0,0 +1,8 @@ +{ + "level": "INFO", + "location": "collect.handler:8", + "message": "Collecting payment", + "timestamp": "2022-11-26 11:47:12,494+0200", + "service": "payment", + "request_id": "1123" +} \ No newline at end of file diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index 7eb3018ef64..4876da5cacf 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -415,6 +415,25 @@ def test_logger_extra_kwargs(stdout, service_name): assert "request_id" not in no_extra_fields_log +def test_logger_arbitrary_fields_as_kwargs(stdout, service_name): + # GIVEN Logger is initialized + logger = Logger(service=service_name, stream=stdout) + + # WHEN `request_id` is an arbitrary field in a log message to the existing structured log + fields = {"request_id": "blah"} + + logger.info("with arbitrary fields", **fields) + logger.info("without extra fields") + + extra_fields_log, no_extra_fields_log = capture_multiple_logging_statements_output(stdout) + + # THEN first log should have request_id field in the root structure + assert "request_id" in extra_fields_log + + # THEN second log should not have request_id in the root structure + assert "request_id" not in no_extra_fields_log + + def test_logger_log_twice_when_log_filter_isnt_present_and_root_logger_is_setup(monkeypatch, stdout, service_name): # GIVEN Lambda configures the root logger with a handler root_logger = logging.getLogger() From 9ce429971a84952ecfdfcf669c98b114f20d5bd8 Mon Sep 17 00:00:00 2001 From: Release bot Date: Wed, 26 Oct 2022 17:41:19 +0000 Subject: [PATCH 28/38] update changelog with latest changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd2bf34d8ec..943f8c5bc79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ ## Features * **layers:** add layer balancer script ([#1643](https://github.com/awslabs/aws-lambda-powertools-python/issues/1643)) +* **logger:** accept arbitrary keyword=value for ephemeral metadata ([#1658](https://github.com/awslabs/aws-lambda-powertools-python/issues/1658)) ## Maintenance From 577bb10dd037e3fd99c1a9155eaae674c81fafdd Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Thu, 27 Oct 2022 12:00:51 +0200 Subject: [PATCH 29/38] docs(homepage): remove 3.6 and add hero image Signed-off-by: Heitor Lessa --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f34c0104c67..37eda06b5b4 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ [![Build](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/python_build.yml/badge.svg)](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/python_build.yml) [![codecov.io](https://codecov.io/github/awslabs/aws-lambda-powertools-python/branch/develop/graphs/badge.svg)](https://app.codecov.io/gh/awslabs/aws-lambda-powertools-python) -![PythonSupport](https://img.shields.io/static/v1?label=python&message=3.6%20|%203.7|%203.8|%203.9&color=blue?style=flat-square&logo=python) ![PyPI version](https://badge.fury.io/py/aws-lambda-powertools.svg) ![PyPi monthly downloads](https://img.shields.io/pypi/dm/aws-lambda-powertools) [![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET) +![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.7|%203.8|%203.9&color=blue?style=flat-square&logo=python) ![PyPI version](https://badge.fury.io/py/aws-lambda-powertools.svg) ![PyPi monthly downloads](https://img.shields.io/pypi/dm/aws-lambda-powertools) [![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET) -A suite of Python utilities for AWS Lambda functions to ease adopting best practices such as tracing, structured logging, custom metrics, and more. +A suite of Python utilities for AWS Lambda functions to ease adopting best practices such as tracing, structured logging, custom metrics, [and more](https://awslabs.github.io/aws-lambda-powertools-python/latest/#features). > Also available in [Java](https://github.com/awslabs/aws-lambda-powertools-java), [Typescript](https://github.com/awslabs/aws-lambda-powertools-typescript), and [.NET](https://awslabs.github.io/aws-lambda-powertools-dotnet/). @@ -13,6 +13,9 @@ A suite of Python utilities for AWS Lambda functions to ease adopting best pract > **An AWS Developer Acceleration (DevAx) initiative by Specialist Solution Architects | aws-devax-open-source@amazon.com** +![hero-image](https://user-images.githubusercontent.com/3340292/198254617-d0fdb672-86a6-4988-8a40-adf437135e0a.png) + + ## Features * **[Tracing](https://awslabs.github.io/aws-lambda-powertools-python/latest/core/tracer/)** - Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions From baf50f9e6de5d5946baeab6398d7bd807ab3b40b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Oct 2022 20:33:54 +0000 Subject: [PATCH 30/38] chore(deps-dev): bump aws-cdk-lib from 2.47.0 to 2.48.0 (#1664) Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.47.0 to 2.48.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/v2.48.0/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.47.0...v2.48.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 | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 55b3be820ef..46da688c259 100644 --- a/poetry.lock +++ b/poetry.lock @@ -45,7 +45,7 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.47.0" +version = "2.48.0" description = "Version 2 of the AWS Cloud Development Kit library" category = "dev" optional = false @@ -53,7 +53,7 @@ python-versions = "~=3.7" [package.dependencies] constructs = ">=10.0.0,<11.0.0" -jsii = ">=1.69.0,<2.0.0" +jsii = ">=1.70.0,<2.0.0" publication = ">=0.0.3" typeguard = ">=2.13.3,<2.14.0" @@ -1511,7 +1511,7 @@ validation = ["fastjsonschema"] [metadata] lock-version = "1.1" python-versions = "^3.7.4" -content-hash = "cd2375547d2f32a8129c1fea82bd2f387950ffe79e2cb79262361eaed7e6a37b" +content-hash = "a3c2ad13e7c73278094696ff3927e1195a108f2375d14163b70d852ec621fd94" [metadata.files] attrs = [ @@ -1527,8 +1527,8 @@ aws-cdk-aws-apigatewayv2-integrations-alpha = [ {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.47.0a0-py3-none-any.whl", hash = "sha256:4633c4e020400c7ee5790652f099f02d4f84bab24fff013250e2b41a4ffca1b0"}, ] aws-cdk-lib = [ - {file = "aws-cdk-lib-2.47.0.tar.gz", hash = "sha256:c9b1626c7afc42ceaee547558efe88439dd1447b18c7837db153e03fb8186167"}, - {file = "aws_cdk_lib-2.47.0-py3-none-any.whl", hash = "sha256:1f1a2e2309625d304a14b388ee0fedb0dffc15eef14dac65e33b10f6c73bf75c"}, + {file = "aws-cdk-lib-2.48.0.tar.gz", hash = "sha256:c419ffa6b07ea945477a55b2d58c73108b886a189c721d0b7c53337b285ceb16"}, + {file = "aws_cdk_lib-2.48.0-py3-none-any.whl", hash = "sha256:8ab509b294bb1e584f6e060f789d8d613a9f55b29faa55513a3345ea18b694d8"}, ] aws-sam-translator = [ {file = "aws-sam-translator-1.53.0.tar.gz", hash = "sha256:392ed4f5fb08f72cb68a8800f0bc278d2a3b6609bd1ac66bfcdeaaa94cdc18e5"}, diff --git a/pyproject.toml b/pyproject.toml index 8c959d6e043..0d142720ee3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" retry = "^0.9.2" pytest-xdist = "^2.5.0" -aws-cdk-lib = "^2.47.0" +aws-cdk-lib = "^2.48.0" "aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^3.4.1" From 2c26f84c75b68bec39ed3c7b96eb583e3f7d6ab8 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Fri, 28 Oct 2022 12:45:14 +0200 Subject: [PATCH 31/38] fix(idempotency): idempotent_function should support standalone falsy values (#1669) --- .../utilities/idempotency/idempotency.py | 6 +-- .../idempotency/test_idempotency.py | 42 ++++++++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/idempotency.py b/aws_lambda_powertools/utilities/idempotency/idempotency.py index abd45a86be1..14fd3bfe5af 100644 --- a/aws_lambda_powertools/utilities/idempotency/idempotency.py +++ b/aws_lambda_powertools/utilities/idempotency/idempotency.py @@ -134,14 +134,14 @@ def decorate(*args, **kwargs): if os.getenv(constants.IDEMPOTENCY_DISABLED_ENV): return function(*args, **kwargs) - payload = kwargs.get(data_keyword_argument) - - if not payload: + if data_keyword_argument not in kwargs: raise RuntimeError( f"Unable to extract '{data_keyword_argument}' from keyword arguments." f" Ensure this exists in your function's signature as well as the caller used it as a keyword argument" ) + payload = kwargs.get(data_keyword_argument) + idempotency_handler = IdempotencyHandler( function=function, function_payload=payload, diff --git a/tests/functional/idempotency/test_idempotency.py b/tests/functional/idempotency/test_idempotency.py index e5c5c777971..8f39b832554 100644 --- a/tests/functional/idempotency/test_idempotency.py +++ b/tests/functional/idempotency/test_idempotency.py @@ -72,7 +72,7 @@ def test_idempotent_lambda_already_completed( lambda_context, ): """ - Test idempotent decorator where event with matching event key has already been succesfully processed + Test idempotent decorator where event with matching event key has already been successfully processed """ stubber = stub.Stubber(persistence_store.table.meta.client) @@ -1247,6 +1247,46 @@ def lambda_handler(event, _): assert handler_result == expected_result +@pytest.mark.parametrize("data", [None, 0, False]) +def test_idempotent_function_falsy_values(data): + # Scenario to validate we can use idempotent_function with any function + # receiving a falsy value (`None`, `False`, `0`, etc.) + # shouldn't cause a RuntimeError + mock_event = data + idempotency_key = f"{TESTS_MODULE_PREFIX}.test_idempotent_function_falsy_values..record_handler#{hash_idempotency_key(mock_event)}" # noqa: E501 + + persistence_layer = MockPersistenceLayer(expected_idempotency_key=idempotency_key) + expected_result = {"message": "Foo"} + + @idempotent_function(persistence_store=persistence_layer, data_keyword_argument="record") + def record_handler(record): + return expected_result + + # WHEN calling the function + result = record_handler(record=mock_event) + # THEN we expect the function to execute successfully + assert result == expected_result + + +@pytest.mark.parametrize("data", [None, 0, False]) +def test_idempotent_function_falsy_values_with_raise_on_no_idempotency_key( + data, persistence_store: DynamoDBPersistenceLayer +): + # GIVEN raise_on_no_idempotency_key is True + idempotency_config = IdempotencyConfig(event_key_jmespath="idemKey", raise_on_no_idempotency_key=True) + + @idempotent_function(data_keyword_argument="record", persistence_store=persistence_store, config=idempotency_config) + def record_handler(record): + return ValueError("Should not be raised") + + # WHEN calling the function + with pytest.raises(IdempotencyKeyError) as e: + record_handler(record=data) + + # THEN we expect an idempotency key error message + assert "No data found to create a hashed idempotency_key" == e.value.args[0] + + def test_idempotent_data_sorting(): # Scenario to validate same data in different order hashes to the same idempotency key data_one = {"data": "test message 1", "more_data": "more data 1"} From 8939535cd804d0500dca89f2e07f48ab3e619754 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Fri, 28 Oct 2022 15:58:11 +0200 Subject: [PATCH 32/38] feat(logger): add use_rfc3339 and auto-complete formatter opts in Logger (#1662) --- aws_lambda_powertools/logging/formatter.py | 33 +++++++++-- aws_lambda_powertools/logging/logger.py | 56 ++++++++++++++++--- docs/core/logger.md | 35 +++++++++--- examples/logger/src/date_formatting.py | 9 +++ .../logger/src/date_formatting_output.json | 16 ++++++ examples/logger/src/overriding_log_records.py | 11 ++-- .../src/overriding_log_records_output.json | 22 +++++--- tests/functional/test_logger.py | 15 +++++ 8 files changed, 161 insertions(+), 36 deletions(-) create mode 100644 examples/logger/src/date_formatting.py create mode 100644 examples/logger/src/date_formatting_output.json diff --git a/aws_lambda_powertools/logging/formatter.py b/aws_lambda_powertools/logging/formatter.py index 25f9c227c97..07971ba0a26 100644 --- a/aws_lambda_powertools/logging/formatter.py +++ b/aws_lambda_powertools/logging/formatter.py @@ -62,6 +62,7 @@ class LambdaPowertoolsFormatter(BasePowertoolsFormatter): default_time_format = "%Y-%m-%d %H:%M:%S,%F%z" # '2021-04-17 18:19:57,656+0200' custom_ms_time_directive = "%F" + RFC3339_ISO8601_FORMAT = "%Y-%m-%dT%H:%M:%S.%F%z" # '2022-10-27T16:27:43.738+02:00' def __init__( self, @@ -72,6 +73,7 @@ def __init__( use_datetime_directive: bool = False, log_record_order: Optional[List[str]] = None, utc: bool = False, + use_rfc3339: bool = False, **kwargs, ): """Return a LambdaPowertoolsFormatter instance. @@ -106,6 +108,9 @@ def __init__( also supports a custom %F directive for milliseconds. utc : bool, optional set logging timestamp to UTC, by default False to continue to use local time as per stdlib + use_rfc3339: bool, optional + Whether to use a popular dateformat that complies with both RFC3339 and ISO8601. + e.g., 2022-10-27T16:27:43.738+02:00. log_record_order : list, optional set order of log keys when logging, by default ["level", "location", "message", "timestamp"] kwargs @@ -129,6 +134,7 @@ def __init__( self.log_record_order = log_record_order or ["level", "location", "message", "timestamp"] self.log_format = dict.fromkeys(self.log_record_order) # Set the insertion order for the log messages self.update_formatter = self.append_keys # alias to old method + self.use_rfc3339_iso8601 = use_rfc3339 if self.utc: self.converter = time.gmtime # type: ignore @@ -153,36 +159,51 @@ def format(self, record: logging.LogRecord) -> str: # noqa: A003 return self.serialize(log=formatted_log) def formatTime(self, record: logging.LogRecord, datefmt: Optional[str] = None) -> str: + # As of Py3.7, we can infer milliseconds directly from any datetime + # saving processing time as we can shortcircuit early + # Maintenance: In V3, we (and Java) should move to this format by default + # since we've provided enough time for those migrating from std logging + if self.use_rfc3339_iso8601: + if self.utc: + ts_as_datetime = datetime.fromtimestamp(record.created, tz=timezone.utc) + else: + ts_as_datetime = datetime.fromtimestamp(record.created).astimezone() + + return ts_as_datetime.isoformat(timespec="milliseconds") # 2022-10-27T17:42:26.841+0200 + + # converts to local/UTC TZ as struct time record_ts = self.converter(record.created) # type: ignore if datefmt is None: # pragma: no cover, it'll always be None in std logging, but mypy datefmt = self.datefmt # NOTE: Python `time.strftime` doesn't provide msec directives - # so we create a custom one (%F) and replace logging record ts + # so we create a custom one (%F) and replace logging record_ts # Reason 2 is that std logging doesn't support msec after TZ msecs = "%03d" % record.msecs - # Datetime format codes might be optionally used - # however it only makes a difference if `datefmt` is passed - # since format codes are the same except %f + # Datetime format codes is a superset of time format codes + # therefore we only honour them if explicitly asked + # by default, those migrating from std logging will use time format codes + # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes if self.use_datetime_directive and datefmt: - # record.msecs are microseconds, divide by 1000 and we get milliseconds + # record.msecs are microseconds, divide by 1000 to get milliseconds timestamp = record.created + record.msecs / 1000 if self.utc: dt = datetime.fromtimestamp(timestamp, tz=timezone.utc) else: - # make sure local timezone is included dt = datetime.fromtimestamp(timestamp).astimezone() custom_fmt = datefmt.replace(self.custom_ms_time_directive, msecs) return dt.strftime(custom_fmt) + # Only time format codes being used elif datefmt: custom_fmt = datefmt.replace(self.custom_ms_time_directive, msecs) return time.strftime(custom_fmt, record_ts) + # Use default fmt: 2021-05-03 10:20:19,650+0200 custom_fmt = self.default_time_format.replace(self.custom_ms_time_directive, msecs) return time.strftime(custom_fmt, record_ts) diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py index 2b97df75c1f..be30c098db4 100644 --- a/aws_lambda_powertools/logging/logger.py +++ b/aws_lambda_powertools/logging/logger.py @@ -6,7 +6,18 @@ import random import sys import traceback -from typing import IO, Any, Callable, Dict, Iterable, Mapping, Optional, TypeVar, Union +from typing import ( + IO, + Any, + Callable, + Dict, + Iterable, + List, + Mapping, + Optional, + TypeVar, + Union, +) import jmespath @@ -86,14 +97,16 @@ class Logger(logging.Logger): # lgtm [py/missing-call-to-init] Parameters propagated to LambdaPowertoolsFormatter -------------------------------------------------- datefmt: str, optional - String directives (strftime) to format log timestamp using `time`, by default it uses RFC - 3339. + String directives (strftime) to format log timestamp using `time`, by default it uses 2021-05-03 11:47:12,494+0200. # noqa: E501 use_datetime_directive: bool, optional Interpret `datefmt` as a format string for `datetime.datetime.strftime`, rather than `time.strftime`. See https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior . This also supports a custom %F directive for milliseconds. + use_rfc3339: bool, optional + Whether to use a popular date format that complies with both RFC3339 and ISO8601. + e.g., 2022-10-27T16:27:43.738+02:00. json_serializer : Callable, optional function to serialize `obj` to a JSON formatted `str`, by default json.dumps json_deserializer : Callable, optional @@ -187,6 +200,14 @@ def __init__( stream: Optional[IO[str]] = None, logger_formatter: Optional[PowertoolsFormatter] = None, logger_handler: Optional[logging.Handler] = None, + json_serializer: Optional[Callable[[Dict], str]] = None, + json_deserializer: Optional[Callable[[Union[Dict, str, bool, int, float]], str]] = None, + json_default: Optional[Callable[[Any], Any]] = None, + datefmt: Optional[str] = None, + use_datetime_directive: bool = False, + log_record_order: Optional[List[str]] = None, + utc: bool = False, + use_rfc3339: bool = False, **kwargs, ): self.service = resolve_env_var_choice( @@ -205,7 +226,20 @@ def __init__( self._default_log_keys = {"service": self.service, "sampling_rate": self.sampling_rate} self._logger = self._get_logger() - self._init_logger(**kwargs) + # NOTE: This is primarily to improve UX, so IDEs can autocomplete LambdaPowertoolsFormatter options + # previously, we masked all of them as kwargs thus limiting feature discovery + formatter_options = { + "json_serializer": json_serializer, + "json_deserializer": json_deserializer, + "json_default": json_default, + "datefmt": datefmt, + "use_datetime_directive": use_datetime_directive, + "log_record_order": log_record_order, + "utc": utc, + "use_rfc3339": use_rfc3339, + } + + self._init_logger(formatter_options=formatter_options, **kwargs) def __getattr__(self, name): # Proxy attributes not found to actual logger to support backward compatibility @@ -220,7 +254,7 @@ def _get_logger(self): return logging.getLogger(logger_name) - def _init_logger(self, **kwargs): + def _init_logger(self, formatter_options: Optional[Dict] = None, **kwargs): """Configures new logger""" # Skip configuration if it's a child logger or a pre-configured logger @@ -235,7 +269,7 @@ def _init_logger(self, **kwargs): self._configure_sampling() self._logger.setLevel(self.log_level) self._logger.addHandler(self.logger_handler) - self.structure_logs(**kwargs) + self.structure_logs(formatter_options=formatter_options, **kwargs) # Maintenance: We can drop this upon Py3.7 EOL. It's a backport for "location" key to work self._logger.findCaller = self.findCaller @@ -501,11 +535,11 @@ def registered_formatter(self) -> BasePowertoolsFormatter: """Convenience property to access logger formatter""" return self.registered_handler.formatter # type: ignore - def structure_logs(self, append: bool = False, **keys): + def structure_logs(self, append: bool = False, formatter_options: Optional[Dict] = None, **keys): """Sets logging formatting to JSON. Optionally, it can append keyword arguments - to an existing logger so it is available across future log statements. + to an existing logger, so it is available across future log statements. Last keyword argument and value wins if duplicated. @@ -513,7 +547,11 @@ def structure_logs(self, append: bool = False, **keys): ---------- append : bool, optional append keys provided to logger formatter, by default False + formatter_options : dict, optional + LambdaPowertoolsFormatter options to be propagated, by default {} """ + formatter_options = formatter_options or {} + # There are 3 operational modes for this method ## 1. Register a Powertools Formatter for the first time ## 2. Append new keys to the current logger formatter; deprecated in favour of append_keys @@ -523,7 +561,7 @@ def structure_logs(self, append: bool = False, **keys): log_keys = {**self._default_log_keys, **keys} is_logger_preconfigured = getattr(self._logger, "init", False) if not is_logger_preconfigured: - formatter = self.logger_formatter or LambdaPowertoolsFormatter(**log_keys) # type: ignore + formatter = self.logger_formatter or LambdaPowertoolsFormatter(**formatter_options, **log_keys) # type: ignore # noqa: E501 self.registered_handler.setFormatter(formatter) # when using a custom Lambda Powertools Formatter diff --git a/docs/core/logger.md b/docs/core/logger.md index 8fc9da441ac..471186cba5b 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -291,6 +291,30 @@ Use `logger.exception` method to log contextual information about exceptions. Lo --8<-- "examples/logger/src/logging_exceptions_output.json" ``` +### Date formatting + +Logger uses Python's standard logging date format with the addition of timezone: `2021-05-03 11:47:12,494+0200`. + +You can easily change the date format using one of the following parameters: + +* **`datefmt`**. You can pass any [strftime format codes](https://strftime.org/){target="_blank"}. Use `%F` if you need milliseconds. +* **`use_rfc3339`**. This flag will use a format compliant with both RFC3339 and ISO8601: `2022-10-27T16:27:43.738+02:00` + +???+ tip "Prefer using [datetime string formats](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes){target="_blank"}?" + Use `use_datetime_directive` flag along with `datefmt` to instruct Logger to use `datetime` instead of `time.strftime`. + +=== "date_formatting.py" + + ```python hl_lines="5 8" + --8<-- "examples/logger/src/date_formatting.py" + ``` + +=== "date_formatting_output.json" + + ```json hl_lines="6 13" + --8<-- "examples/logger/src/date_formatting_output.json" + ``` + ## Advanced ### Built-in Correlation ID expressions @@ -451,24 +475,19 @@ Do this instead: #### Overriding Log records -???+ tip - Use `datefmt` for custom date formats - We honour standard [logging library string formats](https://docs.python.org/3/howto/logging.html#displaying-the-date-time-in-messages){target="_blank"}. - - Prefer using [datetime string formats](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes){target="_blank"}? Set `use_datetime_directive` at Logger constructor or at [Lambda Powertools Formatter](#lambdapowertoolsformatter). - You might want to continue to use the same date formatting style, or override `location` to display the `package.function_name:line_number` as you previously had. -Logger allows you to either change the format or suppress the following keys altogether at the initialization: `location`, `timestamp`, `level`, `xray_trace_id`. +Logger allows you to either change the format or suppress the following keys at initialization: `location`, `timestamp`, `xray_trace_id`. === "overriding_log_records.py" - ```python hl_lines="7 10" + ```python hl_lines="6 10" --8<-- "examples/logger/src/overriding_log_records.py" ``` === "overriding_log_records_output.json" - ```json hl_lines="3 5" + ```json hl_lines="4" --8<-- "examples/logger/src/overriding_log_records_output.json" ``` diff --git a/examples/logger/src/date_formatting.py b/examples/logger/src/date_formatting.py new file mode 100644 index 00000000000..edca29201ec --- /dev/null +++ b/examples/logger/src/date_formatting.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools import Logger + +date_format = "%m/%d/%Y %I:%M:%S %p" + +logger = Logger(service="payment", use_rfc3339=True) +logger.info("Collecting payment") + +logger_custom_format = Logger(service="loyalty", datefmt=date_format) +logger_custom_format.info("Calculating points") diff --git a/examples/logger/src/date_formatting_output.json b/examples/logger/src/date_formatting_output.json new file mode 100644 index 00000000000..2d5ba1dff88 --- /dev/null +++ b/examples/logger/src/date_formatting_output.json @@ -0,0 +1,16 @@ +[ + { + "level": "INFO", + "location": ":6", + "message": "Collecting payment", + "timestamp": "2022-10-28T14:35:03.210+02:00", + "service": "payment" + }, + { + "level": "INFO", + "location": ":9", + "message": "Calculating points", + "timestamp": "10/28/2022 02:35:03 PM", + "service": "loyalty" + } +] \ No newline at end of file diff --git a/examples/logger/src/overriding_log_records.py b/examples/logger/src/overriding_log_records.py index f32da431158..519d8ef2220 100644 --- a/examples/logger/src/overriding_log_records.py +++ b/examples/logger/src/overriding_log_records.py @@ -1,12 +1,11 @@ from aws_lambda_powertools import Logger -date_format = "%m/%d/%Y %I:%M:%S %p" location_format = "[%(funcName)s] %(module)s" # override location and timestamp format -logger = Logger(service="payment", location=location_format, datefmt=date_format) - -# suppress the location key with a None value -logger_two = Logger(service="payment", location=None) - +logger = Logger(service="payment", location=location_format) logger.info("Collecting payment") + +# suppress keys with a None value +logger_two = Logger(service="loyalty", location=None) +logger_two.info("Calculating points") diff --git a/examples/logger/src/overriding_log_records_output.json b/examples/logger/src/overriding_log_records_output.json index ba2f1dfe8d5..676f36ca298 100644 --- a/examples/logger/src/overriding_log_records_output.json +++ b/examples/logger/src/overriding_log_records_output.json @@ -1,7 +1,15 @@ -{ - "level": "INFO", - "location": "[] lambda_handler", - "message": "Collecting payment", - "timestamp": "02/09/2021 09:25:17 AM", - "service": "payment" -} +[ + { + "level": "INFO", + "location": "[] overriding_log_records", + "message": "Collecting payment", + "timestamp": "2022-10-28 14:40:43,801+0200", + "service": "payment" + }, + { + "level": "INFO", + "message": "Calculating points", + "timestamp": "2022-10-28 14:40:43,801+0200", + "service": "loyalty" + } +] \ No newline at end of file diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index 4876da5cacf..f171ba7ee5b 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -814,6 +814,21 @@ def test_use_datetime(stdout, service_name, utc): ) +@pytest.mark.parametrize("utc", [False, True]) +def test_use_rfc3339_iso8601(stdout, service_name, utc): + # GIVEN + logger = Logger(service=service_name, stream=stdout, use_rfc3339=True, utc=utc) + RFC3339_REGEX = r"^((?:(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?))(Z|[\+-]\d{2}:\d{2})?)$" + + # WHEN a log statement happens + logger.info({}) + + # THEN the timestamp has the appropriate formatting + log = capture_logging_output(stdout) + + assert re.fullmatch(RFC3339_REGEX, log["timestamp"]) # "2022-10-27T17:42:26.841+0200" + + def test_inject_lambda_context_log_event_request_data_classes(lambda_context, stdout, lambda_event, service_name): # GIVEN Logger is initialized logger = Logger(service=service_name, stream=stdout) From bdd1a4b67506a64c60158a11b9563d3d1b8c899e Mon Sep 17 00:00:00 2001 From: Release bot Date: Fri, 28 Oct 2022 13:58:42 +0000 Subject: [PATCH 33/38] update changelog with latest changes --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 943f8c5bc79..ce6c26fa574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,13 @@ * **ci:** linting issues after flake8-blackbear,mypy upgrades * **deps:** update build system to poetry-core ([#1651](https://github.com/awslabs/aws-lambda-powertools-python/issues/1651)) +* **idempotency:** idempotent_function should support standalone falsy values ([#1669](https://github.com/awslabs/aws-lambda-powertools-python/issues/1669)) ## Documentation * **community:** fix social handlers for Ran ([#1654](https://github.com/awslabs/aws-lambda-powertools-python/issues/1654)) * **community:** fix twitch parent domain for embedded video +* **homepage:** remove 3.6 and add hero image * **homepage:** add Pulumi code example ([#1652](https://github.com/awslabs/aws-lambda-powertools-python/issues/1652)) * **index:** fold support us banner * **index:** add quotes to pip for zsh customers @@ -22,6 +24,7 @@ ## Features * **layers:** add layer balancer script ([#1643](https://github.com/awslabs/aws-lambda-powertools-python/issues/1643)) +* **logger:** add use_rfc3339 and auto-complete formatter opts in Logger ([#1662](https://github.com/awslabs/aws-lambda-powertools-python/issues/1662)) * **logger:** accept arbitrary keyword=value for ephemeral metadata ([#1658](https://github.com/awslabs/aws-lambda-powertools-python/issues/1658)) ## Maintenance @@ -29,6 +32,7 @@ * **ci:** fix typo on version description * **deps:** bump docker/setup-qemu-action from 2.0.0 to 2.1.0 ([#1627](https://github.com/awslabs/aws-lambda-powertools-python/issues/1627)) * **deps:** bump peaceiris/actions-gh-pages from 3.8.0 to 3.9.0 ([#1649](https://github.com/awslabs/aws-lambda-powertools-python/issues/1649)) +* **deps-dev:** bump aws-cdk-lib from 2.47.0 to 2.48.0 ([#1664](https://github.com/awslabs/aws-lambda-powertools-python/issues/1664)) * **deps-dev:** bump flake8-variables-names from 0.0.4 to 0.0.5 ([#1628](https://github.com/awslabs/aws-lambda-powertools-python/issues/1628)) * **deps-dev:** bump pytest-asyncio from 0.16.0 to 0.20.1 ([#1635](https://github.com/awslabs/aws-lambda-powertools-python/issues/1635)) * **docs:** remove v2 banner on top of the docs From f68d928acaf6a29afb780fdbf70f4b6eb9cb4d8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Oct 2022 20:23:13 +0000 Subject: [PATCH 34/38] chore(deps-dev): bump aws-cdk-lib from 2.48.0 to 2.49.0 (#1671) Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.48.0 to 2.49.0. - [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.48.0...v2.49.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 46da688c259..1ef3728253a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -45,7 +45,7 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.48.0" +version = "2.49.0" description = "Version 2 of the AWS Cloud Development Kit library" category = "dev" optional = false @@ -1511,7 +1511,7 @@ validation = ["fastjsonschema"] [metadata] lock-version = "1.1" python-versions = "^3.7.4" -content-hash = "a3c2ad13e7c73278094696ff3927e1195a108f2375d14163b70d852ec621fd94" +content-hash = "48a6c11b4ef71716e88efa7ffa474aa73fd7fcb02553ffd49c0d03fe72c1f838" [metadata.files] attrs = [ @@ -1527,8 +1527,8 @@ aws-cdk-aws-apigatewayv2-integrations-alpha = [ {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.47.0a0-py3-none-any.whl", hash = "sha256:4633c4e020400c7ee5790652f099f02d4f84bab24fff013250e2b41a4ffca1b0"}, ] aws-cdk-lib = [ - {file = "aws-cdk-lib-2.48.0.tar.gz", hash = "sha256:c419ffa6b07ea945477a55b2d58c73108b886a189c721d0b7c53337b285ceb16"}, - {file = "aws_cdk_lib-2.48.0-py3-none-any.whl", hash = "sha256:8ab509b294bb1e584f6e060f789d8d613a9f55b29faa55513a3345ea18b694d8"}, + {file = "aws-cdk-lib-2.49.0.tar.gz", hash = "sha256:9146f03988aff823cb5b561090875c311d733bf1786859c706381e9b49f6adb7"}, + {file = "aws_cdk_lib-2.49.0-py3-none-any.whl", hash = "sha256:c9c197463e2685aa67248c2cea2a4d3f15e33a3c19250aa34e754e455295417b"}, ] aws-sam-translator = [ {file = "aws-sam-translator-1.53.0.tar.gz", hash = "sha256:392ed4f5fb08f72cb68a8800f0bc278d2a3b6609bd1ac66bfcdeaaa94cdc18e5"}, diff --git a/pyproject.toml b/pyproject.toml index 0d142720ee3..cddceb2388d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" retry = "^0.9.2" pytest-xdist = "^2.5.0" -aws-cdk-lib = "^2.48.0" +aws-cdk-lib = "^2.49.0" "aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^3.4.1" From 1d6ca2dd001f82410c5044ec55223936a1d98a59 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 31 Oct 2022 10:47:23 +0100 Subject: [PATCH 35/38] chore(governance): remove 'area/' from PR labels --- .github/boring-cyborg.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml index 38760c85de6..325cd7c4ebc 100644 --- a/.github/boring-cyborg.yml +++ b/.github/boring-cyborg.yml @@ -1,48 +1,48 @@ ##### Labeler ########################################################################################################## labelPRBasedOnFilePath: - area/logger: + logger: - aws_lambda_powertools/logging/* - aws_lambda_powertools/logging/**/* - aws_lambda_powertools/package_logger.py - area/tracer: + tracer: - aws_lambda_powertools/tracing/* - aws_lambda_powertools/tracing/**/* - area/metrics: + metrics: - aws_lambda_powertools/metrics/* - aws_lambda_powertools/metrics/**/* - area/event_handlers: + event_handlers: - aws_lambda_powertools/event_handler/* - aws_lambda_powertools/event_handler/**/* - area/middleware_factory: + middleware_factory: - aws_lambda_powertools/middleware_factory/* - aws_lambda_powertools/middleware_factory/**/* - area/parameters: + parameters: - aws_lambda_powertools/parameters/* - aws_lambda_powertools/parameters/**/* - area/batch: + batch: - aws_lambda_powertools/batch/* - aws_lambda_powertools/batch/**/* - area/validator: + validator: - aws_lambda_powertools/validation/* - aws_lambda_powertools/validation/**/* - area/event_sources: + event_sources: - aws_lambda_powertools/data_classes/* - aws_lambda_powertools/data_classes/**/* - area/parser: + parser: - aws_lambda_powertools/parser/* - aws_lambda_powertools/parser/**/* - area/idempotency: + idempotency: - aws_lambda_powertools/idempotency/* - aws_lambda_powertools/idempotency/**/* - area/feature_flags: + feature_flags: - aws_lambda_powertools/feature_flags/* - aws_lambda_powertools/feature_flags/**/* - area/jmespath: + jmespath: - aws_lambda_powertools/utilities/jmespath_utils/* - area/typing: + typing: - aws_lambda_powertools/utilities/typing/* - mypy.ini - area/commons: + commons: - aws_lambda_powertools/shared/* documentation: From 2798da194e54181cfc3db9f56a7ff11406defb20 Mon Sep 17 00:00:00 2001 From: nayaverdier Date: Mon, 31 Oct 2022 02:49:10 -0700 Subject: [PATCH 36/38] fix(logger): fix unknown attributes being ignored by mypy (#1670) --- aws_lambda_powertools/logging/logger.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py index be30c098db4..b82c510036a 100644 --- a/aws_lambda_powertools/logging/logger.py +++ b/aws_lambda_powertools/logging/logger.py @@ -8,6 +8,7 @@ import traceback from typing import ( IO, + TYPE_CHECKING, Any, Callable, Dict, @@ -241,10 +242,14 @@ def __init__( self._init_logger(formatter_options=formatter_options, **kwargs) - def __getattr__(self, name): - # Proxy attributes not found to actual logger to support backward compatibility - # https://github.com/awslabs/aws-lambda-powertools-python/issues/97 - return getattr(self._logger, name) + # Prevent __getattr__ from shielding unknown attribute errors in type checkers + # https://github.com/awslabs/aws-lambda-powertools-python/issues/1660 + if not TYPE_CHECKING: + + def __getattr__(self, name): + # Proxy attributes not found to actual logger to support backward compatibility + # https://github.com/awslabs/aws-lambda-powertools-python/issues/97 + return getattr(self._logger, name) def _get_logger(self): """Returns a Logger named {self.service}, or {self.service.filename} for child loggers""" From 0638a13373d40c41f7697845f22404dade63402b Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 31 Oct 2022 10:19:02 +0000 Subject: [PATCH 37/38] update changelog with latest changes --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce6c26fa574..6a77b1f6bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * **ci:** linting issues after flake8-blackbear,mypy upgrades * **deps:** update build system to poetry-core ([#1651](https://github.com/awslabs/aws-lambda-powertools-python/issues/1651)) * **idempotency:** idempotent_function should support standalone falsy values ([#1669](https://github.com/awslabs/aws-lambda-powertools-python/issues/1669)) +* **logger:** fix unknown attributes being ignored by mypy ([#1670](https://github.com/awslabs/aws-lambda-powertools-python/issues/1670)) ## Documentation @@ -30,12 +31,14 @@ ## Maintenance * **ci:** fix typo on version description -* **deps:** bump docker/setup-qemu-action from 2.0.0 to 2.1.0 ([#1627](https://github.com/awslabs/aws-lambda-powertools-python/issues/1627)) * **deps:** bump peaceiris/actions-gh-pages from 3.8.0 to 3.9.0 ([#1649](https://github.com/awslabs/aws-lambda-powertools-python/issues/1649)) +* **deps:** bump docker/setup-qemu-action from 2.0.0 to 2.1.0 ([#1627](https://github.com/awslabs/aws-lambda-powertools-python/issues/1627)) * **deps-dev:** bump aws-cdk-lib from 2.47.0 to 2.48.0 ([#1664](https://github.com/awslabs/aws-lambda-powertools-python/issues/1664)) * **deps-dev:** bump flake8-variables-names from 0.0.4 to 0.0.5 ([#1628](https://github.com/awslabs/aws-lambda-powertools-python/issues/1628)) * **deps-dev:** bump pytest-asyncio from 0.16.0 to 0.20.1 ([#1635](https://github.com/awslabs/aws-lambda-powertools-python/issues/1635)) +* **deps-dev:** bump aws-cdk-lib from 2.48.0 to 2.49.0 ([#1671](https://github.com/awslabs/aws-lambda-powertools-python/issues/1671)) * **docs:** remove v2 banner on top of the docs +* **governance:** remove 'area/' from PR labels From 380a96d98d32a660b4629067e8f6005304516222 Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 31 Oct 2022 10:46:31 +0000 Subject: [PATCH 38/38] 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 8f199647e4f..2eb543f998c 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:11**](#){: .copyMe}:clipboard: -* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11**](#){: .copyMe}:clipboard: +* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:12**](#){: .copyMe}:clipboard: +* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12**](#){: .copyMe}:clipboard: * **PyPi**: **`pip install "aws-lambda-powertools"`** ???+ info "Some utilities require additional dependencies" @@ -67,55 +67,55 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:11](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:12](#){: .copyMe}:clipboard: | === "arm64" | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12](#){: .copyMe}:clipboard: | ??? note "Note: Click to expand and copy code snippets for popular frameworks" @@ -128,7 +128,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: Type: AWS::Serverless::Function Properties: Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:12 ``` === "Serverless framework" @@ -138,7 +138,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: hello: handler: lambda_function.lambda_handler layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:12 ``` === "CDK" @@ -154,7 +154,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: 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:11" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:12" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -203,7 +203,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:11"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:12"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } @@ -256,7 +256,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: ? 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:11 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12 ❯ amplify push -y @@ -267,7 +267,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: - 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:11 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:12 ? Do you want to edit the local lambda function now? No ``` @@ -276,7 +276,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: 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:11 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:12 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key. @@ -291,7 +291,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: Properties: Architectures: [arm64] Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12 ``` === "Serverless framework" @@ -302,7 +302,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12 ``` === "CDK" @@ -318,7 +318,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: 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:11" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -368,7 +368,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:11"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") @@ -424,7 +424,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: ? 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:11 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12 ❯ amplify push -y @@ -435,7 +435,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: - 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:11 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12 ? Do you want to edit the local lambda function now? No ``` @@ -443,7 +443,7 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: 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:11 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:12 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key.