From 6c1a4d2c9a23cd1c56d58ae5b12a62b3164be8ac Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Mon, 4 Jul 2022 13:44:34 +0200 Subject: [PATCH 01/30] fix(logger): preserve std keys when using custom formatters (#1264) --- aws_lambda_powertools/logging/formatter.py | 5 ++++ aws_lambda_powertools/logging/logger.py | 16 +++++++--- tests/functional/test_logger.py | 34 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/aws_lambda_powertools/logging/formatter.py b/aws_lambda_powertools/logging/formatter.py index becfc9de85c..1f01015051c 100644 --- a/aws_lambda_powertools/logging/formatter.py +++ b/aws_lambda_powertools/logging/formatter.py @@ -1,3 +1,4 @@ +import inspect import json import logging import os @@ -286,3 +287,7 @@ def _strip_none_records(records: Dict[str, Any]) -> Dict[str, Any]: JsonFormatter = LambdaPowertoolsFormatter # alias to previous formatter + + +# Fetch current and future parameters from PowertoolsFormatter that should be reserved +RESERVED_FORMATTER_CUSTOM_KEYS: List[str] = inspect.getfullargspec(LambdaPowertoolsFormatter).args[1:] diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py index 157d53adf7e..f70224cabae 100644 --- a/aws_lambda_powertools/logging/logger.py +++ b/aws_lambda_powertools/logging/logger.py @@ -12,7 +12,7 @@ from ..shared.functions import resolve_env_var_choice, resolve_truthy_env_var_choice from .exceptions import InvalidLoggerSamplingRateError from .filters import SuppressFilter -from .formatter import BasePowertoolsFormatter, LambdaPowertoolsFormatter +from .formatter import RESERVED_FORMATTER_CUSTOM_KEYS, BasePowertoolsFormatter, LambdaPowertoolsFormatter from .lambda_context import build_lambda_context_model logger = logging.getLogger(__name__) @@ -82,7 +82,7 @@ class Logger(logging.Logger): # lgtm [py/missing-call-to-init] datefmt: str, optional String directives (strftime) to format log timestamp using `time`, by default it uses RFC 3339. - use_datetime_directive: str, optional + use_datetime_directive: bool, optional Interpret `datefmt` as a format string for `datetime.datetime.strftime`, rather than `time.strftime`. @@ -368,7 +368,7 @@ def registered_handler(self) -> logging.Handler: return handlers[0] @property - def registered_formatter(self) -> PowertoolsFormatter: + def registered_formatter(self) -> BasePowertoolsFormatter: """Convenience property to access logger formatter""" return self.registered_handler.formatter # type: ignore @@ -395,7 +395,15 @@ def structure_logs(self, append: bool = False, **keys): is_logger_preconfigured = getattr(self._logger, "init", False) if not is_logger_preconfigured: formatter = self.logger_formatter or LambdaPowertoolsFormatter(**log_keys) # type: ignore - return self.registered_handler.setFormatter(formatter) + self.registered_handler.setFormatter(formatter) + + # when using a custom Lambda Powertools Formatter + # standard and custom keys that are not Powertools Formatter parameters should be appended + # and custom keys that might happen to be Powertools Formatter parameters should be discarded + # this prevents adding them as custom keys, for example, `json_default=` + # see https://github.com/awslabs/aws-lambda-powertools-python/issues/1263 + custom_keys = {k: v for k, v in log_keys.items() if k not in RESERVED_FORMATTER_CUSTOM_KEYS} + return self.registered_formatter.append_keys(**custom_keys) # Mode 2 (legacy) if append: diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index c76faa7cde5..c8b3dc61755 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -625,6 +625,40 @@ def handler(event, context): assert all(k in second_log for k in lambda_context_keys) +def test_logger_custom_formatter_has_standard_and_custom_keys(stdout, service_name, lambda_context): + class CustomFormatter(LambdaPowertoolsFormatter): + ... + + # GIVEN a Logger is initialized with a custom formatter + logger = Logger(service=service_name, stream=stdout, logger_formatter=CustomFormatter(), my_key="value") + + # WHEN a lambda function is decorated with logger + @logger.inject_lambda_context + def handler(event, context): + logger.info("Hello") + + handler({}, lambda_context) + + standard_keys = ( + "level", + "location", + "message", + "timestamp", + "service", + "cold_start", + "function_name", + "function_memory_size", + "function_arn", + "function_request_id", + ) + + log = capture_logging_output(stdout) + + # THEN all standard keys should be available + assert all(k in log for k in standard_keys) + assert "my_key" in log + + def test_logger_custom_handler(lambda_context, service_name, tmp_path): # GIVEN a Logger is initialized with a FileHandler log_file = tmp_path / "log.json" From c6de9c1e56889cbff1b68850e04a0f9eebbbbdd3 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 4 Jul 2022 14:46:37 +0200 Subject: [PATCH 02/30] fix(ci): checkout project before validating related issue workflow --- .github/workflows/on_merged_pr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/on_merged_pr.yml b/.github/workflows/on_merged_pr.yml index 97029740cdb..70f43daab3b 100644 --- a/.github/workflows/on_merged_pr.yml +++ b/.github/workflows/on_merged_pr.yml @@ -18,6 +18,7 @@ jobs: issues: write # required for new scoped token pull-requests: write # required for new scoped token steps: + - uses: actions/checkout@v3 - name: "Label PR related issue for release" uses: actions/github-script@v6 with: From 0f1f1cdb06de9355dcd4af3bac355fcdedac8df7 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 4 Jul 2022 17:05:32 +0200 Subject: [PATCH 03/30] chore(layers): bump to 22 for 1.26.3 --- docs/index.md | 58 +++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/index.md b/docs/index.md index cc3d437334e..5396ccb3f2e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -15,7 +15,7 @@ A suite of utilities for AWS Lambda functions to ease adopting best practices su Powertools is available in the following formats: -* **Lambda Layer**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:21**](#){: .copyMe}:clipboard: +* **Lambda Layer**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:22**](#){: .copyMe}:clipboard: * **PyPi**: **`pip install aws-lambda-powertools`** ???+ hint "Support this project by using Lambda Layers :heart:" @@ -33,23 +33,23 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: | Region | Layer ARN | | ---------------- | -------------------------------------------------------------------------------------------------------- | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPython:21](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPython:22](#){: .copyMe}:clipboard: | ??? question "Can't find our Lambda Layer for your preferred AWS region?" You can use [Serverless Application Repository (SAR)](#sar) method, our [CDK Layer Construct](https://github.com/aws-samples/cdk-lambda-powertools-python-layer){target="_blank"}, or PyPi like you normally would for any other library. @@ -63,7 +63,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:AWSLambdaPowertoolsPython:21 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:22 ``` === "Serverless framework" @@ -73,7 +73,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:AWSLambdaPowertoolsPython:21 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPython:22 ``` === "CDK" @@ -89,7 +89,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:AWSLambdaPowertoolsPython:21" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPython:22" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -138,7 +138,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:AWSLambdaPowertoolsPython:21"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:22"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } @@ -157,7 +157,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:AWSLambdaPowertoolsPython:21 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPython:22 ❯ amplify push -y @@ -168,7 +168,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:AWSLambdaPowertoolsPython:21 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPython:22 ? Do you want to edit the local lambda function now? No ``` @@ -176,7 +176,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:AWSLambdaPowertoolsPython:21 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:22 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key. @@ -214,7 +214,7 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, Properties: Location: ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer - SemanticVersion: 1.25.10 # change to latest semantic version available in SAR + SemanticVersion: 1.26.3 # change to latest semantic version available in SAR MyLambdaFunction: Type: AWS::Serverless::Function @@ -242,7 +242,7 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, 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: 1.25.10 + SemanticVersion: 1.26.3 ``` === "CDK" @@ -252,7 +252,7 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, POWERTOOLS_BASE_NAME = 'AWSLambdaPowertools' # Find latest from github.com/awslabs/aws-lambda-powertools-python/releases - POWERTOOLS_VER = '1.23.0' + POWERTOOLS_VER = '1.26.3' POWERTOOLS_ARN = 'arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer' class SampleApp(core.Construct): @@ -316,7 +316,7 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, variable "aws_powertools_version" { type = string - default = "1.20.2" + default = "1.26.3" description = "The AWS Powertools release version" } From 89d33d376e54d7a414af23a533290a960da6f3d7 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 4 Jul 2022 17:10:45 +0200 Subject: [PATCH 04/30] chore(ci): limits concurrency for docs workflow --- .github/workflows/python_docs.yml | 4 ++ .github/workflows/rebuild_latest_docs.yml | 88 ++++++++++++----------- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/.github/workflows/python_docs.yml b/.github/workflows/python_docs.yml index 3a6e15e5431..d7ae6c2cc52 100644 --- a/.github/workflows/python_docs.yml +++ b/.github/workflows/python_docs.yml @@ -12,6 +12,10 @@ on: jobs: docs: + # Force Github action to run only a single job at a time (based on the group name) + # This is to prevent "race-condition" in publishing a new version of doc to `gh-pages` + concurrency: + group: on-docs-build runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/rebuild_latest_docs.yml b/.github/workflows/rebuild_latest_docs.yml index b185556f2ff..92cb8a3635d 100644 --- a/.github/workflows/rebuild_latest_docs.yml +++ b/.github/workflows/rebuild_latest_docs.yml @@ -7,56 +7,58 @@ name: Rebuild latest docs # 2. Use the latest version released under Releases e.g. v1.22.0 # 3. Set `Build and publish docs only` field to `true` - on: workflow_dispatch: inputs: latest_published_version: - description: 'Latest PyPi published version to rebuild latest docs for, e.g. v1.22.0' - default: 'v1.22.0' + description: "Latest PyPi published version to rebuild latest docs for, e.g. v1.22.0" + default: "v1.22.0" required: true - jobs: release: + # Force Github action to run only a single job at a time (based on the group name) + # This is to prevent "race-condition" in publishing a new version of doc to `gh-pages` + concurrency: + group: on-docs-rebuild runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.8" - - name: Set release notes tag - run: | - RELEASE_TAG_VERSION=${{ github.event.inputs.latest_published_version }} - echo "RELEASE_TAG_VERSION=${RELEASE_TAG_VERSION:1}" >> $GITHUB_ENV - - name: Ensure new version is also set in pyproject and CHANGELOG - run: | - grep --regexp "${RELEASE_TAG_VERSION}" CHANGELOG.md - grep --regexp "version \= \"${RELEASE_TAG_VERSION}\"" pyproject.toml - - name: Install dependencies - run: make dev - - name: Setup doc deploy - run: | - git config --global user.name Docs deploy - git config --global user.email aws-devax-open-source@amazon.com - - name: Build docs website and API reference - run: | - make release-docs VERSION=${RELEASE_TAG_VERSION} ALIAS="latest" - poetry run mike set-default --push latest - - name: Release API docs to release version - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./api - keep_files: true - destination_dir: ${{ env.RELEASE_TAG_VERSION }}/api - - name: Release API docs to latest - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./api - keep_files: true - destination_dir: latest/api + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.8" + - name: Set release notes tag + run: | + RELEASE_TAG_VERSION=${{ github.event.inputs.latest_published_version }} + echo "RELEASE_TAG_VERSION=${RELEASE_TAG_VERSION:1}" >> $GITHUB_ENV + - name: Ensure new version is also set in pyproject and CHANGELOG + run: | + grep --regexp "${RELEASE_TAG_VERSION}" CHANGELOG.md + grep --regexp "version \= \"${RELEASE_TAG_VERSION}\"" pyproject.toml + - name: Install dependencies + run: make dev + - name: Setup doc deploy + run: | + git config --global user.name Docs deploy + git config --global user.email aws-devax-open-source@amazon.com + - name: Build docs website and API reference + run: | + make release-docs VERSION=${RELEASE_TAG_VERSION} ALIAS="latest" + poetry run mike set-default --push latest + - name: Release API docs to release version + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./api + keep_files: true + destination_dir: ${{ env.RELEASE_TAG_VERSION }}/api + - name: Release API docs to latest + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./api + keep_files: true + destination_dir: latest/api From c0bb85f341a4e98a5a19e1f27f824166974b66a8 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 5 Jul 2022 12:16:35 +0200 Subject: [PATCH 05/30] fix(ci): regex to catch combination of related issues workflow --- .github/scripts/label_related_issue.js | 31 +++++++++++++------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/.github/scripts/label_related_issue.js b/.github/scripts/label_related_issue.js index 1953412ae41..8f851056cb3 100644 --- a/.github/scripts/label_related_issue.js +++ b/.github/scripts/label_related_issue.js @@ -4,27 +4,26 @@ module.exports = async ({github, context}) => { const releaseLabel = process.env.RELEASE_LABEL; const maintainersTeam = process.env.MAINTAINERS_TEAM - const RELATED_ISSUE_REGEX = /Issue number:.+(\d)/ + const RELATED_ISSUE_REGEX = /Issue number:[^\d\r\n]+(?\d+)/; - const matcher = new RegExp(RELATED_ISSUE_REGEX) - const isMatch = matcher.exec(prBody) - if (isMatch != null) { - let relatedIssueNumber = isMatch[1] - console.info(`Auto-labeling related issue ${relatedIssueNumber} for release`) - - return await github.rest.issues.addLabels({ - issue_number: relatedIssueNumber, - owner: context.repo.owner, - repo: context.repo.repo, - labels: [releaseLabel] - }) - } else { - let msg = `${maintainersTeam} No related issues found. Please ensure '${releaseLabel}' label is applied before releasing.`; + const isMatch = RELATED_ISSUE_REGEX.exec(body); + if (!isMatch) { + core.setFailed(`Unable to find related issue for PR number ${prNumber}.\n\n Body details: ${prBody}`); return await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, - body: msg, + body: `${maintainersTeam} No related issues found. Please ensure '${releaseLabel}' label is applied before releasing.`, issue_number: prNumber, }); } + + const { groups: {relatedIssueNumber} } = isMatch + + core.info(`Auto-labeling related issue ${relatedIssueNumber} for release`) + return await github.rest.issues.addLabels({ + issue_number: relatedIssueNumber, + owner: context.repo.owner, + repo: context.repo.repo, + labels: [releaseLabel] + }) } From 1f570a62aaffbb7c4c4434404c7086ebede2ab37 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 12:54:00 +0200 Subject: [PATCH 06/30] chore(layers): add release pipeline in GitHub Actions (#1278) * chore: add layer project * reduce to 1 region for dev * chore: shorter name for the workflow * fix ignore markdown lint for now * fix: more f strings * ignore mdlint * add reusable workflow for both beta and prod * Update layer/layer/canary/app.py Co-authored-by: Heitor Lessa * Update layer/layer/canary/app.py Co-authored-by: Heitor Lessa * readme review * rephrase canary stack ssm parameter usage * add default RELEASE_TAG_VERSION assignment based on the input (release or manual trigger) * add reference to layer docs * wording * move version trackign arn to canary stack * remove outdated npm caching, add release tag resolution for manual workflow trigger * review: fix layer name and remove dependencies from reusable workflow * remove debug statement, add default working dir * pin versions and hashes for requirements with pip-compile * rename reusable workflow * pass artefact name to the reusable workflow to prevent potential future conflicts Co-authored-by: Heitor Lessa --- .github/workflows/publish_layer.yml | 80 +++++++++++++++ .../workflows/reusable_deploy_layer_stack.yml | 87 ++++++++++++++++ layer/.gitignore | 10 ++ layer/README.md | 27 +++++ layer/app.py | 23 +++++ layer/cdk.json | 35 +++++++ layer/layer/__init__.py | 0 layer/layer/canary/app.py | 99 +++++++++++++++++++ layer/layer/canary_stack.py | 75 ++++++++++++++ layer/layer/layer_stack.py | 19 ++++ layer/requirements-dev.txt | 2 + layer/requirements.txt | 76 ++++++++++++++ 12 files changed, 533 insertions(+) create mode 100644 .github/workflows/publish_layer.yml create mode 100644 .github/workflows/reusable_deploy_layer_stack.yml create mode 100644 layer/.gitignore create mode 100644 layer/README.md create mode 100644 layer/app.py create mode 100644 layer/cdk.json create mode 100644 layer/layer/__init__.py create mode 100644 layer/layer/canary/app.py create mode 100644 layer/layer/canary_stack.py create mode 100644 layer/layer/layer_stack.py create mode 100644 layer/requirements-dev.txt create mode 100644 layer/requirements.txt diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml new file mode 100644 index 00000000000..d4001e0bdce --- /dev/null +++ b/.github/workflows/publish_layer.yml @@ -0,0 +1,80 @@ +name: Deploy layer to all regions + +permissions: + id-token: write + contents: read + +on: + workflow_dispatch: + inputs: + latest_published_version: + description: "Latest PyPi published version to rebuild latest docs for, e.g. v1.22.0" + default: "v1.22.0" + required: true + workflow_run: + workflows: [ "Publish to PyPi" ] + types: + - completed + + +jobs: + build-layer: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./layer + steps: + - name: checkout + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16.12' + cache: 'npm' + - name: Setup python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + cache: 'pip' + - name: Set release notes tag + run: | + RELEASE_INPUT=${{ inputs.latest_published_version }} + GITHUB_EVENT_RELEASE_TAG=${{ github.event.release.tag_name }} + RELEASE_TAG_VERSION=${GITHUB_EVENT_RELEASE_TAG:-$RELEASE_INPUT} + echo "RELEASE_TAG_VERSION=${RELEASE_TAG_VERSION:1}" >> $GITHUB_ENV + - name: install cdk and deps + run: | + npm install -g aws-cdk@2.29.0 + cdk --version + - name: install deps + run: | + pip install -r requirements.txt + - name: CDK build + run: cdk synth --context version=$RELEASE_TAG_VERSION -o cdk.out + - name: zip output + run: zip -r cdk.out.zip cdk.out + - name: Archive CDK artifacts + uses: actions/upload-artifact@v3 + with: + name: cdk-layer-artefact + path: cdk.out.zip + + deploy-beta: + needs: + - build-layer + uses: ./.github/workflows/reusable_deploy_layer_stack.yml + with: + stage: "BETA" + artifact-name: "cdk-layer-artefact" + secrets: + target-account: ${{ secrets.LAYERS_BETA_ACCOUNT }} + + deploy-prod: + needs: + - deploy-beta + uses: ./.github/workflows/reusable_deploy_layer_stack.yml + with: + stage: "PROD" + artifact-name: "cdk-layer-artefact" + secrets: + target-account: ${{ secrets.LAYERS_PROD_ACCOUNT }} diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml new file mode 100644 index 00000000000..f31449e7ba6 --- /dev/null +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -0,0 +1,87 @@ +name: Deploy cdk stack + +permissions: + id-token: write + contents: read + +on: + workflow_call: + inputs: + stage: + required: true + type: string + artefact-name: + required: true + type: string + secrets: + target-account: + required: true + +jobs: + deploy-cdk-stack: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./layer + strategy: + fail-fast: false + matrix: + region: [ + "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" + ] + steps: + - name: checkout + uses: actions/checkout@v2 + - name: aws credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-region: ${{ matrix.region }} + role-to-assume: arn:aws:iam::${{ secrets.target-account }}:role/${{ secrets.AWS_GITHUB_OIDC_ROLE }} + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16.12' + cache: 'npm' + - name: Setup python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + cache: 'pip' + - name: install cdk and deps + run: | + npm install -g aws-cdk@2.29.0 + cdk --version + - name: install deps + run: | + pip install -r requirements.txt + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: ${{ inputs.artefact-name }} + - name: unzip artefact + run: unzip cdk.out.zip + - name: CDK Deploy Layer + run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerStack ' --require-approval never --verbose + - name: CDK Deploy Canary + run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="${{ input.stage }}" 'CanaryStack' --require-approval never --verbose diff --git a/layer/.gitignore b/layer/.gitignore new file mode 100644 index 00000000000..37833f8beb2 --- /dev/null +++ b/layer/.gitignore @@ -0,0 +1,10 @@ +*.swp +package-lock.json +__pycache__ +.pytest_cache +.venv +*.egg-info + +# CDK asset staging directory +.cdk.staging +cdk.out diff --git a/layer/README.md b/layer/README.md new file mode 100644 index 00000000000..99da0083ffc --- /dev/null +++ b/layer/README.md @@ -0,0 +1,27 @@ + +# CDK Powertools layer + +This is a CDK project to build and deploy AWS Lambda Powertools [Lambda layer](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-concepts.html#gettingstarted-concepts-layer) to multiple commercial regions. + +## Build the layer + +To build the layer construct you need to provide the Powertools version that is [available in PyPi](https://pypi.org/project/aws-lambda-powertools/). +You can pass it as a context variable when running `synth` or `deploy`, + +```shell +cdk synth --context version=1.25.1 +``` + +## Canary stack + +We use a canary stack to verify that the deployment is successful and we can use the layer by adding it to a newly created Lambda function. +The canary is deployed after the layer construct. Because the layer ARN is created during the deploy we need to pass this information async via SSM parameter. +To achieve that we use SSM parameter store to pass the layer ARN to the canary. +The layer stack writes the layer ARN after the deployment as SSM parameter and the canary stacks reads this information and adds the layer to the function. + +## Version tracking + +AWS Lambda versions Lambda layers by incrementing a number at the end of the ARN. +This makes it challenging to know which Powertools version a layer contains. +For better tracking of the ARNs and the corresponding version we need to keep track which powertools version was deployed to which layer. +To achieve that we created two components. First, we created a version tracking app which receives events via EventBridge. Second, after a successful canary deployment we send the layer ARN, Powertools version, and the region to this EventBridge. diff --git a/layer/app.py b/layer/app.py new file mode 100644 index 00000000000..78e99b17654 --- /dev/null +++ b/layer/app.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +import aws_cdk as cdk + +from layer.canary_stack import CanaryStack +from layer.layer_stack import LayerStack + +app = cdk.App() + +POWERTOOLS_VERSION: str = app.node.try_get_context("version") +SSM_PARAM_LAYER_ARN: str = "/layers/powertools-layer-arn" + +if not POWERTOOLS_VERSION: + raise ValueError( + "Please set the version for Powertools by passing the '--context=version:' parameter to the CDK " + "synth step." + ) + +LayerStack(app, "LayerStack", powertools_version=POWERTOOLS_VERSION, ssm_paramter_layer_arn=SSM_PARAM_LAYER_ARN) + +CanaryStack(app, "CanaryStack", powertools_version=POWERTOOLS_VERSION, ssm_paramter_layer_arn=SSM_PARAM_LAYER_ARN) + +app.synth() diff --git a/layer/cdk.json b/layer/cdk.json new file mode 100644 index 00000000000..c120c5f4765 --- /dev/null +++ b/layer/cdk.json @@ -0,0 +1,35 @@ +{ + "app": "python3 app.py", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "requirements*.txt", + "source.bat", + "**/__init__.py", + "python/__pycache__", + "tests" + ] + }, + "context": { + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, + "@aws-cdk/core:stackRelativeExports": true, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, + "@aws-cdk/aws-lambda:recognizeVersionProps": true, + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ] + } +} diff --git a/layer/layer/__init__.py b/layer/layer/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/layer/layer/canary/app.py b/layer/layer/canary/app.py new file mode 100644 index 00000000000..31db94dd92b --- /dev/null +++ b/layer/layer/canary/app.py @@ -0,0 +1,99 @@ +import datetime +import json +import os +from importlib.metadata import version + +import boto3 + +from aws_lambda_powertools import Logger, Metrics, Tracer + +logger = Logger(service="version-track") +tracer = Tracer() +metrics = Metrics(namespace="powertools-layer-canary", service="PowertoolsLayerCanary") + +layer_arn = os.getenv("POWERTOOLS_LAYER_ARN") +powertools_version = os.getenv("POWERTOOLS_VERSION") +stage = os.getenv("LAYER_PIPELINE_STAGE") +event_bus_arn = os.getenv("VERSION_TRACKING_EVENT_BUS_ARN") + + +def handler(event): + logger.info("Running checks") + check_envs() + verify_powertools_version() + send_notification() + return True + + +@logger.inject_lambda_context(log_event=True) +def on_event(event, context): + request_type = event["RequestType"] + # we handle only create events, because we recreate the canary on each run + if request_type == "Create": + return on_create(event) + + return "Nothing to be processed" + + +def on_create(event): + props = event["ResourceProperties"] + logger.info("create new resource with properties %s" % props) + handler(event) + + +def check_envs(): + logger.info('Checking required envs ["POWERTOOLS_LAYER_ARN", "AWS_REGION", "STAGE"]') + if not layer_arn: + raise ValueError("POWERTOOLS_LAYER_ARN is not set. Aborting...") + if not powertools_version: + raise ValueError("POWERTOOLS_VERSION is not set. Aborting...") + if not stage: + raise ValueError("LAYER_PIPELINE_STAGE is not set. Aborting...") + if not event_bus_arn: + raise ValueError("VERSION_TRACKING_EVENT_BUS_ARN is not set. Aborting...") + logger.info("All envs configured, continue...") + + +def verify_powertools_version() -> None: + """ + fetches the version that we import from the powertools layer and compares + it with expected version set in environment variable, which we pass during deployment. + :raise ValueError if the expected version is not the same as the version we get from the layer + """ + logger.info("Checking Powertools version in library...") + current_version = version("aws_lambda_powertools") + if powertools_version != current_version: + raise ValueError( + f'Expected powertoosl version is "{powertools_version}", but layer contains version "{current_version}"' + ) + logger.info(f"Current Powertools version is: {current_version}") + + +def send_notification(): + """ + sends an event to version tracking event bridge + """ + event = { + "Time": datetime.datetime.now(), + "Source": "powertools.layer.canary", + "EventBusName": event_bus_arn, + "DetailType": "deployment", + "Detail": json.dumps( + { + "id": "powertools-python", + "stage": stage, + "region": os.environ["AWS_REGION"], + "version": powertools_version, + "layerArn": layer_arn, + } + ), + } + + logger.info(f"sending notification event: {event}") + + client = boto3.client("events", region_name="eu-central-1") + resp = client.put_events(Entries=[event]) + logger.info(resp) + if resp["FailedEntryCount"] != 0: + logger.error(resp) + raise ValueError("Failed to send deployment notification to version tracking") diff --git a/layer/layer/canary_stack.py b/layer/layer/canary_stack.py new file mode 100644 index 00000000000..15bc80214d3 --- /dev/null +++ b/layer/layer/canary_stack.py @@ -0,0 +1,75 @@ +import uuid + +from aws_cdk import CfnParameter, CustomResource, Duration, Stack +from aws_cdk.aws_iam import Effect, ManagedPolicy, PolicyStatement, Role, ServicePrincipal +from aws_cdk.aws_lambda import Code, Function, LayerVersion, Runtime +from aws_cdk.aws_logs import RetentionDays +from aws_cdk.aws_ssm import StringParameter +from aws_cdk.custom_resources import Provider +from constructs import Construct + + +class CanaryStack(Stack): + def __init__( + self, + scope: Construct, + construct_id: str, + powertools_version: str, + ssm_paramter_layer_arn: str, + **kwargs, + ) -> None: + super().__init__(scope, construct_id, **kwargs) + + VERSION_TRACKING_EVENT_BUS_ARN: str = ( + "arn:aws:events:eu-central-1:027876851704:event-bus/VersionTrackingEventBus" + ) + + layer_arn = StringParameter.from_string_parameter_attributes( + self, "LayerVersionArnParam", parameter_name=ssm_paramter_layer_arn + ).string_value + + layer = LayerVersion.from_layer_version_arn(self, "PowertoolsLayer", layer_version_arn=layer_arn) + deploy_stage = CfnParameter(self, "DeployStage", description="Deployment stage for canary").value_as_string + + execution_role = Role(self, "LambdaExecutionRole", assumed_by=ServicePrincipal("lambda.amazonaws.com")) + + execution_role.add_managed_policy( + ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole") + ) + + execution_role.add_to_policy( + PolicyStatement(effect=Effect.ALLOW, actions=["lambda:GetFunction"], resources=["*"]) + ) + + canary_lambda = Function( + self, + "CanaryLambdaFunction", + function_name="CanaryLambdaFunction", + code=Code.from_asset("layer/canary"), + handler="app.on_event", + layers=[layer], + memory_size=512, + timeout=Duration.seconds(10), + runtime=Runtime.PYTHON_3_9, + log_retention=RetentionDays.ONE_MONTH, + role=execution_role, + environment={ + "POWERTOOLS_VERSION": powertools_version, + "POWERTOOLS_LAYER_ARN": layer_arn, + "VERSION_TRACKING_EVENT_BUS_ARN": VERSION_TRACKING_EVENT_BUS_ARN, + "LAYER_PIPELINE_STAGE": deploy_stage, + }, + ) + + canary_lambda.add_to_role_policy( + PolicyStatement( + effect=Effect.ALLOW, actions=["events:PutEvents"], resources=[VERSION_TRACKING_EVENT_BUS_ARN] + ) + ) + + # custom resource provider configuration + provider = Provider( + self, "CanaryCustomResource", on_event_handler=canary_lambda, log_retention=RetentionDays.ONE_MONTH + ) + # force to recreate resource on each deployment with randomized name + CustomResource(self, f"CanaryTrigger-{str(uuid.uuid4())[0:7]}", service_token=provider.service_token) diff --git a/layer/layer/layer_stack.py b/layer/layer/layer_stack.py new file mode 100644 index 00000000000..8b32de9c206 --- /dev/null +++ b/layer/layer/layer_stack.py @@ -0,0 +1,19 @@ +from aws_cdk import Stack +from aws_cdk.aws_ssm import StringParameter +from cdk_lambda_powertools_python_layer import LambdaPowertoolsLayer +from constructs import Construct + + +class LayerStack(Stack): + def __init__( + self, scope: Construct, construct_id: str, powertools_version: str, ssm_paramter_layer_arn: str, **kwargs + ) -> None: + super().__init__(scope, construct_id, **kwargs) + + layer = LambdaPowertoolsLayer( + self, "Layer", layer_version_name="AWSLambdaPowertoolsPython", version=powertools_version + ) + + layer.add_permission("PublicLayerAccess", account_id="*") + + StringParameter(self, "VersionArn", parameter_name=ssm_paramter_layer_arn, string_value=layer.layer_version_arn) diff --git a/layer/requirements-dev.txt b/layer/requirements-dev.txt new file mode 100644 index 00000000000..f3ec7d732b5 --- /dev/null +++ b/layer/requirements-dev.txt @@ -0,0 +1,2 @@ +pytest==6.2.5 +boto3==1.24.22 diff --git a/layer/requirements.txt b/layer/requirements.txt new file mode 100644 index 00000000000..0484892d321 --- /dev/null +++ b/layer/requirements.txt @@ -0,0 +1,76 @@ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# pip-compile --generate-hashes requirements.txt +# +attrs==21.4.0 \ + --hash=sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4 \ + --hash=sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd + # via + # -r requirements.txt + # cattrs + # jsii +aws-cdk-lib==2.29.0 \ + --hash=sha256:4f852105cafd28a2bbd9bd2c6d24a2e1ab503bba923fd49a1782390b235af999 \ + --hash=sha256:53a78788219d9bf3a998211223225b34a10f066124e2812adcd40fd0a2058572 + # via + # -r requirements.txt + # cdk-lambda-powertools-python-layer +cattrs==22.1.0 \ + --hash=sha256:94b67b64cf92c994f8784c40c082177dc916e0489a73a9a36b24eb18a9db40c6 \ + --hash=sha256:d55c477b4672f93606e992049f15d526dc7867e6c756cd6256d4af92e2b1e364 + # via + # -r requirements.txt + # jsii +cdk-lambda-powertools-python-layer==2.0.48 \ + --hash=sha256:7bdd5a196e74b48d403223722f2838d1d10064d02e960a5565482cc0b7aad18d \ + --hash=sha256:9afeacea31eba14d67360db71af385c654c9e0af9b29a0d4e0922b52f862ae03 + # via -r requirements.txt +constructs==10.1.43 \ + --hash=sha256:69fd6da574c9506f44ca61e112af7d5db08ebb29b4bedc67b6d200b616f4abce \ + --hash=sha256:f37e8c3432f94f403b50bf69476bea55719bcc3fa0d3a0e60bf0975dfe492867 + # via + # -r requirements.txt + # aws-cdk-lib + # cdk-lambda-powertools-python-layer +exceptiongroup==1.0.0rc8 \ + --hash=sha256:6990c24f06b8d33c8065cfe43e5e8a4bfa384e0358be036af9cc60b6321bd11a \ + --hash=sha256:ab0a968e1ef769e55d9a596f4a89f7be9ffedbc9fdefdb77cc68cf5c33ce1035 + # via + # -r requirements.txt + # cattrs +jsii==1.61.0 \ + --hash=sha256:542a72cd1a144d36fa530dc359b5295b82d9e7ecdd76d5c7b4b61195f132a746 \ + --hash=sha256:b2899f24bcc95ce009bc256558c81cde8cff9f830eddbe9b0d581c40558a1ff0 + # via + # -r requirements.txt + # aws-cdk-lib + # cdk-lambda-powertools-python-layer + # constructs +publication==0.0.3 \ + --hash=sha256:0248885351febc11d8a1098d5c8e3ab2dabcf3e8c0c96db1e17ecd12b53afbe6 \ + --hash=sha256:68416a0de76dddcdd2930d1c8ef853a743cc96c82416c4e4d3b5d901c6276dc4 + # via + # -r requirements.txt + # aws-cdk-lib + # cdk-lambda-powertools-python-layer + # constructs +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via + # -r requirements.txt + # jsii +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via + # -r requirements.txt + # python-dateutil +typing-extensions==4.3.0 \ + --hash=sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02 \ + --hash=sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6 + # via + # -r requirements.txt + # jsii From 577a410ab3bcde7d2017eedd59bb4f37ccd2687f Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 13:05:41 +0200 Subject: [PATCH 07/30] fix: typo in input for layer workflow --- .github/workflows/publish_layer.yml | 4 ++-- .github/workflows/reusable_deploy_layer_stack.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index d4001e0bdce..7192bf8b6ce 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -65,7 +65,7 @@ jobs: uses: ./.github/workflows/reusable_deploy_layer_stack.yml with: stage: "BETA" - artifact-name: "cdk-layer-artefact" + artefact-name: "cdk-layer-artefact" secrets: target-account: ${{ secrets.LAYERS_BETA_ACCOUNT }} @@ -75,6 +75,6 @@ jobs: uses: ./.github/workflows/reusable_deploy_layer_stack.yml with: stage: "PROD" - artifact-name: "cdk-layer-artefact" + artefact-name: "cdk-layer-artefact" secrets: target-account: ${{ secrets.LAYERS_PROD_ACCOUNT }} diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index f31449e7ba6..ffeadf43045 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -84,4 +84,4 @@ jobs: - name: CDK Deploy Layer run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerStack ' --require-approval never --verbose - name: CDK Deploy Canary - run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="${{ input.stage }}" 'CanaryStack' --require-approval never --verbose + run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="${{ inputs.stage }}" 'CanaryStack' --require-approval never --verbose From e0b3b58d9774d5203d6370a2a16968026f751fb2 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 13:15:30 +0200 Subject: [PATCH 08/30] fix: no need to cache npm since we only install cdk cli and don't have .lock files --- .github/workflows/publish_layer.yml | 1 - .github/workflows/reusable_deploy_layer_stack.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index 7192bf8b6ce..c69e8cb5b9e 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -30,7 +30,6 @@ jobs: uses: actions/setup-node@v2 with: node-version: '16.12' - cache: 'npm' - name: Setup python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index ffeadf43045..2923c3efdbb 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -62,7 +62,6 @@ jobs: uses: actions/setup-node@v2 with: node-version: '16.12' - cache: 'npm' - name: Setup python uses: actions/setup-python@v4 with: From 925c14583d0815fec22dc606d350baef4dbd3d56 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 13:43:49 +0200 Subject: [PATCH 09/30] fix: add entire ARN role instead of account and role name --- .github/workflows/publish_layer.yml | 4 ++-- .github/workflows/reusable_deploy_layer_stack.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index c69e8cb5b9e..df20241c331 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -66,7 +66,7 @@ jobs: stage: "BETA" artefact-name: "cdk-layer-artefact" secrets: - target-account: ${{ secrets.LAYERS_BETA_ACCOUNT }} + target-account-role: arn:aws:iam::${{ secrets.LAYERS_BETA_ACCOUNT }}:role/${{ secrets.AWS_GITHUB_OIDC_ROLE }} deploy-prod: needs: @@ -76,4 +76,4 @@ jobs: stage: "PROD" artefact-name: "cdk-layer-artefact" secrets: - target-account: ${{ secrets.LAYERS_PROD_ACCOUNT }} + target-account-role: arn:aws:iam::${{ secrets.LAYERS_PROD_ACCOUNT }}:role/${{ secrets.AWS_GITHUB_OIDC_ROLE }} diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 2923c3efdbb..506cae96809 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -14,7 +14,7 @@ on: required: true type: string secrets: - target-account: + target-account-role: required: true jobs: @@ -57,7 +57,7 @@ jobs: uses: aws-actions/configure-aws-credentials@v1 with: aws-region: ${{ matrix.region }} - role-to-assume: arn:aws:iam::${{ secrets.target-account }}:role/${{ secrets.AWS_GITHUB_OIDC_ROLE }} + role-to-assume: ${{ secrets.target-account-role }} - name: Setup Node.js uses: actions/setup-node@v2 with: From 5bcd0260e8e793e55258cc1a795845656b3acfad Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 15:47:53 +0200 Subject: [PATCH 10/30] fix: path to artefact --- .github/workflows/publish_layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index df20241c331..b4814fbb98a 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -56,7 +56,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: cdk-layer-artefact - path: cdk.out.zip + path: layer/cdk.out.zip deploy-beta: needs: From 46c1754ac073b7e0b9151d07ce26eec4ba7033dc Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 16:03:44 +0200 Subject: [PATCH 11/30] fix: unzip the right artifact name --- .github/workflows/reusable_deploy_layer_stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 506cae96809..31f8830931d 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -79,7 +79,7 @@ jobs: with: name: ${{ inputs.artefact-name }} - name: unzip artefact - run: unzip cdk.out.zip + run: unzip ${{ inputs.artefact-name }} - name: CDK Deploy Layer run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerStack ' --require-approval never --verbose - name: CDK Deploy Canary From 1170e7674d8d09fb7938dae79d332371e85e2329 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Thu, 7 Jul 2022 16:47:43 +0200 Subject: [PATCH 12/30] docs(event-handler): snippets split, improved, and lint (#1279) --- docs/core/event_handler/api_gateway.md | 1166 +++-------------- docs/core/logger.md | 3 + docs/core/metrics.md | 3 + docs/core/tracer.md | 3 + examples/event_handler_rest/sam/template.yaml | 56 + .../src/accessing_request_details.py | 40 + .../src/accessing_request_details_headers.py | 30 + .../src/assert_http_response.py | 28 + .../src/assert_http_response_module.py | 27 + .../src/binary_responses.json | 8 + .../src/binary_responses.py | 27 + .../src/binary_responses_logo.svg | 14 + .../src/binary_responses_output.json | 8 + .../src/compressing_responses.json | 8 + .../src/compressing_responses.py | 28 + .../src/compressing_responses_output.json | 9 + .../src/custom_api_mapping.json | 5 + .../src/custom_api_mapping.py | 20 + .../src/custom_serializer.py | 58 + examples/event_handler_rest/src/debug_mode.py | 28 + .../src/dynamic_routes.json | 5 + .../event_handler_rest/src/dynamic_routes.py | 27 + .../src/dynamic_routes_catch_all.json | 5 + .../src/dynamic_routes_catch_all.py | 21 + .../src/exception_handling.py | 43 + .../src/fine_grained_responses.py | 36 + .../src/fine_grained_responses_output.json | 9 + .../src/getting_started_alb_api_resolver.py | 28 + .../src/getting_started_http_api_resolver.py | 28 + .../getting_started_rest_api_resolver.json | 58 + .../src/getting_started_rest_api_resolver.py | 28 + ...ting_started_rest_api_resolver_output.json | 8 + .../event_handler_rest/src/http_methods.json | 6 + .../event_handler_rest/src/http_methods.py | 28 + .../src/http_methods_multiple.py | 29 + .../src/not_found_routes.py | 35 + .../src/raising_http_errors.py | 59 + .../event_handler_rest/src/setting_cors.py | 44 + .../src/setting_cors_output.json | 10 + .../event_handler_rest/src/split_route.py | 18 + .../src/split_route_module.py | 33 + .../src/split_route_prefix.py | 19 + .../src/split_route_prefix_module.py | 36 + 43 files changed, 1164 insertions(+), 1018 deletions(-) create mode 100644 examples/event_handler_rest/sam/template.yaml create mode 100644 examples/event_handler_rest/src/accessing_request_details.py create mode 100644 examples/event_handler_rest/src/accessing_request_details_headers.py create mode 100644 examples/event_handler_rest/src/assert_http_response.py create mode 100644 examples/event_handler_rest/src/assert_http_response_module.py create mode 100644 examples/event_handler_rest/src/binary_responses.json create mode 100644 examples/event_handler_rest/src/binary_responses.py create mode 100644 examples/event_handler_rest/src/binary_responses_logo.svg create mode 100644 examples/event_handler_rest/src/binary_responses_output.json create mode 100644 examples/event_handler_rest/src/compressing_responses.json create mode 100644 examples/event_handler_rest/src/compressing_responses.py create mode 100644 examples/event_handler_rest/src/compressing_responses_output.json create mode 100644 examples/event_handler_rest/src/custom_api_mapping.json create mode 100644 examples/event_handler_rest/src/custom_api_mapping.py create mode 100644 examples/event_handler_rest/src/custom_serializer.py create mode 100644 examples/event_handler_rest/src/debug_mode.py create mode 100644 examples/event_handler_rest/src/dynamic_routes.json create mode 100644 examples/event_handler_rest/src/dynamic_routes.py create mode 100644 examples/event_handler_rest/src/dynamic_routes_catch_all.json create mode 100644 examples/event_handler_rest/src/dynamic_routes_catch_all.py create mode 100644 examples/event_handler_rest/src/exception_handling.py create mode 100644 examples/event_handler_rest/src/fine_grained_responses.py create mode 100644 examples/event_handler_rest/src/fine_grained_responses_output.json create mode 100644 examples/event_handler_rest/src/getting_started_alb_api_resolver.py create mode 100644 examples/event_handler_rest/src/getting_started_http_api_resolver.py create mode 100644 examples/event_handler_rest/src/getting_started_rest_api_resolver.json create mode 100644 examples/event_handler_rest/src/getting_started_rest_api_resolver.py create mode 100644 examples/event_handler_rest/src/getting_started_rest_api_resolver_output.json create mode 100644 examples/event_handler_rest/src/http_methods.json create mode 100644 examples/event_handler_rest/src/http_methods.py create mode 100644 examples/event_handler_rest/src/http_methods_multiple.py create mode 100644 examples/event_handler_rest/src/not_found_routes.py create mode 100644 examples/event_handler_rest/src/raising_http_errors.py create mode 100644 examples/event_handler_rest/src/setting_cors.py create mode 100644 examples/event_handler_rest/src/setting_cors_output.json create mode 100644 examples/event_handler_rest/src/split_route.py create mode 100644 examples/event_handler_rest/src/split_route_module.py create mode 100644 examples/event_handler_rest/src/split_route_prefix.py create mode 100644 examples/event_handler_rest/src/split_route_prefix_module.py diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index cf99b615a80..9db219e994e 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -8,14 +8,14 @@ Event handler for Amazon API Gateway REST and HTTP APIs, and Application Loader ## Key Features * Lightweight routing to reduce boilerplate for API Gateway REST/HTTP API and ALB -* Seamless support for CORS, binary and Gzip compression -* Integrates with [Data classes utilities](../../utilities/data_classes.md){target="_blank"} to easily access event and identity information -* Built-in support for Decimals JSON encoding -* Support for dynamic path expressions -* Router to allow for splitting up the handler across multiple files +* Support for CORS, binary and Gzip compression, Decimals JSON encoding and bring your own JSON serializer +* Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"} for self-documented event schema ## Getting started +???+ tip + All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}. + ### Required resources You must have an existing [API Gateway Proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html){target="_blank"} or [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html){target="_blank"} configured to invoke your Lambda function. @@ -25,54 +25,14 @@ This is the sample infrastructure for API Gateway we are using for the examples ???+ info "There is no additional permissions or dependencies required to use this utility." ```yaml title="AWS Serverless Application Model (SAM) example" -AWSTemplateFormatVersion: "2010-09-09" -Transform: AWS::Serverless-2016-10-31 -Description: Hello world event handler API Gateway - -Globals: - Api: - TracingEnabled: true - Cors: # see CORS section - AllowOrigin: "'https://example.com'" - AllowHeaders: "'Content-Type,Authorization,X-Amz-Date'" - MaxAge: "'300'" - BinaryMediaTypes: # see Binary responses section - - "*~1*" # converts to */* for any binary type - Function: - Timeout: 5 - Runtime: python3.8 - Tracing: Active - Environment: - Variables: - LOG_LEVEL: INFO - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 - POWERTOOLS_LOGGER_LOG_EVENT: true - POWERTOOLS_METRICS_NAMESPACE: MyServerlessApplication - POWERTOOLS_SERVICE_NAME: my_api-service - -Resources: - ApiFunction: - Type: AWS::Serverless::Function - Properties: - Handler: app.lambda_handler - CodeUri: api_handler/ - Description: API handler function - Events: - ApiEvent: - Type: Api - Properties: - # NOTE: this is a catch-all rule to simply the documentation. - # explicit routes and methods are recommended for prod instead - # for example, Path: /hello, Method: GET - Path: /{proxy+} # Send requests on any path to the lambda function - Method: ANY # Send requests using any http method to the lambda function +--8<-- "examples/event_handler_rest/sam/template.yaml" ``` ### Event Resolvers Before you decorate your functions to handle a given path and HTTP method(s), you need to initialize a resolver. -A resolver will handle request resolution, include [one or more routers](#split-routes-with-router), and give you access to the current event via typed properties. +A resolver will handle request resolution, including [one or more routers](#split-routes-with-router), and give you access to the current event via typed properties. For resolvers, we provide: `APIGatewayRestResolver`, `APIGatewayHttpResolver`, and `ALBResolver`. @@ -83,113 +43,29 @@ For resolvers, we provide: `APIGatewayRestResolver`, `APIGatewayHttpResolver`, a When using Amazon API Gateway REST API to front your Lambda functions, you can use `APIGatewayRestResolver`. -Here's an example on how we can handle the `/hello` path. +Here's an example on how we can handle the `/todos` path. ???+ info We automatically serialize `Dict` responses as JSON, trim whitespace for compact responses, and set content-type to `application/json`. === "app.py" - ```python hl_lines="3 7 9 12 18" - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - tracer = Tracer() - logger = Logger() - app = APIGatewayRestResolver() - - @app.get("/hello") - @tracer.capture_method - def get_hello_universe(): - return {"message": "hello universe"} - - # You can continue to use other utilities just as before - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="5 11 14 28" + --8<-- "examples/event_handler_rest/src/getting_started_rest_api_resolver.py" ``` -=== "hello_event.json" + +=== "Request" This utility uses `path` and `httpMethod` to route to the right function. This helps make unit tests and local invocation easier too. ```json hl_lines="4-5" - { - "body": "hello", - "resource": "/hello", - "path": "/hello", - "httpMethod": "GET", - "isBase64Encoded": false, - "queryStringParameters": { - "foo": "bar" - }, - "multiValueQueryStringParameters": {}, - "pathParameters": { - "hello": "/hello" - }, - "stageVariables": {}, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - "Accept-Encoding": "gzip, deflate, sdch", - "Accept-Language": "en-US,en;q=0.8", - "Cache-Control": "max-age=0", - "CloudFront-Forwarded-Proto": "https", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-Mobile-Viewer": "false", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Tablet-Viewer": "false", - "CloudFront-Viewer-Country": "US", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Custom User Agent String", - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" - }, - "multiValueHeaders": {}, - "requestContext": { - "accountId": "123456789012", - "resourceId": "123456", - "stage": "Prod", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "requestTime": "25/Jul/2020:12:34:56 +0000", - "requestTimeEpoch": 1428582896000, - "identity": { - "cognitoIdentityPoolId": null, - "accountId": null, - "cognitoIdentityId": null, - "caller": null, - "accessKey": null, - "sourceIp": "127.0.0.1", - "cognitoAuthenticationType": null, - "cognitoAuthenticationProvider": null, - "userArn": null, - "userAgent": "Custom User Agent String", - "user": null - }, - "path": "/Prod/hello", - "resourcePath": "/hello", - "httpMethod": "POST", - "apiId": "1234567890", - "protocol": "HTTP/1.1" - } - } + --8<-- "examples/event_handler_rest/src/getting_started_rest_api_resolver.json" ``` -=== "response.json" +=== "Response" ```json - { - "statusCode": 200, - "headers": { - "Content-Type": "application/json" - }, - "body": "{\"message\":\"hello universe\"}", - "isBase64Encoded": false - } + --8<-- "examples/event_handler_rest/src/getting_started_rest_api_resolver_output.json" ``` #### API Gateway HTTP API @@ -199,477 +75,166 @@ When using Amazon API Gateway HTTP API to front your Lambda functions, you can u ???+ note Using HTTP API v1 payload? Use `APIGatewayRestResolver` instead. `APIGatewayHttpResolver` defaults to v2 payload. -Here's an example on how we can handle the `/hello` path. - -```python hl_lines="3 7" title="Using HTTP API resolver" -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.logging import correlation_paths -from aws_lambda_powertools.event_handler import APIGatewayHttpResolver - -tracer = Tracer() -logger = Logger() -app = APIGatewayHttpResolver() - -@app.get("/hello") -@tracer.capture_method -def get_hello_universe(): - return {"message": "hello universe"} - -# You can continue to use other utilities just as before -@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP) -@tracer.capture_lambda_handler -def lambda_handler(event, context): - return app.resolve(event, context) +```python hl_lines="5 11" title="Using HTTP API resolver" +--8<-- "examples/event_handler_rest/src/getting_started_http_api_resolver.py" ``` #### Application Load Balancer -When using Amazon Application Load Balancer to front your Lambda functions, you can use `ALBResolver`. - -```python hl_lines="3 7" title="Using ALB resolver" -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.logging import correlation_paths -from aws_lambda_powertools.event_handler import ALBResolver - -tracer = Tracer() -logger = Logger() -app = ALBResolver() +When using Amazon Application Load Balancer (ALB) to front your Lambda functions, you can use `ALBResolver`. -@app.get("/hello") -@tracer.capture_method -def get_hello_universe(): - return {"message": "hello universe"} - -# You can continue to use other utilities just as before -@logger.inject_lambda_context(correlation_id_path=correlation_paths.APPLICATION_LOAD_BALANCER) -@tracer.capture_lambda_handler -def lambda_handler(event, context): - return app.resolve(event, context) +```python hl_lines="5 11" title="Using ALB resolver" +--8<-- "examples/event_handler_rest/src/getting_started_alb_api_resolver.py" ``` ### Dynamic routes -You can use `/path/{dynamic_value}` when configuring dynamic URL paths. This allows you to define such dynamic value as part of your function signature. - -=== "app.py" - - ```python hl_lines="9 11" - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - tracer = Tracer() - logger = Logger() - app = APIGatewayRestResolver() - - @app.get("/hello/") - @tracer.capture_method - def get_hello_you(name): - return {"message": f"hello {name}"} - - # You can continue to use other utilities just as before - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event, context): - return app.resolve(event, context) - ``` - -=== "sample_request.json" +You can use `/todos/` to configure dynamic URL paths, where `` will be resolved at runtime. - ```json - { - "resource": "/hello/{name}", - "path": "/hello/lessa", - "httpMethod": "GET", - ... - } - ``` +Each dynamic route you set must be part of your function signature. This allows us to call your function using keyword arguments when matching your dynamic route. -#### Nested routes - -You can also nest paths as configured earlier in [our sample infrastructure](#required-resources): `/{message}/{name}`. +???+ note + For brevity, we will only include the necessary keys for each sample request for the example to work. === "app.py" - ```python hl_lines="9 11" - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - tracer = Tracer() - logger = Logger() - app = APIGatewayRestResolver() - - @app.get("//") - @tracer.capture_method - def get_message(message, name): - return {"message": f"{message}, {name}"} - - # You can continue to use other utilities just as before - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="14 16" + --8<-- "examples/event_handler_rest/src/dynamic_routes.py" ``` -=== "sample_request.json" +=== "Request" ```json - { - "resource": "/{message}/{name}", - "path": "/hi/michael", - "httpMethod": "GET", - ... - } + --8<-- "examples/event_handler_rest/src/dynamic_routes.json" ``` +???+ tip + You can also nest dynamic paths, for example `/todos//`. + #### Catch-all routes ???+ note We recommend having explicit routes whenever possible; use catch-all routes sparingly. -You can use a regex string to handle an arbitrary number of paths within a request, for example `.+`. +You can use a [regex](https://docs.python.org/3/library/re.html#regular-expression-syntax){target="_blank"} string to handle an arbitrary number of paths within a request, for example `.+`. You can also combine nested paths with greedy regex to catch in between routes. ???+ warning - We will choose the more explicit registered route that match incoming event. + We choose the most explicit registered route that matches an incoming event. === "app.py" - ```python hl_lines="5" - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - app = APIGatewayRestResolver() - - @app.get(".+") - def catch_any_route_after_any(): - return {"path_received": app.current_event.path} - - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="11" + --8<-- "examples/event_handler_rest/src/dynamic_routes_catch_all.py" ``` -=== "sample_request.json" +=== "Request" ```json - { - "resource": "/any/route/should/work", - "path": "/any/route/should/work", - "httpMethod": "GET", - ... - } + --8<-- "examples/event_handler_rest/src/dynamic_routes_catch_all.json" ``` ### HTTP Methods -You can use named decorators to specify the HTTP method that should be handled in your functions. As well as the -`get` method already shown above, you can use `post`, `put`, `patch`, `delete`, and `patch`. +You can use named decorators to specify the HTTP method that should be handled in your functions. That is, `app.`, where the HTTP method could be `get`, `post`, `put`, `patch`, `delete`, and `options`. === "app.py" - ```python hl_lines="9-10" - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - tracer = Tracer() - logger = Logger() - app = APIGatewayRestResolver() - - # Only POST HTTP requests to the path /hello will route to this function - @app.post("/hello") - @tracer.capture_method - def get_hello_you(): - name = app.current_event.json_body.get("name") - return {"message": f"hello {name}"} - - # You can continue to use other utilities just as before - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="14 17" + --8<-- "examples/event_handler_rest/src/http_methods.py" ``` -=== "sample_request.json" +=== "Request" ```json - { - "resource": "/hello/{name}", - "path": "/hello/lessa", - "httpMethod": "GET", - ... - } - ``` - -If you need to accept multiple HTTP methods in a single function, you can use the `route` method and pass a list of -HTTP methods. - -=== "app.py" - - ```python hl_lines="9-10" - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - tracer = Tracer() - logger = Logger() - app = APIGatewayRestResolver() - - # PUT and POST HTTP requests to the path /hello will route to this function - @app.route("/hello", method=["PUT", "POST"]) - @tracer.capture_method - def get_hello_you(): - name = app.current_event.json_body.get("name") - return {"message": f"hello {name}"} - - # You can continue to use other utilities just as before - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event, context): - return app.resolve(event, context) + --8<-- "examples/event_handler_rest/src/http_methods.json" ``` -=== "sample_request.json" +If you need to accept multiple HTTP methods in a single function, you can use the `route` method and pass a list of HTTP methods. - ```json - { - "resource": "/hello/{name}", - "path": "/hello/lessa", - "httpMethod": "GET", - ... - } - ``` +```python hl_lines="15" title="Handling multiple HTTP Methods" +--8<-- "examples/event_handler_rest/src/http_methods_multiple.py" +``` ???+ note - It is usually better to have separate functions for each HTTP method, as the functionality tends to differ depending on which method is used. + It is generally better to have separate functions for each HTTP method, as the functionality tends to differ depending on which method is used. ### Accessing request details -By integrating with [Data classes utilities](../../utilities/data_classes.md){target="_blank"}, you have access to request details, Lambda context and also some convenient methods. +Event Handler integrates with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"}, and it exposes their respective resolver request details and convenient methods under `app.current_event`. -These are made available in the response returned when instantiating `APIGatewayRestResolver`, for example `app.current_event` and `app.lambda_context`. +That is why you see `app.resolve(event, context)` in every example. This allows Event Handler to resolve requests, and expose data like `app.lambda_context` and `app.current_event`. #### Query strings and payload -Within `app.current_event` property, you can access query strings as dictionary via `query_string_parameters`, or by name via `get_query_string_value` method. - -You can access the raw payload via `body` property, or if it's a JSON string you can quickly deserialize it via `json_body` property. +Within `app.current_event` property, you can access all available query strings as a dictionary via `query_string_parameters`, or a specific one via `get_query_string_value` method. -```python hl_lines="7-9 11" title="Accessing query strings, JSON payload, and raw payload" -from aws_lambda_powertools.event_handler import APIGatewayRestResolver +You can access the raw payload via `body` property, or if it's a JSON string you can quickly deserialize it via `json_body` property - like the earlier example in the [HTTP Methods](#http-methods) section. -app = APIGatewayRestResolver() - -@app.get("/hello") -def get_hello_you(): - query_strings_as_dict = app.current_event.query_string_parameters - json_payload = app.current_event.json_body - payload = app.current_event.body - - name = app.current_event.get_query_string_value(name="name", default_value="") - return {"message": f"hello {name}"} - -def lambda_handler(event, context): - return app.resolve(event, context) +```python hl_lines="19 24" title="Accessing query strings and raw payload" +--8<-- "examples/event_handler_rest/src/accessing_request_details.py" ``` #### Headers Similarly to [Query strings](#query-strings-and-payload), you can access headers as dictionary via `app.current_event.headers`, or by name via `get_header_value`. -```python hl_lines="7-8" title="Accessing HTTP Headers" -from aws_lambda_powertools.event_handler import APIGatewayRestResolver - -app = APIGatewayRestResolver() - -@app.get("/hello") -def get_hello_you(): - headers_as_dict = app.current_event.headers - name = app.current_event.get_header_value(name="X-Name", default_value="") - - return {"message": f"hello {name}"} - -def lambda_handler(event, context): - return app.resolve(event, context) +```python hl_lines="19" title="Accessing HTTP Headers" +--8<-- "examples/event_handler_rest/src/accessing_request_details_headers.py" ``` ### Handling not found routes By default, we return `404` for any unmatched route. -You can use **`not_found`** decorator to override this behaviour, and return a custom **`Response`**. - -```python hl_lines="11 13 16" title="Handling not found" -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.logging import correlation_paths -from aws_lambda_powertools.event_handler import content_types -from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, Response -from aws_lambda_powertools.event_handler.exceptions import NotFoundError - -tracer = Tracer() -logger = Logger() -app = APIGatewayRestResolver() - -@app.not_found -@tracer.capture_method -def handle_not_found_errors(exc: NotFoundError) -> Response: - # Return 418 upon 404 errors - logger.info(f"Not found route: {app.current_event.path}") - return Response( - status_code=418, - content_type=content_types.TEXT_PLAIN, - body="I'm a teapot!" - ) - - -@app.get("/catch/me/if/you/can") -@tracer.capture_method -def catch_me_if_you_can(): - return {"message": "oh hey"} - -@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) -@tracer.capture_lambda_handler -def lambda_handler(event, context): - return app.resolve(event, context) +You can use **`not_found`** decorator to override this behavior, and return a custom **`Response`**. + +```python hl_lines="14 18" title="Handling not found" +--8<-- "examples/event_handler_rest/src/not_found_routes.py" ``` ### Exception handling You can use **`exception_handler`** decorator with any Python exception. This allows you to handle a common exception outside your route, for example validation errors. -```python hl_lines="10 15" title="Exception handling" -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.logging import correlation_paths -from aws_lambda_powertools.event_handler import content_types -from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, Response - -tracer = Tracer() -logger = Logger() -app = APIGatewayRestResolver() - -@app.exception_handler(ValueError) -def handle_value_error(ex: ValueError): - metadata = {"path": app.current_event.path} - logger.error(f"Malformed request: {ex}", extra=metadata) - - return Response( - status_code=400, - content_type=content_types.TEXT_PLAIN, - body="Invalid request", - ) - - -@app.get("/hello") -@tracer.capture_method -def hello_name(): - name = app.current_event.get_query_string_value(name="name") - if name is not None: - raise ValueError("name query string must be present") - return {"message": f"hello {name}"} - -@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) -@tracer.capture_lambda_handler -def lambda_handler(event, context): - return app.resolve(event, context) +```python hl_lines="14 15" title="Exception handling" +--8<-- "examples/event_handler_rest/src/exception_handling.py" ``` ### Raising HTTP errors -You can easily raise any HTTP Error back to the client using `ServiceError` exception. +You can easily raise any HTTP Error back to the client using `ServiceError` exception. This ensures your Lambda function doesn't fail but return the correct HTTP response signalling the error. ???+ info If you need to send custom headers, use [Response](#fine-grained-responses) class instead. -Additionally, we provide pre-defined errors for the most popular ones such as HTTP 400, 401, 404, 500. - -```python hl_lines="4-10 20 25 30 35 39" title="Raising common HTTP Status errors (4xx, 5xx)" -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.logging import correlation_paths -from aws_lambda_powertools.event_handler import APIGatewayRestResolver -from aws_lambda_powertools.event_handler.exceptions import ( - BadRequestError, - InternalServerError, - NotFoundError, - ServiceError, - UnauthorizedError, -) - -tracer = Tracer() -logger = Logger() - -app = APIGatewayRestResolver() - -@app.get(rule="/bad-request-error") -def bad_request_error(): - # HTTP 400 - raise BadRequestError("Missing required parameter") - -@app.get(rule="/unauthorized-error") -def unauthorized_error(): - # HTTP 401 - raise UnauthorizedError("Unauthorized") - -@app.get(rule="/not-found-error") -def not_found_error(): - # HTTP 404 - raise NotFoundError - -@app.get(rule="/internal-server-error") -def internal_server_error(): - # HTTP 500 - raise InternalServerError("Internal server error") - -@app.get(rule="/service-error", cors=True) -def service_error(): - raise ServiceError(502, "Something went wrong!") - # alternatively - # from http import HTTPStatus - # raise ServiceError(HTTPStatus.BAD_GATEWAY.value, "Something went wrong) - -def handler(event, context): - return app.resolve(event, context) +We provide pre-defined errors for the most popular ones such as HTTP 400, 401, 404, 500. + +```python hl_lines="6-11 23 28 33 38 43" title="Raising common HTTP Status errors (4xx, 5xx)" +--8<-- "examples/event_handler_rest/src/raising_http_errors.py" ``` ### Custom Domain API Mappings -When using Custom Domain API Mappings feature, you must use **`strip_prefixes`** param in the `APIGatewayRestResolver` constructor. - -Scenario: You have a custom domain `api.mydomain.dev` and set an API Mapping `payment` to forward requests to your Payments API, the path argument will be `/payment/`. +When using [Custom Domain API Mappings feature](https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html){target="_blank"}, you must use **`strip_prefixes`** param in the `APIGatewayRestResolver` constructor. -This will lead to a HTTP 404 despite having your Lambda configured correctly. See the example below on how to account for this change. - -=== "app.py" +**Scenario**: You have a custom domain `api.mydomain.dev`. Then you set `/payment` API Mapping to forward any payment requests to your Payments API. - ```python hl_lines="7" - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler import APIGatewayRestResolver +**Challenge**: This means your `path` value for any API requests will always contain `/payment/`, leading to HTTP 404 as Event Handler is trying to match what's after `payment/`. This gets further complicated with an [arbitrary level of nesting](https://github.com/awslabs/aws-lambda-powertools-roadmap/issues/34). - tracer = Tracer() - logger = Logger() - app = APIGatewayRestResolver(strip_prefixes=["/payment"]) +To address this API Gateway behavior, we use `strip_prefixes` parameter to account for these prefixes that are now injected into the path regardless of which type of API Gateway you're using. - @app.get("/subscriptions/") - @tracer.capture_method - def get_subscription(subscription): - return {"subscription_id": subscription} +=== "app.py" - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="8" + --8<-- "examples/event_handler_rest/src/custom_api_mapping.py" ``` -=== "sample_request.json" +=== "Request" ```json - { - "resource": "/subscriptions/{subscription}", - "path": "/payment/subscriptions/123", - "httpMethod": "GET", - ... - } + --8<-- "examples/event_handler_rest/src/custom_api_mapping.json" ``` ???+ note @@ -685,67 +250,21 @@ You can configure CORS at the `APIGatewayRestResolver` constructor via `cors` pa This will ensure that CORS headers are always returned as part of the response when your functions match the path invoked. -=== "app.py" - - ```python hl_lines="9 11" - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, CORSConfig - - tracer = Tracer() - logger = Logger() - - cors_config = CORSConfig(allow_origin="https://example.com", max_age=300) - app = APIGatewayRestResolver(cors=cors_config) - - @app.get("/hello/") - @tracer.capture_method - def get_hello_you(name): - return {"message": f"hello {name}"} - - @app.get("/hello", cors=False) # optionally exclude CORS from response, if needed - @tracer.capture_method - def get_hello_no_cors_needed(): - return {"message": "hello, no CORS needed for this path ;)"} - - # You can continue to use other utilities just as before - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event, context): - return app.resolve(event, context) - ``` +???+ tip + Optionally disable CORS on a per path basis with `cors=False` parameter. -=== "response.json" +=== "app.py" - ```json - { - "statusCode": 200, - "headers": { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": "https://www.example.com", - "Access-Control-Allow-Headers": "Authorization,Content-Type,X-Amz-Date,X-Amz-Security-Token,X-Api-Key" - }, - "body": "{\"message\":\"hello lessa\"}", - "isBase64Encoded": false - } + ```python hl_lines="5 11-12 34" + --8<-- "examples/event_handler_rest/src/setting_cors.py" ``` -=== "response_no_cors.json" +=== "Response" ```json - { - "statusCode": 200, - "headers": { - "Content-Type": "application/json" - }, - "body": "{\"message\":\"hello lessa\"}", - "isBase64Encoded": false - } + --8<-- "examples/event_handler_rest/src/setting_cors_output.json" ``` -???+ tip - Optionally disable CORS on a per path basis with `cors=False` parameter. - #### Pre-flight Pre-flight (OPTIONS) calls are typically handled at the API Gateway level as per [our sample infrastructure](#required-resources), no Lambda integration necessary. However, ALB expects you to handle pre-flight requests. @@ -773,40 +292,15 @@ You can use the `Response` class to have full control over the response, for exa === "app.py" - ```python hl_lines="11-16" - import json - from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, Response - - app = APIGatewayRestResolver() - - @app.get("/hello") - def get_hello_you(): - payload = json.dumps({"message": "I'm a teapot"}) - custom_headers = {"X-Custom": "X-Value"} - - return Response( - status_code=418, - content_type="application/json", - body=payload, - headers=custom_headers, - ) - - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="7 24-28" + --8<-- "examples/event_handler_rest/src/fine_grained_responses.py" ``` -=== "response.json" +=== "Response" ```json - { - "body": "{\"message\":\"I\'m a teapot\"}", - "headers": { - "Content-Type": "application/json", - "X-Custom": "X-Value" - }, - "isBase64Encoded": false, - "statusCode": 418 - } + --8<-- "examples/event_handler_rest/src/fine_grained_responses_output.json" + ``` ### Compress @@ -817,44 +311,20 @@ You can compress with gzip and base64 encode your responses via `compress` param === "app.py" - ```python hl_lines="5 7" - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - app = APIGatewayRestResolver() - - @app.get("/hello", compress=True) - def get_hello_you(): - return {"message": "hello universe"} - - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="14" + --8<-- "examples/event_handler_rest/src/compressing_responses.py" ``` -=== "sample_request.json" +=== "Request" ```json - { - "headers": { - "Accept-Encoding": "gzip" - }, - "httpMethod": "GET", - "path": "/hello", - ... - } + --8<-- "examples/event_handler_rest/src/compressing_responses.json" ``` -=== "response.json" +=== "Response" ```json - { - "body": "H4sIAAAAAAACE6tWyk0tLk5MT1WyUspIzcnJVyjNyyxLLSpOVaoFANha8kEcAAAA", - "headers": { - "Content-Encoding": "gzip", - "Content-Type": "application/json" - }, - "isBase64Encoded": true, - "statusCode": 200 - } + --8<-- "examples/event_handler_rest/src/compressing_responses_output.json" ``` ### Binary responses @@ -868,89 +338,26 @@ Like `compress` feature, the client must send the `Accept` header with the corre === "app.py" - ```python hl_lines="4 7 11" - import os - from pathlib import Path - - from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, Response - - app = APIGatewayRestResolver() - logo_file: bytes = Path(os.getenv("LAMBDA_TASK_ROOT") + "/logo.svg").read_bytes() - - @app.get("/logo") - def get_logo(): - return Response(status_code=200, content_type="image/svg+xml", body=logo_file) - - def lambda_handler(event, context): - return app.resolve(event, context) + ```python hl_lines="14 20" + --8<-- "examples/event_handler_rest/src/binary_responses.py" ``` === "logo.svg" ```xml - - - - - - - - - - - - + --8<-- "examples/event_handler_rest/src/binary_responses_logo.svg" ``` -=== "sample_request.json" + +=== "Request" ```json - { - "headers": { - "Accept": "image/svg+xml" - }, - "httpMethod": "GET", - "path": "/logo", - ... - } + --8<-- "examples/event_handler_rest/src/binary_responses.json" ``` -=== "response.json" +=== "Response" ```json - { - "body": "H4sIAAAAAAACE3VXa2scRxD87ID/w+byKTCzN899yFZMLBLHYEMg4K9BHq0l4c2duDudZIf891TVrPwiMehmd+fR3dXV1eOnz+7/mpvjtNtfbzenK9+6VTNtyvbienN5uro9vLPD6tlPj797+r21zYtpM+3OD9vdSfPzxfbt1Lyc59v9QZ8aP7au9ab5482L5pf7m+3u0Pw+317al5um1cc31chJ07XONc9vr+eLxv3YNNby/P3x8ks3/Kq5vjhdvTr/MO3+xAu83OxPV1eHw83Jen13d9fexXa7u1wH59wam5clJ/fz9eb9fy304ziuNYulpyt3c79qPtTx8XePmuP1dPd8y4nGNdGlxg9h1ewPH+bpdDVtzt/Ok317Xt5f7ra3m4uTzXTXfLHyicyf7G/OC5bf7Kb9tDtOKwXGI5rDhxtMHKb7w7rs95x41O4P7u931/N88sOv+vfkn/rV66vd3c7TyXScNtuLiydlvr75+su3O5+uZYkmL3n805vzw1VT5vM9cIOpVQM8Xw9dm0yHn+JMbHvj+IoRiJuhHYtrBxPagPfBpLbDmmD6NuB7NpxzWttpDG3EKd46vAfr29HE2XZtxMYABx4VzIxY2VmvnaMN2jkW642zAdPZRkyms76DndGZPpthgEt9MvB0wEJM91gacUpsvc3c3eO4sYXJHuf52A42jNjEp2qXRzjrMzaENtngLGOwCS4krO7xzXscoIeR4WFLNpFbEo7GNrhdOhkEGElrgUyCx3gokQYAHMOLxjvFVY1XVDNQy0AKkx4PgPSIjcALv8QDf0He9NZ3BaEFhTdgInESMPKBMwAemzxTZT1zgFP5vRekOJTg8zucquEvCULsXOx1hjY5bWKuAh1fFkbuIGABa71+4cuRcMHfuiboMB6Kw8gGW5mQtDUwBa1f4s/Kd6+1iD8oplyIvq9oebEFYBOKsXi+ORNEJBKLbBhaXzIcZ0YGbgMF9IAkdG9I4Y/N65RhaYCLi+morPSipK8RMlmdIgahbFR+s2UF+Gpe3ieip6/kayCbkHpYRUp6QgH6MGFEgLuiFQHbviLO/DkdEGkbk4ljsawtR7J1zIAFk0aTioBBpIQYbmWNJArqKQlXxh9UoSQXjZxFIGoGFmzSPM/8FD+w8IDNmxG+l1pwlr5Ey/rwzP1gay1mG5Ykj6/GrpoIRZOMYqR3GiudHijAFJPJiePVCGBr2mIlE0bEUKpIMFrQwjCEcQabB4pOmJVyPolCYWEnYJZVyU+VE4JrQC56cPWtpfSVHfhkJD60RDy6foYyRNv1NZlCXoh/YwM05C7rEU0sitKERehqrLkiYCrhvcSO53VFrzxeAqB0UxHzbMFPb/q+1ltVRoITiTnNKRWm0ownRlbpFUu/iI5uYRMEoMb/kLt+yR3BSq98xtkQXElWl5h1yg6nvcz5SrVFta1UHTz3v4koIEzIVPgRKlkkc44ykipJsip7kVMWdICDFPBMMoOwUhlbRb23NX/UjqHYesi4sK2OmDhaWpLKiE1YzxbCsUhATZUlb2q7iBX7Kj/Kc80atEz66yWyXorhGTIkRqnrSURu8fWhdNIFKT7B8UnNJPIUwYLgLVHkOD7knC4rjNpFeturrBRRbmtHkpTh5VVIncmBnYlpjhT3HhMUd1urK0rQE7AE14goJdFRWBYZHyUIcLLm3AuhwF5qO7Zg4B+KTodiJCaSOMN4SXbRC+pR1Vs8FEZGOcnCtKvNvnC/aoiKj2+dekO1GdS4VMfAQo2++KXOonIgf5ifoo6hOkm6EFDP8pItNXvVpFNdxiNErThVXG1UQXHEz/eEYWk/jEmCRcyyaKtWKbVSr1YNc6rytcLnq6AORazytbMa9nqOutgYdUPmGL72nyKmlzxMVcjpPLPdE7cC1MlQQkpyZHasjPbRFVpJ+mNPqlcln6Tekk5lg7cd/9CbJMkkXFInSmrcw4PHQS1p0HZSANa6s8CqNiN/Qh7hI0vVfK7aj6u1Lnq67n173/P1vhd6Nf+ETgJLgSyjjYGpj2SVD3JM96PM+xRRZYcMtV8NJHKn3bW+pUydGMFg1CMelUSIgjwj4nGUVULDxxJJM1zvsM/q0uZ5TQggwFnoRanI9h76gcSJDPYLz5dA/y/EgXnygRcGostStqFXv0KdD7qP6MYUTKVXr1uhEzty8QP5plqDXbZuk1mtuUZGv3jtg8JIFKHTJrt6H9AduN4TAE6q95qzMEikMmkVRq+bKQXrC0cfUrdm7h5+8b8YjP8Cgadmu5INAAA=", - "headers": { - "Content-Type": "image/svg+xml" - }, - "isBase64Encoded": true, - "statusCode": 200 - } + --8<-- "examples/event_handler_rest/src/binary_responses_output.json" ``` ### Debug mode @@ -964,326 +371,88 @@ This will enable full tracebacks errors in the response, print request and respo It's best to use for local development only! -```python hl_lines="3" title="Enabling debug mode" -from aws_lambda_powertools.event_handler import APIGatewayRestResolver - -app = APIGatewayRestResolver(debug=True) - -@app.get("/hello") -def get_hello_universe(): - return {"message": "hello universe"} - -def lambda_handler(event, context): - return app.resolve(event, context) +```python hl_lines="11" title="Enabling debug mode" +--8<-- "examples/event_handler_rest/src/debug_mode.py" ``` ### Custom serializer You can instruct API Gateway handler to use a custom serializer to best suit your needs, for example take into account Enums when serializing. -```python hl_lines="21-22 26" title="Using a custom JSON serializer for responses" -import json -from enum import Enum -from json import JSONEncoder -from typing import Dict - -from aws_lambda_powertools.event_handler import APIGatewayRestResolver - -class CustomEncoder(JSONEncoder): - """Your customer json encoder""" - def default(self, obj): - if isinstance(obj, Enum): - return obj.value - try: - iterable = iter(obj) - except TypeError: - pass - else: - return sorted(iterable) - return JSONEncoder.default(self, obj) - -def custom_serializer(obj) -> str: - """Your custom serializer function APIGatewayRestResolver will use""" - return json.dumps(obj, cls=CustomEncoder) - -# Assigning your custom serializer -app = APIGatewayRestResolver(serializer=custom_serializer) - -class Color(Enum): - RED = 1 - BLUE = 2 - -@app.get("/colors") -def get_color() -> Dict: - return { - # Color.RED will be serialized to 1 as expected now - "color": Color.RED, - "variations": {"light", "dark"}, - } +```python hl_lines="35 40" title="Using a custom JSON serializer for responses" +--8<-- "examples/event_handler_rest/src/custom_serializer.py" ``` ### Split routes with Router As you grow the number of routes a given Lambda function should handle, it is natural to split routes into separate files to ease maintenance - That's where the `Router` feature is useful. -Let's assume you have `app.py` as your Lambda function entrypoint and routes in `users.py`, this is how you'd use the `Router` feature. +Let's assume you have `app.py` as your Lambda function entrypoint and routes in `todos.py`, this is how you'd use the `Router` feature. -=== "users.py" +=== "todos.py" We import **Router** instead of **APIGatewayRestResolver**; syntax wise is exactly the same. - ```python hl_lines="5 8 12 15 21" - import itertools - from typing import Dict - - from aws_lambda_powertools import Logger - from aws_lambda_powertools.event_handler.api_gateway import Router - - logger = Logger(child=True) - router = Router() - USERS = {"user1": "details_here", "user2": "details_here", "user3": "details_here"} - - - @router.get("/users") - def get_users() -> Dict: - # /users?limit=1 - pagination_limit = router.current_event.get_query_string_value(name="limit", default_value=10) - - logger.info(f"Fetching the first {pagination_limit} users...") - ret = dict(itertools.islice(USERS.items(), int(pagination_limit))) - return {"items": [ret]} - - @router.get("/users/") - def get_user(username: str) -> Dict: - logger.info(f"Fetching username {username}") - return {"details": USERS.get(username, {})} - - # many other related /users routing + ```python hl_lines="5 13 16 25 28" + --8<-- "examples/event_handler_rest/src/split_route_module.py" ``` === "app.py" We use `include_router` method and include all user routers registered in the `router` global object. - ```python hl_lines="7 10-11" - from typing import Dict - - from aws_lambda_powertools import Logger - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - from aws_lambda_powertools.utilities.typing import LambdaContext - - import users - - logger = Logger() - app = APIGatewayRestResolver() - app.include_router(users.router) - - - def lambda_handler(event: Dict, context: LambdaContext): - return app.resolve(event, context) + ```python hl_lines="11" + --8<-- "examples/event_handler_rest/src/split_route.py" ``` #### Route prefix -In the previous example, `users.py` routes had a `/users` prefix. This might grow over time and become repetitive. +In the previous example, `todos.py` routes had a `/todos` prefix. This might grow over time and become repetitive. -When necessary, you can set a prefix when including a router object. This means you could remove `/users` prefix in `users.py` altogether. +When necessary, you can set a prefix when including a router object. This means you could remove `/todos` prefix in `todos.py` altogether. === "app.py" - ```python hl_lines="9" - from typing import Dict - - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - from aws_lambda_powertools.utilities.typing import LambdaContext - - import users - - app = APIGatewayRestResolver() - app.include_router(users.router, prefix="/users") # prefix '/users' to any route in `users.router` - - - def lambda_handler(event: Dict, context: LambdaContext): - return app.resolve(event, context) + ```python hl_lines="12" + --8<-- "examples/event_handler_rest/src/split_route_prefix.py" ``` -=== "users.py" - - ```python hl_lines="11 15" - from typing import Dict - - from aws_lambda_powertools import Logger - from aws_lambda_powertools.event_handler.api_gateway import Router - - logger = Logger(child=True) - router = Router() - USERS = {"user1": "details", "user2": "details", "user3": "details"} - +=== "todos.py" - @router.get("/") # /users, when we set the prefix in app.py - def get_users() -> Dict: - ... - - @router.get("/") - def get_user(username: str) -> Dict: - ... - - # many other related /users routing + ```python hl_lines="13 25" + --8<-- "examples/event_handler_rest/src/split_route_prefix_module.py" ``` #### Sample layout -This sample project contains a Users function with two distinct set of routes, `/users` and `/health`. The layout optimizes for code sharing, no custom build tooling, and it uses [Lambda Layers](../../index.md#lambda-layer) to install Lambda Powertools. - -=== "Project layout" - - ```python hl_lines="1 8 10 12-15" - . - ├── Pipfile # project app & dev dependencies; poetry, pipenv, etc. - ├── Pipfile.lock - ├── README.md - ├── src - │ ├── __init__.py - │ ├── requirements.txt # sam build detect it automatically due to CodeUri: src, e.g. pipenv lock -r > src/requirements.txt - │ └── users - │ ├── __init__.py - │ ├── main.py # this will be our users Lambda fn; it could be split in folders if we want separate fns same code base - │ └── routers # routers module - │ ├── __init__.py - │ ├── health.py # /users routes, e.g. from routers import users; users.router - │ └── users.py # /users routes, e.g. from .routers import users; users.router - ├── template.yml # SAM template.yml, CodeUri: src, Handler: users.main.lambda_handler - └── tests +This is a sample project layout for a monolithic function with routes split in different files (`/todos`, `/health`). + +```shell hl_lines="4 7 10 12-13" title="Sample project layout" +. +├── pyproject.toml # project app & dev dependencies; poetry, pipenv, etc. +├── poetry.lock +├── src +│ ├── __init__.py +│ ├── requirements.txt # sam build detect it automatically due to CodeUri: src. poetry export --format src/requirements.txt +│ └── todos +│ ├── __init__.py +│ ├── main.py # this will be our todos Lambda fn; it could be split in folders if we want separate fns same code base +│ └── routers # routers module +│ ├── __init__.py +│ ├── health.py # /health routes. from routers import todos; health.router +│ └── todos.py # /todos routes. from .routers import todos; todos.router +├── template.yml # SAM. CodeUri: src, Handler: todos.main.lambda_handler +└── tests + ├── __init__.py + ├── unit + │ ├── __init__.py + │ └── test_todos.py # unit tests for the todos router + │ └── test_health.py # unit tests for the health router + └── functional ├── __init__.py - ├── unit - │ ├── __init__.py - │ └── test_users.py # unit tests for the users router - │ └── test_health.py # unit tests for the health router - └── functional - ├── __init__.py - ├── conftest.py # pytest fixtures for the functional tests - └── test_main.py # functional tests for the main lambda handler - ``` - -=== "template.yml" - - ```yaml hl_lines="22-23" - AWSTemplateFormatVersion: '2010-09-09' - Transform: AWS::Serverless-2016-10-31 - Description: Example service with multiple routes - Globals: - Function: - Timeout: 10 - MemorySize: 512 - Runtime: python3.9 - Tracing: Active - Architectures: - - x86_64 - Environment: - Variables: - LOG_LEVEL: INFO - POWERTOOLS_LOGGER_LOG_EVENT: true - POWERTOOLS_METRICS_NAMESPACE: MyServerlessApplication - POWERTOOLS_SERVICE_NAME: users - Resources: - UsersService: - Type: AWS::Serverless::Function - Properties: - Handler: users.main.lambda_handler - CodeUri: src - Layers: - # Latest version: https://awslabs.github.io/aws-lambda-powertools-python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:4 - Events: - ByUser: - Type: Api - Properties: - Path: /users/{name} - Method: GET - AllUsers: - Type: Api - Properties: - Path: /users - Method: GET - HealthCheck: - Type: Api - Properties: - Path: /status - Method: GET - Outputs: - UsersApiEndpoint: - Description: "API Gateway endpoint URL for Prod environment for Users Function" - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod" - AllUsersURL: - Description: "URL to fetch all registered users" - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/users" - ByUserURL: - Description: "URL to retrieve details by user" - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/users/test" - UsersServiceFunctionArn: - Description: "Users Lambda Function ARN" - Value: !GetAtt UsersService.Arn - ``` - -=== "src/users/main.py" - - ```python hl_lines="8 14-15" - from typing import Dict - - from aws_lambda_powertools import Logger, Tracer - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - from aws_lambda_powertools.logging.correlation_paths import APPLICATION_LOAD_BALANCER - from aws_lambda_powertools.utilities.typing import LambdaContext - - from .routers import health, users - - tracer = Tracer() - logger = Logger() - app = APIGatewayRestResolver() - - app.include_router(health.router) - app.include_router(users.router) - - - @logger.inject_lambda_context(correlation_id_path=API_GATEWAY_REST) - @tracer.capture_lambda_handler - def lambda_handler(event: Dict, context: LambdaContext): - return app.resolve(event, context) - ``` - -=== "src/users/routers/health.py" - - ```python hl_lines="4 6-7 10" - from typing import Dict - - from aws_lambda_powertools import Logger - from aws_lambda_powertools.event_handler.api_gateway import Router - - router = Router() - logger = Logger(child=True) - - - @router.get("/status") - def health() -> Dict: - logger.debug("Health check called") - return {"status": "OK"} - ``` - -=== "tests/functional/test_users.py" - - ```python hl_lines="3" - import json - - from src.users import main # follows namespace package from root - - - def test_lambda_handler(apigw_event, lambda_context): - ret = main.lambda_handler(apigw_event, lambda_context) - expected = json.dumps({"message": "hello universe"}, separators=(",", ":")) - - assert ret["statusCode"] == 200 - assert ret["body"] == expected - ``` + ├── conftest.py # pytest fixtures for the functional tests + └── test_main.py # functional tests for the main lambda handler +``` ### Considerations @@ -1342,53 +511,14 @@ You can test your routes by passing a proxy event request where `path` and `http === "test_app.py" - ```python hl_lines="18-24" - from dataclasses import dataclass - - import pytest - import app - - @pytest.fixture - def lambda_context(): - @dataclass - class LambdaContext: - function_name: str = "test" - memory_limit_in_mb: int = 128 - invoked_function_arn: str = "arn:aws:lambda:eu-west-1:809313241:function:test" - aws_request_id: str = "52fdfc07-2182-154f-163f-5f0f9a621d72" - - return LambdaContext() - - def test_lambda_handler(lambda_context): - minimal_event = { - "path": "/hello", - "httpMethod": "GET", - "requestContext": { # correlation ID - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef" - } - } - - app.lambda_handler(minimal_event, lambda_context) + ```python hl_lines="21-24" + --8<-- "examples/event_handler_rest/src/assert_http_response.py" ``` === "app.py" ```python - from aws_lambda_powertools import Logger - from aws_lambda_powertools.logging import correlation_paths - from aws_lambda_powertools.event_handler import APIGatewayRestResolver - - logger = Logger() - app = APIGatewayRestResolver() # API Gateway REST API (v1) - - @app.get("/hello") - def get_hello_universe(): - return {"message": "hello universe"} - - # You can continue to use other utilities just as before - @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) - def lambda_handler(event, context): - return app.resolve(event, context) + --8<-- "examples/event_handler_rest/src/assert_http_response_module.py" ``` ## FAQ diff --git a/docs/core/logger.md b/docs/core/logger.md index 23d57e251b9..b09cc6c85d3 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -14,6 +14,9 @@ Logger provides an opinionated logger with output structured as JSON. ## Getting started +???+ tip + All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}. + Logger requires two settings: | Setting | Description | Environment variable | Constructor parameter | diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 24a8f1e6fda..713a53b193c 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -28,6 +28,9 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar ## Getting started +???+ tip + All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}. + Metric has two global settings that will be used across all metrics emitted: | Setting | Description | Environment variable | Constructor parameter | diff --git a/docs/core/tracer.md b/docs/core/tracer.md index c8037eff241..7664231cc31 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -16,6 +16,9 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github. ## Getting started +???+ tip + All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}. + ### Permissions Before your use this utility, your AWS Lambda function [must have permissions](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html#services-xray-permissions) to send traces to AWS X-Ray. diff --git a/examples/event_handler_rest/sam/template.yaml b/examples/event_handler_rest/sam/template.yaml new file mode 100644 index 00000000000..f9837e729a5 --- /dev/null +++ b/examples/event_handler_rest/sam/template.yaml @@ -0,0 +1,56 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: Hello world event handler API Gateway + +Globals: + Api: + TracingEnabled: true + Cors: # see CORS section + AllowOrigin: "'https://example.com'" + AllowHeaders: "'Content-Type,Authorization,X-Amz-Date'" + MaxAge: "'300'" + BinaryMediaTypes: # see Binary responses section + - "*~1*" # converts to */* for any binary type + Function: + Timeout: 5 + Runtime: python3.8 + Tracing: Active + Environment: + Variables: + LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + POWERTOOLS_SERVICE_NAME: example + +Resources: + ApiFunction: + Type: AWS::Serverless::Function + Properties: + Handler: app.lambda_handler + CodeUri: api_handler/ + Description: API handler function + Events: + AnyApiEvent: + Type: Api + Properties: + # NOTE: this is a catch-all rule to simplify the documentation. + # explicit routes and methods are recommended for prod instead (see below) + Path: /{proxy+} # Send requests on any path to the lambda function + Method: ANY # Send requests using any http method to the lambda function + + + # GetAllTodos: + # Type: Api + # Properties: + # Path: /todos + # Method: GET + # GetTodoById: + # Type: Api + # Properties: + # Path: /todos/{todo_id} + # Method: GET + # CreateTodo: + # Type: Api + # Properties: + # Path: /todos + # Method: POST diff --git a/examples/event_handler_rest/src/accessing_request_details.py b/examples/event_handler_rest/src/accessing_request_details.py new file mode 100644 index 00000000000..9929b601db0 --- /dev/null +++ b/examples/event_handler_rest/src/accessing_request_details.py @@ -0,0 +1,40 @@ +from typing import Optional + +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todo_id: str = app.current_event.get_query_string_value(name="id", default_value="") + # alternatively + _: Optional[str] = app.current_event.query_string_parameters.get("id") + + # Payload + _: Optional[str] = app.current_event.body # raw str | None + + endpoint = "https://jsonplaceholder.typicode.com/todos" + if todo_id: + endpoint = f"{endpoint}/{todo_id}" + + todos: Response = requests.get(endpoint) + todos.raise_for_status() + + return {"todos": todos.json()} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/accessing_request_details_headers.py b/examples/event_handler_rest/src/accessing_request_details_headers.py new file mode 100644 index 00000000000..f6bfb88c869 --- /dev/null +++ b/examples/event_handler_rest/src/accessing_request_details_headers.py @@ -0,0 +1,30 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + endpoint = "https://jsonplaceholder.typicode.com/todos" + + api_key: str = app.current_event.get_header_value(name="X-Api-Key", case_sensitive=True, default_value="") + todos: Response = requests.get(endpoint, headers={"X-Api-Key": api_key}) + todos.raise_for_status() + + return {"todos": todos.json()} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/assert_http_response.py b/examples/event_handler_rest/src/assert_http_response.py new file mode 100644 index 00000000000..95d56599288 --- /dev/null +++ b/examples/event_handler_rest/src/assert_http_response.py @@ -0,0 +1,28 @@ +from dataclasses import dataclass + +import assert_http_response_module +import pytest + + +@pytest.fixture +def lambda_context(): + @dataclass + class LambdaContext: + function_name: str = "test" + memory_limit_in_mb: int = 128 + invoked_function_arn: str = "arn:aws:lambda:eu-west-1:123456789012:function:test" + aws_request_id: str = "da658bd3-2d6f-4e7b-8ec2-937234644fdc" + + return LambdaContext() + + +def test_lambda_handler(lambda_context): + minimal_event = { + "path": "/todos", + "httpMethod": "GET", + "requestContext": {"requestId": "227b78aa-779d-47d4-a48e-ce62120393b8"}, # correlation ID + } + + ret = assert_http_response_module.lambda_handler(minimal_event, lambda_context) + assert ret["statusCode"] == 200 + assert ret["body"] != "" diff --git a/examples/event_handler_rest/src/assert_http_response_module.py b/examples/event_handler_rest/src/assert_http_response_module.py new file mode 100644 index 00000000000..ea5d839fb72 --- /dev/null +++ b/examples/event_handler_rest/src/assert_http_response_module.py @@ -0,0 +1,27 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/binary_responses.json b/examples/event_handler_rest/src/binary_responses.json new file mode 100644 index 00000000000..fcdf86dfebe --- /dev/null +++ b/examples/event_handler_rest/src/binary_responses.json @@ -0,0 +1,8 @@ +{ + "headers": { + "Accept": "image/svg+xml" + }, + "resource": "/logo", + "path": "/logo", + "httpMethod": "GET" +} diff --git a/examples/event_handler_rest/src/binary_responses.py b/examples/event_handler_rest/src/binary_responses.py new file mode 100644 index 00000000000..00c027937b8 --- /dev/null +++ b/examples/event_handler_rest/src/binary_responses.py @@ -0,0 +1,27 @@ +import os +from pathlib import Path + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, Response +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() + + +app = APIGatewayRestResolver() +logo_file: bytes = Path(os.getenv("LAMBDA_TASK_ROOT") + "/logo.svg").read_bytes() + + +@app.get("/logo") +@tracer.capture_method +def get_logo(): + return Response(status_code=200, content_type="image/svg+xml", body=logo_file) + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/binary_responses_logo.svg b/examples/event_handler_rest/src/binary_responses_logo.svg new file mode 100644 index 00000000000..fccb29e01ed --- /dev/null +++ b/examples/event_handler_rest/src/binary_responses_logo.svg @@ -0,0 +1,14 @@ + + + AWS Lambda + + + + + + + + + + + diff --git a/examples/event_handler_rest/src/binary_responses_output.json b/examples/event_handler_rest/src/binary_responses_output.json new file mode 100644 index 00000000000..0938dee6811 --- /dev/null +++ b/examples/event_handler_rest/src/binary_responses_output.json @@ -0,0 +1,8 @@ +{ + "body": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjU2cHgiIGhlaWdodD0iMjU2cHgiIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4KICAgIDx0aXRsZT5BV1MgTGFtYmRhPC90aXRsZT4KICAgIDxkZWZzPgogICAgICAgIDxsaW5lYXJHcmFkaWVudCB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMTAwJSIgeTI9IjAlIiBpZD0ibGluZWFyR3JhZGllbnQtMSI+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNDODUxMUIiIG9mZnNldD0iMCUiPjwvc3RvcD4KICAgICAgICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI0ZGOTkwMCIgb2Zmc2V0PSIxMDAlIj48L3N0b3A+CiAgICAgICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDwvZGVmcz4KICAgIDxnPgogICAgICAgIDxyZWN0IGZpbGw9InVybCgjbGluZWFyR3JhZGllbnQtMSkiIHg9IjAiIHk9IjAiIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2Ij48L3JlY3Q+CiAgICAgICAgPHBhdGggZD0iTTg5LjYyNDExMjYsMjExLjIgTDQ5Ljg5MDMyNzcsMjExLjIgTDkzLjgzNTQ4MzIsMTE5LjM0NzIgTDExMy43NDcyOCwxNjAuMzM5MiBMODkuNjI0MTEyNiwyMTEuMiBaIE05Ni43MDI5MzU3LDExMC41Njk2IEM5Ni4xNjQwODU4LDEwOS40NjU2IDk1LjA0MTQ4MTMsMTA4Ljc2NDggOTMuODE2MjM4NCwxMDguNzY0OCBMOTMuODA2NjE2MywxMDguNzY0OCBDOTIuNTcxNzUxNCwxMDguNzY4IDkxLjQ0OTE0NjYsMTA5LjQ3NTIgOTAuOTE5OTE4NywxMTAuNTg1NiBMNDEuOTEzNDIwOCwyMTMuMDIwOCBDNDEuNDM4NzE5NywyMTQuMDEyOCA0MS41MDYwNzU4LDIxNS4xNzc2IDQyLjA5NjI0NTEsMjE2LjEwODggQzQyLjY3OTk5OTQsMjE3LjAzNjggNDMuNzA2MzgwNSwyMTcuNiA0NC44MDY1MzMxLDIxNy42IEw5MS42NTQ0MjMsMjE3LjYgQzkyLjg5NTcwMjcsMjE3LjYgOTQuMDIxNTE0OSwyMTYuODg2NCA5NC41NTM5NTAxLDIxNS43Njk2IEwxMjAuMjAzODU5LDE2MS42ODk2IEMxMjAuNjE3NjE5LDE2MC44MTI4IDEyMC42MTQ0MTIsMTU5Ljc5ODQgMTIwLjE4NzgyMiwxNTguOTI4IEw5Ni43MDI5MzU3LDExMC41Njk2IFogTTIwNy45ODUxMTcsMjExLjIgTDE2OC41MDc5MjgsMjExLjIgTDEwNS4xNzM3ODksNzguNjI0IEMxMDQuNjQ0NTYxLDc3LjUxMDQgMTAzLjUxNTU0MSw3Ni44IDEwMi4yNzc0NjksNzYuOCBMNzYuNDQ3OTQzLDc2LjggTDc2LjQ3NjgwOTksNDQuOCBMMTI3LjEwMzA2Niw0NC44IEwxOTAuMTQ1MzI4LDE3Ny4zNzI4IEMxOTAuNjc0NTU2LDE3OC40ODY0IDE5MS44MDM1NzUsMTc5LjIgMTkzLjA0MTY0NywxNzkuMiBMMjA3Ljk4NTExNywxNzkuMiBMMjA3Ljk4NTExNywyMTEuMiBaIE0yMTEuMTkyNTU4LDE3Mi44IEwxOTUuMDcxOTU4LDE3Mi44IEwxMzIuMDI5Njk2LDQwLjIyNzIgQzEzMS41MDA0NjgsMzkuMTEzNiAxMzAuMzcxNDQ5LDM4LjQgMTI5LjEzMDE2OSwzOC40IEw3My4yNzI1NzYsMzguNCBDNzEuNTA1Mjc1OCwzOC40IDcwLjA2ODM0MjEsMzkuODMwNCA3MC4wNjUxMzQ0LDQxLjU5NjggTDcwLjAyOTg1MjgsNzkuOTk2OCBDNzAuMDI5ODUyOCw4MC44NDggNzAuMzYzNDI2Niw4MS42NjA4IDcwLjk2OTYzMyw4Mi4yNjI0IEM3MS41Njk0MjQ2LDgyLjg2NCA3Mi4zODQxMTQ2LDgzLjIgNzMuMjM3Mjk0MSw4My4yIEwxMDAuMjUzNTczLDgzLjIgTDE2My41OTA5MiwyMTUuNzc2IEMxNjQuMTIzMzU1LDIxNi44ODk2IDE2NS4yNDU5NiwyMTcuNiAxNjYuNDg0MDMyLDIxNy42IEwyMTEuMTkyNTU4LDIxNy42IEMyMTIuOTY2Mjc0LDIxNy42IDIxNC40LDIxNi4xNjY0IDIxNC40LDIxNC40IEwyMTQuNCwxNzYgQzIxNC40LDE3NC4yMzM2IDIxMi45NjYyNzQsMTcyLjggMjExLjE5MjU1OCwxNzIuOCBMMjExLjE5MjU1OCwxNzIuOCBaIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICA8L2c+Cjwvc3ZnPg==", + "headers": { + "Content-Type": "image/svg+xml" + }, + "isBase64Encoded": true, + "statusCode": 200 +} diff --git a/examples/event_handler_rest/src/compressing_responses.json b/examples/event_handler_rest/src/compressing_responses.json new file mode 100644 index 00000000000..f706df20d58 --- /dev/null +++ b/examples/event_handler_rest/src/compressing_responses.json @@ -0,0 +1,8 @@ +{ + "headers": { + "Accept-Encoding": "gzip" + }, + "resource": "/todos", + "path": "/todos", + "httpMethod": "GET" +} diff --git a/examples/event_handler_rest/src/compressing_responses.py b/examples/event_handler_rest/src/compressing_responses.py new file mode 100644 index 00000000000..1af4b9a58b2 --- /dev/null +++ b/examples/event_handler_rest/src/compressing_responses.py @@ -0,0 +1,28 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get("/todos", compress=True) +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/compressing_responses_output.json b/examples/event_handler_rest/src/compressing_responses_output.json new file mode 100644 index 00000000000..0836b3aa726 --- /dev/null +++ b/examples/event_handler_rest/src/compressing_responses_output.json @@ -0,0 +1,9 @@ +{ + "statusCode": 200, + "headers": { + "Content-Type": "application/json", + "Content-Encoding": "gzip" + }, + "body": "H4sIAAAAAAACE42STU4DMQyFrxJl3QXln96AMyAW7sSDLCVxiJ0Kqerd8TCCUOgii1EmP/783pOPXjmw+N3L0TfB+hz8brvxtC5KGtHvfMCIkzZx0HT5MPmNnziViIr2dIYoeNr8Q1x3xHsjcVadIbkZJoq2RXU8zzQROLseQ9505NzeCNQdMJNBE+UmY4zbzjAJhWtlZ57sB84BWtul+rteH2HPlVgWARwjqXkxpklK5gmEHAQqJBMtFsGVygcKmNVRjG0wxvuzGF2L0dpVUOKMC3bfJNjJgWMrCuZk7cUp02AiD72D6WKHHwUDKbiJs6AZ0VZXKOUx4uNvzdxT+E4mLcMA+6G8nzrLQkaxkNEVrFKW2VGbJCoCY7q2V3+tiv5kGThyxfTecDWbgGz/NfYXhL6ePgF9PnFdPgMAAA==", + "isBase64Encoded": true +} diff --git a/examples/event_handler_rest/src/custom_api_mapping.json b/examples/event_handler_rest/src/custom_api_mapping.json new file mode 100644 index 00000000000..eb1d68afbf9 --- /dev/null +++ b/examples/event_handler_rest/src/custom_api_mapping.json @@ -0,0 +1,5 @@ +{ + "resource": "/subscriptions/{subscription}", + "path": "/payment/subscriptions/123", + "httpMethod": "GET" +} diff --git a/examples/event_handler_rest/src/custom_api_mapping.py b/examples/event_handler_rest/src/custom_api_mapping.py new file mode 100644 index 00000000000..0b180d54f01 --- /dev/null +++ b/examples/event_handler_rest/src/custom_api_mapping.py @@ -0,0 +1,20 @@ +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver(strip_prefixes=["/payment"]) + + +@app.get("/subscriptions/") +@tracer.capture_method +def get_subscription(subscription): + return {"subscription_id": subscription} + + +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/custom_serializer.py b/examples/event_handler_rest/src/custom_serializer.py new file mode 100644 index 00000000000..cfb8cefd2d9 --- /dev/null +++ b/examples/event_handler_rest/src/custom_serializer.py @@ -0,0 +1,58 @@ +import json +from dataclasses import asdict, dataclass, is_dataclass +from json import JSONEncoder + +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@dataclass +class Todo: + userId: str + id: str # noqa: A003 VNE003 "id" field is reserved + title: str + completed: bool + + +class DataclassCustomEncoder(JSONEncoder): + """A custom JSON encoder to serialize dataclass obj""" + + def default(self, obj): + # Only called for values that aren't JSON serializable + # where `obj` will be an instance of Todo in this example + return asdict(obj) if is_dataclass(obj) else super().default(obj) + + +def custom_serializer(obj) -> str: + """Your custom serializer function APIGatewayRestResolver will use""" + return json.dumps(obj, separators=(",", ":"), cls=DataclassCustomEncoder) + + +app = APIGatewayRestResolver(serializer=custom_serializer) + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + ret: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + ret.raise_for_status() + todos = [Todo(**todo) for todo in ret.json()] + + # for brevity, we'll limit to the first 10 only + return {"todos": todos[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/debug_mode.py b/examples/event_handler_rest/src/debug_mode.py new file mode 100644 index 00000000000..47ffb8905eb --- /dev/null +++ b/examples/event_handler_rest/src/debug_mode.py @@ -0,0 +1,28 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver(debug=True) + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/dynamic_routes.json b/examples/event_handler_rest/src/dynamic_routes.json new file mode 100644 index 00000000000..23e8261d283 --- /dev/null +++ b/examples/event_handler_rest/src/dynamic_routes.json @@ -0,0 +1,5 @@ +{ + "resource": "/todos/{id}", + "path": "/todos/1", + "httpMethod": "GET" +} diff --git a/examples/event_handler_rest/src/dynamic_routes.py b/examples/event_handler_rest/src/dynamic_routes.py new file mode 100644 index 00000000000..2ee2dc21044 --- /dev/null +++ b/examples/event_handler_rest/src/dynamic_routes.py @@ -0,0 +1,27 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get("/todos/") +@tracer.capture_method +def get_todo_by_id(todo_id: str): # value come as str + todos: Response = requests.get(f"https://jsonplaceholder.typicode.com/todos/{todo_id}") + todos.raise_for_status() + + return {"todos": todos.json()} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/dynamic_routes_catch_all.json b/examples/event_handler_rest/src/dynamic_routes_catch_all.json new file mode 100644 index 00000000000..c9395f23027 --- /dev/null +++ b/examples/event_handler_rest/src/dynamic_routes_catch_all.json @@ -0,0 +1,5 @@ +{ + "resource": "/{proxy+}", + "path": "/any/route/should/work", + "httpMethod": "GET" +} diff --git a/examples/event_handler_rest/src/dynamic_routes_catch_all.py b/examples/event_handler_rest/src/dynamic_routes_catch_all.py new file mode 100644 index 00000000000..f615f2a8dee --- /dev/null +++ b/examples/event_handler_rest/src/dynamic_routes_catch_all.py @@ -0,0 +1,21 @@ +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get(".+") +@tracer.capture_method +def catch_any_route_get_method(): + return {"path_received": app.current_event.path} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/exception_handling.py b/examples/event_handler_rest/src/exception_handling.py new file mode 100644 index 00000000000..fdac8589299 --- /dev/null +++ b/examples/event_handler_rest/src/exception_handling.py @@ -0,0 +1,43 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, content_types +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.exception_handler(ValueError) +def handle_invalid_limit_qs(ex: ValueError): # receives exception raised + metadata = {"path": app.current_event.path, "query_strings": app.current_event.query_string_parameters} + logger.error(f"Malformed request: {ex}", extra=metadata) + + return Response( + status_code=400, + content_type=content_types.TEXT_PLAIN, + body="Invalid request parameters.", + ) + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + # educational purpose only: we should receive a `ValueError` + # if a query string value for `limit` cannot be coerced to int + max_results: int = int(app.current_event.get_query_string_value(name="limit", default_value=0)) + + todos: Response = requests.get(f"https://jsonplaceholder.typicode.com/todos?limit={max_results}") + todos.raise_for_status() + + return {"todos": todos.json()} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/fine_grained_responses.py b/examples/event_handler_rest/src/fine_grained_responses.py new file mode 100644 index 00000000000..3e477160307 --- /dev/null +++ b/examples/event_handler_rest/src/fine_grained_responses.py @@ -0,0 +1,36 @@ +from http import HTTPStatus +from uuid import uuid4 + +import requests + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response, content_types +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: requests.Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + custom_headers = {"X-Transaction-Id": f"{uuid4()}"} + + return Response( + status_code=HTTPStatus.OK.value, # 200 + content_type=content_types.APPLICATION_JSON, + body=todos.json()[:10], + headers=custom_headers, + ) + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/fine_grained_responses_output.json b/examples/event_handler_rest/src/fine_grained_responses_output.json new file mode 100644 index 00000000000..c3d58098e80 --- /dev/null +++ b/examples/event_handler_rest/src/fine_grained_responses_output.json @@ -0,0 +1,9 @@ +{ + "statusCode": 200, + "headers": { + "Content-Type": "application/json", + "X-Transaction-Id": "3490eea9-791b-47a0-91a4-326317db61a9" + }, + "body": "{\"todos\":[{\"userId\":1,\"id\":1,\"title\":\"delectus aut autem\",\"completed\":false},{\"userId\":1,\"id\":2,\"title\":\"quis ut nam facilis et officia qui\",\"completed\":false},{\"userId\":1,\"id\":3,\"title\":\"fugiat veniam minus\",\"completed\":false},{\"userId\":1,\"id\":4,\"title\":\"et porro tempora\",\"completed\":true},{\"userId\":1,\"id\":5,\"title\":\"laboriosam mollitia et enim quasi adipisci quia provident illum\",\"completed\":false},{\"userId\":1,\"id\":6,\"title\":\"qui ullam ratione quibusdam voluptatem quia omnis\",\"completed\":false},{\"userId\":1,\"id\":7,\"title\":\"illo expedita consequatur quia in\",\"completed\":false},{\"userId\":1,\"id\":8,\"title\":\"quo adipisci enim quam ut ab\",\"completed\":true},{\"userId\":1,\"id\":9,\"title\":\"molestiae perspiciatis ipsa\",\"completed\":false},{\"userId\":1,\"id\":10,\"title\":\"illo est ratione doloremque quia maiores aut\",\"completed\":true}]}", + "isBase64Encoded": false +} diff --git a/examples/event_handler_rest/src/getting_started_alb_api_resolver.py b/examples/event_handler_rest/src/getting_started_alb_api_resolver.py new file mode 100644 index 00000000000..612823625ec --- /dev/null +++ b/examples/event_handler_rest/src/getting_started_alb_api_resolver.py @@ -0,0 +1,28 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import ALBResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = ALBResolver() + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.APPLICATION_LOAD_BALANCER) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/getting_started_http_api_resolver.py b/examples/event_handler_rest/src/getting_started_http_api_resolver.py new file mode 100644 index 00000000000..e976ef4169f --- /dev/null +++ b/examples/event_handler_rest/src/getting_started_http_api_resolver.py @@ -0,0 +1,28 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayHttpResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayHttpResolver() + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/getting_started_rest_api_resolver.json b/examples/event_handler_rest/src/getting_started_rest_api_resolver.json new file mode 100644 index 00000000000..92d3e40f139 --- /dev/null +++ b/examples/event_handler_rest/src/getting_started_rest_api_resolver.json @@ -0,0 +1,58 @@ +{ + "body": "", + "resource": "/todos", + "path": "/todos", + "httpMethod": "GET", + "isBase64Encoded": false, + "queryStringParameters": {}, + "multiValueQueryStringParameters": {}, + "pathParameters": {}, + "stageVariables": {}, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "multiValueHeaders": {}, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "Prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "25/Jul/2020:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/Prod/todos", + "resourcePath": "/todos", + "httpMethod": "GET", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } +} diff --git a/examples/event_handler_rest/src/getting_started_rest_api_resolver.py b/examples/event_handler_rest/src/getting_started_rest_api_resolver.py new file mode 100644 index 00000000000..3b30b5810f2 --- /dev/null +++ b/examples/event_handler_rest/src/getting_started_rest_api_resolver.py @@ -0,0 +1,28 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/getting_started_rest_api_resolver_output.json b/examples/event_handler_rest/src/getting_started_rest_api_resolver_output.json new file mode 100644 index 00000000000..2ef3714531f --- /dev/null +++ b/examples/event_handler_rest/src/getting_started_rest_api_resolver_output.json @@ -0,0 +1,8 @@ +{ + "statusCode": 200, + "headers": { + "Content-Type": "application/json" + }, + "body": "{\"todos\":[{\"userId\":1,\"id\":1,\"title\":\"delectus aut autem\",\"completed\":false},{\"userId\":1,\"id\":2,\"title\":\"quis ut nam facilis et officia qui\",\"completed\":false},{\"userId\":1,\"id\":3,\"title\":\"fugiat veniam minus\",\"completed\":false},{\"userId\":1,\"id\":4,\"title\":\"et porro tempora\",\"completed\":true},{\"userId\":1,\"id\":5,\"title\":\"laboriosam mollitia et enim quasi adipisci quia provident illum\",\"completed\":false},{\"userId\":1,\"id\":6,\"title\":\"qui ullam ratione quibusdam voluptatem quia omnis\",\"completed\":false},{\"userId\":1,\"id\":7,\"title\":\"illo expedita consequatur quia in\",\"completed\":false},{\"userId\":1,\"id\":8,\"title\":\"quo adipisci enim quam ut ab\",\"completed\":true},{\"userId\":1,\"id\":9,\"title\":\"molestiae perspiciatis ipsa\",\"completed\":false},{\"userId\":1,\"id\":10,\"title\":\"illo est ratione doloremque quia maiores aut\",\"completed\":true}]}", + "isBase64Encoded": false +} diff --git a/examples/event_handler_rest/src/http_methods.json b/examples/event_handler_rest/src/http_methods.json new file mode 100644 index 00000000000..e0f775d72df --- /dev/null +++ b/examples/event_handler_rest/src/http_methods.json @@ -0,0 +1,6 @@ +{ + "resource": "/todos", + "path": "/todos", + "httpMethod": "POST", + "body": "{\"title\": \"foo\", \"userId\": 1, \"completed\": false}" +} diff --git a/examples/event_handler_rest/src/http_methods.py b/examples/event_handler_rest/src/http_methods.py new file mode 100644 index 00000000000..47eb1499a38 --- /dev/null +++ b/examples/event_handler_rest/src/http_methods.py @@ -0,0 +1,28 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.post("/todos") +@tracer.capture_method +def create_todo(): + todo_data: dict = app.current_event.json_body # deserialize json str to dict + todo: Response = requests.post("https://jsonplaceholder.typicode.com/todos", data=todo_data) + todo.raise_for_status() + + return {"todo": todo.json()} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/http_methods_multiple.py b/examples/event_handler_rest/src/http_methods_multiple.py new file mode 100644 index 00000000000..a482c96d80f --- /dev/null +++ b/examples/event_handler_rest/src/http_methods_multiple.py @@ -0,0 +1,29 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +# PUT and POST HTTP requests to the path /hello will route to this function +@app.route("/todos", method=["PUT", "POST"]) +@tracer.capture_method +def create_todo(): + todo_data: dict = app.current_event.json_body # deserialize json str to dict + todo: Response = requests.post("https://jsonplaceholder.typicode.com/todos", data=todo_data) + todo.raise_for_status() + + return {"todo": todo.json()} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/not_found_routes.py b/examples/event_handler_rest/src/not_found_routes.py new file mode 100644 index 00000000000..889880292c0 --- /dev/null +++ b/examples/event_handler_rest/src/not_found_routes.py @@ -0,0 +1,35 @@ +import requests + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response, content_types +from aws_lambda_powertools.event_handler.exceptions import NotFoundError +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.not_found +@tracer.capture_method +def handle_not_found_errors(exc: NotFoundError) -> Response: + logger.info(f"Not found route: {app.current_event.path}") + return Response(status_code=418, content_type=content_types.TEXT_PLAIN, body="I'm a teapot!") + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: requests.Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/raising_http_errors.py b/examples/event_handler_rest/src/raising_http_errors.py new file mode 100644 index 00000000000..97e7cc5048f --- /dev/null +++ b/examples/event_handler_rest/src/raising_http_errors.py @@ -0,0 +1,59 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.event_handler.exceptions import ( + BadRequestError, + InternalServerError, + NotFoundError, + ServiceError, + UnauthorizedError, +) +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() + + +@app.get(rule="/bad-request-error") +def bad_request_error(): + raise BadRequestError("Missing required parameter") # HTTP 400 + + +@app.get(rule="/unauthorized-error") +def unauthorized_error(): + raise UnauthorizedError("Unauthorized") # HTTP 401 + + +@app.get(rule="/not-found-error") +def not_found_error(): + raise NotFoundError # HTTP 404 + + +@app.get(rule="/internal-server-error") +def internal_server_error(): + raise InternalServerError("Internal server error") # HTTP 500 + + +@app.get(rule="/service-error", cors=True) +def service_error(): + raise ServiceError(502, "Something went wrong!") + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + return {"todos": todos.json()[:10]} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/setting_cors.py b/examples/event_handler_rest/src/setting_cors.py new file mode 100644 index 00000000000..101e013e552 --- /dev/null +++ b/examples/event_handler_rest/src/setting_cors.py @@ -0,0 +1,44 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver, CORSConfig +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +cors_config = CORSConfig(allow_origin="https://example.com", max_age=300) +app = APIGatewayRestResolver(cors=cors_config) + + +@app.get("/todos") +@tracer.capture_method +def get_todos(): + todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +@app.get("/todos/") +@tracer.capture_method +def get_todo_by_id(todo_id: str): # value come as str + todos: Response = requests.get(f"https://jsonplaceholder.typicode.com/todos/{todo_id}") + todos.raise_for_status() + + return {"todos": todos.json()} + + +@app.get("/healthcheck", cors=False) # optionally removes CORS for a given route +@tracer.capture_method +def am_i_alive(): + return {"am_i_alive": "yes"} + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/setting_cors_output.json b/examples/event_handler_rest/src/setting_cors_output.json new file mode 100644 index 00000000000..ca86e892d38 --- /dev/null +++ b/examples/event_handler_rest/src/setting_cors_output.json @@ -0,0 +1,10 @@ +{ + "statusCode": 200, + "headers": { + "Content-Type": "application/json", + "Access-Control-Allow-Origin": "https://www.example.com", + "Access-Control-Allow-Headers": "Authorization,Content-Type,X-Amz-Date,X-Amz-Security-Token,X-Api-Key" + }, + "body": "{\"todos\":[{\"userId\":1,\"id\":1,\"title\":\"delectus aut autem\",\"completed\":false},{\"userId\":1,\"id\":2,\"title\":\"quis ut nam facilis et officia qui\",\"completed\":false},{\"userId\":1,\"id\":3,\"title\":\"fugiat veniam minus\",\"completed\":false},{\"userId\":1,\"id\":4,\"title\":\"et porro tempora\",\"completed\":true},{\"userId\":1,\"id\":5,\"title\":\"laboriosam mollitia et enim quasi adipisci quia provident illum\",\"completed\":false},{\"userId\":1,\"id\":6,\"title\":\"qui ullam ratione quibusdam voluptatem quia omnis\",\"completed\":false},{\"userId\":1,\"id\":7,\"title\":\"illo expedita consequatur quia in\",\"completed\":false},{\"userId\":1,\"id\":8,\"title\":\"quo adipisci enim quam ut ab\",\"completed\":true},{\"userId\":1,\"id\":9,\"title\":\"molestiae perspiciatis ipsa\",\"completed\":false},{\"userId\":1,\"id\":10,\"title\":\"illo est ratione doloremque quia maiores aut\",\"completed\":true}]}", + "isBase64Encoded": false +} diff --git a/examples/event_handler_rest/src/split_route.py b/examples/event_handler_rest/src/split_route.py new file mode 100644 index 00000000000..6c0933ea08e --- /dev/null +++ b/examples/event_handler_rest/src/split_route.py @@ -0,0 +1,18 @@ +import split_route_module + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() +app.include_router(split_route_module.router) + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/split_route_module.py b/examples/event_handler_rest/src/split_route_module.py new file mode 100644 index 00000000000..eeb696ede56 --- /dev/null +++ b/examples/event_handler_rest/src/split_route_module.py @@ -0,0 +1,33 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Tracer +from aws_lambda_powertools.event_handler.api_gateway import Router + +tracer = Tracer() +router = Router() + +endpoint = "https://jsonplaceholder.typicode.com/todos" + + +@router.get("/todos") +@tracer.capture_method +def get_todos(): + api_key: str = router.current_event.get_header_value(name="X-Api-Key", case_sensitive=True, default_value="") + + todos: Response = requests.get(endpoint, headers={"X-Api-Key": api_key}) + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +@router.get("/todos/") +@tracer.capture_method +def get_todo_by_id(todo_id: str): # value come as str + api_key: str = router.current_event.get_header_value(name="X-Api-Key", case_sensitive=True, default_value="") + + todos: Response = requests.get(f"{endpoint}/{todo_id}", headers={"X-Api-Key": api_key}) + todos.raise_for_status() + + return {"todos": todos.json()} diff --git a/examples/event_handler_rest/src/split_route_prefix.py b/examples/event_handler_rest/src/split_route_prefix.py new file mode 100644 index 00000000000..01129c80148 --- /dev/null +++ b/examples/event_handler_rest/src/split_route_prefix.py @@ -0,0 +1,19 @@ +import split_route_module + +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.typing import LambdaContext + +tracer = Tracer() +logger = Logger() +app = APIGatewayRestResolver() +# prefix '/todos' to any route in `split_route_module.router` +app.include_router(split_route_module.router, prefix="/todos") + + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/split_route_prefix_module.py b/examples/event_handler_rest/src/split_route_prefix_module.py new file mode 100644 index 00000000000..b4035282776 --- /dev/null +++ b/examples/event_handler_rest/src/split_route_prefix_module.py @@ -0,0 +1,36 @@ +import requests +from requests import Response + +from aws_lambda_powertools import Tracer +from aws_lambda_powertools.event_handler.api_gateway import Router + +tracer = Tracer() +router = Router() + +endpoint = "https://jsonplaceholder.typicode.com/todos" + + +@router.get("/") +@tracer.capture_method +def get_todos(): + api_key: str = router.current_event.get_header_value(name="X-Api-Key", case_sensitive=True, default_value="") + + todos: Response = requests.get(endpoint, headers={"X-Api-Key": api_key}) + todos.raise_for_status() + + # for brevity, we'll limit to the first 10 only + return {"todos": todos.json()[:10]} + + +@router.get("/") +@tracer.capture_method +def get_todo_by_id(todo_id: str): # value come as str + api_key: str = router.current_event.get_header_value(name="X-Api-Key", case_sensitive=True, default_value="") + + todos: Response = requests.get(f"{endpoint}/{todo_id}", headers={"X-Api-Key": api_key}) + todos.raise_for_status() + + return {"todos": todos.json()} + + +# many more routes From a34d34d066e8e5fb086f831d3f382aa20f23f005 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Thu, 7 Jul 2022 16:52:02 +0200 Subject: [PATCH 13/30] chore(ci): fix reference error in related_issue --- .github/scripts/label_related_issue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/label_related_issue.js b/.github/scripts/label_related_issue.js index 8f851056cb3..fb47a7bc4b0 100644 --- a/.github/scripts/label_related_issue.js +++ b/.github/scripts/label_related_issue.js @@ -6,7 +6,7 @@ module.exports = async ({github, context}) => { const RELATED_ISSUE_REGEX = /Issue number:[^\d\r\n]+(?\d+)/; - const isMatch = RELATED_ISSUE_REGEX.exec(body); + const isMatch = RELATED_ISSUE_REGEX.exec(prBody); if (!isMatch) { core.setFailed(`Unable to find related issue for PR number ${prNumber}.\n\n Body details: ${prBody}`); return await github.rest.issues.createComment({ From ad86b1018af1275d8d74f7299cb3aa214d9a8979 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 17:03:43 +0200 Subject: [PATCH 14/30] fix: download artefact into the layer dir --- .github/workflows/reusable_deploy_layer_stack.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 31f8830931d..6ac646f2bd8 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -78,6 +78,7 @@ jobs: uses: actions/download-artifact@v3 with: name: ${{ inputs.artefact-name }} + path: layer - name: unzip artefact run: unzip ${{ inputs.artefact-name }} - name: CDK Deploy Layer From 1962f192917413d308fa26e8faa81e61d66fd135 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 17:46:28 +0200 Subject: [PATCH 15/30] fix: mathc the name of the cdk synth from the build phase --- .github/workflows/reusable_deploy_layer_stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 6ac646f2bd8..69f182c4189 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -80,7 +80,7 @@ jobs: name: ${{ inputs.artefact-name }} path: layer - name: unzip artefact - run: unzip ${{ inputs.artefact-name }} + run: unzip cdk.out.zip - name: CDK Deploy Layer run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerStack ' --require-approval never --verbose - name: CDK Deploy Canary From 2ded8a6481836da7bdccf7a005fbe31bdf9dbd68 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 7 Jul 2022 17:58:45 +0200 Subject: [PATCH 16/30] fix: sight, yes a whitespace character breaks the build --- .github/workflows/reusable_deploy_layer_stack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 69f182c4189..f03cb117d6f 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -82,6 +82,6 @@ jobs: - name: unzip artefact run: unzip cdk.out.zip - name: CDK Deploy Layer - run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerStack ' --require-approval never --verbose + run: cdk deploy --app cdk.out --context region=${{ matrix.region }} 'LayerStack' --require-approval never --verbose - name: CDK Deploy Canary run: cdk deploy --app cdk.out --context region=${{ matrix.region}} --parameters DeployStage="${{ inputs.stage }}" 'CanaryStack' --require-approval never --verbose From 3fd2d5ce3844dc02e9af720e1a0ef740b60ada74 Mon Sep 17 00:00:00 2001 From: Release bot Date: Mon, 18 Jul 2022 11:43:19 +0000 Subject: [PATCH 17/30] chore(ci): update project with version 1.26.4 --- CHANGELOG.md | 1972 +++++++++++++++++++++++++++++++++++------------- pyproject.toml | 2 +- 2 files changed, 1455 insertions(+), 519 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b0cc7b5a8..274ce07676c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,82 @@ + -# Changelog + +# Unreleased -All notable changes to this project will be documented in this file. -This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format for changes and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## 1.26.3 - 2022-07-04 + +## [v1.26.4] - 2022-07-18 +## Bug Fixes -### Bug Fixes +* **ci:** checkout project before validating related issue workflow +* **ci:** fixes typos and small issues on github scripts ([#1302](https://github.com/awslabs/aws-lambda-powertools-python/issues/1302)) +* **ci:** address conditional type on_merge +* **ci:** address pr title semantic not found logic +* **ci:** address gh-actions additional quotes; remove debug +* **ci:** regex group name for on_merge workflow +* **ci:** escape outputs as certain PRs can break GH Actions expressions +* **ci:** move conditionals from yaml to code; leftover +* **ci:** move conditionals from yaml to code +* **ci:** accept core arg in label related issue workflow +* **ci:** match the name of the cdk synth from the build phase +* **ci:** regex to catch combination of related issues workflow +* **logger:** preserve std keys when using custom formatters ([#1264](https://github.com/awslabs/aws-lambda-powertools-python/issues/1264)) +* **parser:** raise ValidationError when SNS->SQS keys are intentionally missing ([#1299](https://github.com/awslabs/aws-lambda-powertools-python/issues/1299)) + +## Documentation + +* **event-handler:** snippets split, improved, and lint ([#1279](https://github.com/awslabs/aws-lambda-powertools-python/issues/1279)) +* **graphql:** snippets split, improved, and lint ([#1287](https://github.com/awslabs/aws-lambda-powertools-python/issues/1287)) +* **homepage:** emphasize additional powertools languages ([#1292](https://github.com/awslabs/aws-lambda-powertools-python/issues/1292)) +* **metrics:** snippets split, improved, and lint + +## Maintenance + +* **ci:** increase release automation and limit to one manual step ([#1297](https://github.com/awslabs/aws-lambda-powertools-python/issues/1297)) +* **ci:** make export PR reusable +* **ci:** auto-merge cdk lib and lambda layer construct +* **ci:** convert inline gh-script to file +* **ci:** lockdown 3rd party workflows to pin sha ([#1301](https://github.com/awslabs/aws-lambda-powertools-python/issues/1301)) +* **ci:** automatically add area label based on title ([#1300](https://github.com/awslabs/aws-lambda-powertools-python/issues/1300)) +* **ci:** disable output debugging as pr body isnt accepted +* **ci:** experiment with conditional on outputs +* **ci:** improve error handling for non-issue numbers +* **ci:** add end to end testing mechanism ([#1247](https://github.com/awslabs/aws-lambda-powertools-python/issues/1247)) +* **ci:** limits concurrency for docs workflow +* **ci:** fix reference error in related_issue +* **ci:** move error prone env to code as constants +* **ci:** move all scripts under .github/scripts +* **deps:** bump cdk-lambda-powertools-python-layer ([#1284](https://github.com/awslabs/aws-lambda-powertools-python/issues/1284)) +* **deps:** bump jsii from 1.61.0 to 1.62.0 ([#1294](https://github.com/awslabs/aws-lambda-powertools-python/issues/1294)) +* **deps:** bump constructs from 10.1.1 to 10.1.46 ([#1306](https://github.com/awslabs/aws-lambda-powertools-python/issues/1306)) +* **deps:** bump actions/setup-node from 2 to 3 ([#1281](https://github.com/awslabs/aws-lambda-powertools-python/issues/1281)) +* **deps:** bump fastjsonschema from 2.15.3 to 2.16.1 ([#1309](https://github.com/awslabs/aws-lambda-powertools-python/issues/1309)) +* **deps:** bump constructs from 10.1.1 to 10.1.49 ([#1308](https://github.com/awslabs/aws-lambda-powertools-python/issues/1308)) +* **deps:** bump attrs from 21.2.0 to 21.4.0 ([#1282](https://github.com/awslabs/aws-lambda-powertools-python/issues/1282)) +* **deps:** bump aws-cdk-lib from 2.29.0 to 2.31.1 ([#1290](https://github.com/awslabs/aws-lambda-powertools-python/issues/1290)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.24.12 to 1.24.27 ([#1293](https://github.com/awslabs/aws-lambda-powertools-python/issues/1293)) +* **deps-dev:** bump mypy-boto3-appconfig from 1.24.0 to 1.24.29 ([#1295](https://github.com/awslabs/aws-lambda-powertools-python/issues/1295)) +* **governance:** remove any step relying on master branch +* **governance:** update emeritus affiliation +* **layers:** add release pipeline in GitHub Actions ([#1278](https://github.com/awslabs/aws-lambda-powertools-python/issues/1278)) +* **layers:** bump to 22 for 1.26.3 + + + +## [v1.26.3] - 2022-07-04 +## Bug Fixes +* **ci:** remove utf-8 body in octokit body req * **ci:** improve msg visibility on closed issues * **ci:** disable merged_pr workflow * **ci:** merged_pr add issues write access * **ci:** quote prBody GH expr on_opened_pr -* **ci:** remove utf-8 body in octokit body req * **ci:** reusable workflow secrets param -* **logger:** support additional args for handlers when injecting lambda context decorator ([#1276](https://github.com/awslabs/aws-lambda-powertools-python/issues/1276)) +* **logger:** support additional args for handlers when injecting lambda context ([#1276](https://github.com/awslabs/aws-lambda-powertools-python/issues/1276)) +* **logger:** preserve std keys when using custom formatters ([#1264](https://github.com/awslabs/aws-lambda-powertools-python/issues/1264)) -### Documentation +## Documentation * **lint:** add markdownlint rules and automation ([#1256](https://github.com/awslabs/aws-lambda-powertools-python/issues/1256)) * **logger:** document enriching logs with logrecord attributes ([#1271](https://github.com/awslabs/aws-lambda-powertools-python/issues/1271)) @@ -27,15 +85,16 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **tracer:** snippets split, improved, and lint ([#1261](https://github.com/awslabs/aws-lambda-powertools-python/issues/1261)) * **tracer:** split and lint code snippets ([#1260](https://github.com/awslabs/aws-lambda-powertools-python/issues/1260)) -### Maintenance +## Maintenance +* move to approach B for multiple IaC * add sam build gitignore -* **documentation**: move to approach B for multiple IaC +* bump to version 1.26.3 +* **ci:** reactivate on_merged_pr workflow * **ci:** improve wording on closed issues action * **ci:** deactivate on_merged_pr workflow -* **ci:** reactivate on_merged_pr workflow -* **deps:** bump dependabot/fetch-metadata from 1.1.1 to 1.3.2 ([#1269](https://github.com/awslabs/aws-lambda-powertools-python/issues/1269)) * **deps:** bump aws-xray-sdk from 2.9.0 to 2.10.0 ([#1270](https://github.com/awslabs/aws-lambda-powertools-python/issues/1270)) +* **deps:** bump dependabot/fetch-metadata from 1.1.1 to 1.3.2 ([#1269](https://github.com/awslabs/aws-lambda-powertools-python/issues/1269)) * **deps:** bump dependabot/fetch-metadata from 1.3.2 to 1.3.3 ([#1273](https://github.com/awslabs/aws-lambda-powertools-python/issues/1273)) * **deps-dev:** bump flake8-bugbear from 22.6.22 to 22.7.1 ([#1274](https://github.com/awslabs/aws-lambda-powertools-python/issues/1274)) * **deps-dev:** bump flake8-bugbear from 22.4.25 to 22.6.22 ([#1258](https://github.com/awslabs/aws-lambda-powertools-python/issues/1258)) @@ -46,78 +105,98 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **layers:** bump to 21 for 1.26.2 * **test-perf:** use pytest-benchmark to improve reliability ([#1250](https://github.com/awslabs/aws-lambda-powertools-python/issues/1250)) -## 1.26.2 - 2022-06-16 -### Bug Fixes + +## [v1.26.2] - 2022-06-16 +## Bug Fixes * **event-handler:** body to empty string in CORS preflight (ALB non-compliant) ([#1249](https://github.com/awslabs/aws-lambda-powertools-python/issues/1249)) -### Maintenance +## Code Refactoring + +* rename to clear_state +* rename to remove_custom_keys + +## Documentation + +* fix anchor + +## Features +* **logger:** add option to clear state per invocation + +## Maintenance + +* bump to 1.26.2 * **deps:** bump actions/setup-python from 3 to 4 ([#1244](https://github.com/awslabs/aws-lambda-powertools-python/issues/1244)) * **deps-dev:** bump mypy from 0.960 to 0.961 ([#1241](https://github.com/awslabs/aws-lambda-powertools-python/issues/1241)) * **deps-dev:** bump mypy-boto3-ssm from 1.23.0.post1 to 1.24.0 ([#1231](https://github.com/awslabs/aws-lambda-powertools-python/issues/1231)) * **deps-dev:** bump mypy-boto3-secretsmanager from 1.23.8 to 1.24.0 ([#1232](https://github.com/awslabs/aws-lambda-powertools-python/issues/1232)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.23.0.post1 to 1.24.0 ([#1234](https://github.com/awslabs/aws-lambda-powertools-python/issues/1234)) * **deps-dev:** bump mypy-boto3-appconfig from 1.23.0.post1 to 1.24.0 ([#1233](https://github.com/awslabs/aws-lambda-powertools-python/issues/1233)) -* **governance:** fix workflow action requirements & syntax -* **governance:** add release label on pr merge * **governance:** auto-merge on all PR events +* **governance:** add release label on pr merge * **governance:** enforce safe scope on pr merge labelling +* **governance:** limit build workflow to code changes only * **governance:** auto-merge workflow_dispatch off * **governance:** auto-merge to use squash -* **governance:** limit build workflow to code changes only -* **governance:** auto-merge mypy-stub dependabot * **governance:** check for related issue in new PRs +* **governance:** auto-merge mypy-stub dependabot * **governance:** address gh reusable workflow limitation +* **governance:** fix workflow action requirements & syntax * **governance:** warn message on closed issues * **metrics:** revert dimensions test before splitting ([#1243](https://github.com/awslabs/aws-lambda-powertools-python/issues/1243)) -## 1.26.1 - 2022-06-07 -### Bug Fixes + +## [v1.26.1] - 2022-06-07 +## Bug Fixes * **metrics:** raise SchemaValidationError for >8 metric dimensions ([#1240](https://github.com/awslabs/aws-lambda-powertools-python/issues/1240)) -### Documentation +## Documentation * **governance:** link roadmap and maintainers doc * **maintainers:** initial maintainers playbook ([#1222](https://github.com/awslabs/aws-lambda-powertools-python/issues/1222)) * **roadmap:** use pinned pause issue instead -### Maintenance +## Maintenance +* bump version 1.26.1 * **deps-dev:** bump mypy from 0.950 to 0.960 ([#1224](https://github.com/awslabs/aws-lambda-powertools-python/issues/1224)) * **deps-dev:** bump mypy-boto3-secretsmanager from 1.23.0.post1 to 1.23.8 ([#1225](https://github.com/awslabs/aws-lambda-powertools-python/issues/1225)) -## 1.26.0 - 2022-05-20 -### Bug Fixes + +## [v1.26.0] - 2022-05-20 +## Bug Fixes * **batch:** missing space in BatchProcessingError message ([#1201](https://github.com/awslabs/aws-lambda-powertools-python/issues/1201)) * **batch:** docstring fix for success_handler() record parameter ([#1202](https://github.com/awslabs/aws-lambda-powertools-python/issues/1202)) * **docs:** remove Slack link ([#1210](https://github.com/awslabs/aws-lambda-powertools-python/issues/1210)) -### Documentation +## Documentation * **layer:** upgrade to 1.25.10 * **roadmap:** add new roadmap section ([#1204](https://github.com/awslabs/aws-lambda-powertools-python/issues/1204)) -### Features +## Features * **parameters:** accept boto3_client to support private endpoints and ease testing ([#1096](https://github.com/awslabs/aws-lambda-powertools-python/issues/1096)) -### Maintenance +## Maintenance +* bump to 1.26.0 * **deps:** bump pydantic from 1.9.0 to 1.9.1 ([#1221](https://github.com/awslabs/aws-lambda-powertools-python/issues/1221)) * **deps:** bump email-validator from 1.1.3 to 1.2.1 ([#1199](https://github.com/awslabs/aws-lambda-powertools-python/issues/1199)) * **deps-dev:** bump mypy-boto3-secretsmanager from 1.21.34 to 1.23.0.post1 ([#1218](https://github.com/awslabs/aws-lambda-powertools-python/issues/1218)) * **deps-dev:** bump mypy-boto3-appconfig from 1.21.34 to 1.23.0.post1 ([#1219](https://github.com/awslabs/aws-lambda-powertools-python/issues/1219)) * **deps-dev:** bump mypy-boto3-ssm from 1.21.34 to 1.23.0.post1 ([#1220](https://github.com/awslabs/aws-lambda-powertools-python/issues/1220)) -## 1.25.10 - 2022-04-29 -### Bug Fixes + +## [v1.25.10] - 2022-04-29 +## Bug Fixes * **data-classes:** Add missing SES fields and ([#1045](https://github.com/awslabs/aws-lambda-powertools-python/issues/1045)) * **deps:** Ignore boto3 changes until needed ([#1151](https://github.com/awslabs/aws-lambda-powertools-python/issues/1151)) @@ -126,73 +205,86 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **event_handler:** Allow for event_source support ([#1159](https://github.com/awslabs/aws-lambda-powertools-python/issues/1159)) * **parser:** Add missing fields for SESEvent ([#1027](https://github.com/awslabs/aws-lambda-powertools-python/issues/1027)) -### Documentation +## Documentation * **layer:** upgrade to 1.25.9 -### Features +## Features * **parameters:** add clear_cache method for providers ([#1194](https://github.com/awslabs/aws-lambda-powertools-python/issues/1194)) -### Maintenance +## Maintenance +* include regression in changelog +* bump to 1.25.10 * **ci:** changelog pre-generation to fetch tags from origin -* **ci:** post release on tagged issues too * **ci:** disable mergify configuration after breaking changes ([#1188](https://github.com/awslabs/aws-lambda-powertools-python/issues/1188)) +* **ci:** post release on tagged issues too * **deps:** bump codecov/codecov-action from 3.0.0 to 3.1.0 ([#1143](https://github.com/awslabs/aws-lambda-powertools-python/issues/1143)) * **deps:** bump github/codeql-action from 1 to 2 ([#1154](https://github.com/awslabs/aws-lambda-powertools-python/issues/1154)) -* **deps-dev:** bump flake8-bugbear from 22.1.11 to 22.4.25 ([#1156](https://github.com/awslabs/aws-lambda-powertools-python/issues/1156)) * **deps-dev:** bump flake8-eradicate from 1.2.0 to 1.2.1 ([#1158](https://github.com/awslabs/aws-lambda-powertools-python/issues/1158)) -* **deps-dev:** bump mkdocs-git-revision-date-plugin ([#1146](https://github.com/awslabs/aws-lambda-powertools-python/issues/1146)) * **deps-dev:** bump mypy from 0.942 to 0.950 ([#1162](https://github.com/awslabs/aws-lambda-powertools-python/issues/1162)) +* **deps-dev:** bump mkdocs-git-revision-date-plugin ([#1146](https://github.com/awslabs/aws-lambda-powertools-python/issues/1146)) +* **deps-dev:** bump flake8-bugbear from 22.1.11 to 22.4.25 ([#1156](https://github.com/awslabs/aws-lambda-powertools-python/issues/1156)) * **deps-dev:** bump xenon from 0.8.0 to 0.9.0 ([#1145](https://github.com/awslabs/aws-lambda-powertools-python/issues/1145)) * **deps-dev:** bump mypy from 0.931 to 0.942 ([#1133](https://github.com/awslabs/aws-lambda-powertools-python/issues/1133)) -### Regression +## Regression * **parser:** Add missing fields for SESEvent ([#1027](https://github.com/awslabs/aws-lambda-powertools-python/issues/1027)) ([#1190](https://github.com/awslabs/aws-lambda-powertools-python/issues/1190)) -## 1.25.9 - 2022-04-21 -### Bug Fixes + +## [v1.25.9] - 2022-04-21 +## Bug Fixes + +* **deps:** correct py36 marker for jmespath + +## Maintenance -* **deps**: correct py36 marker for jmespath +* bump to 1.25.9 -## 1.25.8 - 2022-04-21 -### Bug Fixes + +## [v1.25.8] - 2022-04-21 +## Bug Fixes -* **governance:** removed ambiguous quotes from labels +* removed ambiguous quotes from labels. * **deps:** update jmespath marker to support 1.0 and py3.6 ([#1139](https://github.com/awslabs/aws-lambda-powertools-python/issues/1139)) * **governance:** update label in names in issues -### Documentation +## Documentation * **install:** instructions to reduce pydantic package size ([#1077](https://github.com/awslabs/aws-lambda-powertools-python/issues/1077)) * **layer:** remove link from clipboard button ([#1135](https://github.com/awslabs/aws-lambda-powertools-python/issues/1135)) * **layer:** update to 1.25.7 -### Maintenance +## Maintenance +* bump to 1.25.8 * **deps:** bump codecov/codecov-action from 2.1.0 to 3.0.0 ([#1102](https://github.com/awslabs/aws-lambda-powertools-python/issues/1102)) * **deps:** bump actions/upload-artifact from 2 to 3 ([#1103](https://github.com/awslabs/aws-lambda-powertools-python/issues/1103)) * **deps-dev:** bump mkdocs-material from 8.2.4 to 8.2.7 ([#1131](https://github.com/awslabs/aws-lambda-powertools-python/issues/1131)) * **deps-dev:** bump pytest from 6.2.5 to 7.0.1 ([#1063](https://github.com/awslabs/aws-lambda-powertools-python/issues/1063)) -## 1.25.7 - 2022-04-08 -### Bug Fixes + +## [v1.25.7] - 2022-04-08 +## Bug Fixes -* **idempotency:** pass by value on idem key to guard inadvertent mutations ([#1090](https://github.com/awslabs/aws-lambda-powertools-python/issues/1090)) +* **api_gateway:** allow whitespace in routes' path parameter ([#1099](https://github.com/awslabs/aws-lambda-powertools-python/issues/1099)) +* **api_gateway:** allow whitespace in routes' path parameter ([#1099](https://github.com/awslabs/aws-lambda-powertools-python/issues/1099)) +* **idempotency:** pass by value on idem key to guard inadvert mutations ([#1090](https://github.com/awslabs/aws-lambda-powertools-python/issues/1090)) * **logger:** clear_state should keep custom key formats ([#1095](https://github.com/awslabs/aws-lambda-powertools-python/issues/1095)) * **middleware_factory:** ret type annotation for handler dec ([#1066](https://github.com/awslabs/aws-lambda-powertools-python/issues/1066)) -### Documentation +## Documentation * **layer:** update to 1.25.6; cosmetic changes -### Maintenance +## Maintenance +* bump to 1.25.7 * **governance:** refresh pull request template sections * **governance:** update external non-triage effort disclaimer * **governance:** update static typing to a form @@ -204,109 +296,187 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **governance:** new ask a question * **governance:** new static typing report -## 1.25.6 - 2022-04-01 -* **logger:** clear_state regression on absent standard keys like level, location, timestamp ([#1088](https://github.com/awslabs/aws-lambda-powertools-python/issues/1088)) + +## [v1.25.6] - 2022-04-01 +## Bug Fixes + +* **logger:** clear_state regression on absent standard keys ([#1088](https://github.com/awslabs/aws-lambda-powertools-python/issues/1088)) + +## Documentation + +* **layer:** bump to 1.25.5 + +## Maintenance + +* bump to 1.25.6 + + + +## [v1.25.5] - 2022-03-18 +## Bug Fixes + +* **logger-utils:** regression on exclude set leading to no formatter ([#1080](https://github.com/awslabs/aws-lambda-powertools-python/issues/1080)) + +## Maintenance + +* bump to 1.25.5 + + + +## [v1.25.4] - 2022-03-17 +## Bug Fixes -## 1.25.5 - 2022-03-18 +* package_logger as const over logger instance +* repurpose test to cover parent loggers case +* use addHandler over monkeypatch -### Bug Fixes +## Documentation -* **logger-utils:** regression on exclude set leading to no formatter on append_keys ([#1080](https://github.com/awslabs/aws-lambda-powertools-python/issues/1080)) +* **appsync:** fix typo +* **contributing:** operational excellence pause +* **layer:** update to 1.25.3 -## 1.25.4 - 2022-03-17 +## Maintenance -### Bug Fixes +* bump to 1.25.4 +* remove duplicate test +* comment reason for change +* remove unnecessary test +* lint unused import -* **logger-utils**: ensure external loggers doesn't propagate logs when copying config +## Regression -### Documentation +* service_name fixture -* **appsync:** fix typo on `listLocations` return -* **contributing:** pause new features/enhancements over operational excellence focus +## Pull Requests -## 1.25.3 - 2022-03-09 +* Merge pull request [#1075](https://github.com/awslabs/aws-lambda-powertools-python/issues/1075) from mploski/fix/existing-loggers-duplicated-logs -### Bug Fixes + + +## [v1.25.3] - 2022-03-09 +## Bug Fixes * **logger:** ensure state is cleared for custom formatters ([#1072](https://github.com/awslabs/aws-lambda-powertools-python/issues/1072)) -### Documentation +## Documentation * **plugin:** add mermaid to create diagram as code ([#1070](https://github.com/awslabs/aws-lambda-powertools-python/issues/1070)) -## 1.25.2 - 2022-03-07 +## Maintenance + +* bump to 1.25.3 -### Bug Fixes -* **event_handler:** high-level import CorsConfig, docs snippets ([#1019](https://github.com/awslabs/aws-lambda-powertools-python/issues/1019)) + +## [v1.25.2] - 2022-03-07 +## Bug Fixes + +* **event_handler:** docs snippets, high-level import CorsConfig ([#1019](https://github.com/awslabs/aws-lambda-powertools-python/issues/1019)) * **lambda-authorizer:** allow proxy resources path in arn ([#1051](https://github.com/awslabs/aws-lambda-powertools-python/issues/1051)) * **metrics:** flush upon a single metric 100th data point ([#1046](https://github.com/awslabs/aws-lambda-powertools-python/issues/1046)) -### Documentation +## Documentation * **layer:** update to 1.25.1 * **parser:** APIGatewayProxyEvent to APIGatewayProxyEventModel ([#1061](https://github.com/awslabs/aws-lambda-powertools-python/issues/1061)) -### Maintenance +## Maintenance +* bump to 1.25.2 * **deps:** bump actions/setup-python from 2.3.1 to 3 ([#1048](https://github.com/awslabs/aws-lambda-powertools-python/issues/1048)) * **deps:** bump actions/checkout from 2 to 3 ([#1052](https://github.com/awslabs/aws-lambda-powertools-python/issues/1052)) * **deps:** bump actions/github-script from 5 to 6 ([#1023](https://github.com/awslabs/aws-lambda-powertools-python/issues/1023)) * **deps:** bump fastjsonschema from 2.15.2 to 2.15.3 ([#949](https://github.com/awslabs/aws-lambda-powertools-python/issues/949)) * **deps-dev:** bump mkdocs-material from 8.1.9 to 8.2.4 ([#1054](https://github.com/awslabs/aws-lambda-powertools-python/issues/1054)) -## 1.25.1 - 2022-02-14 -### Bug Fixes + +## [v1.25.1] - 2022-02-14 +## Bug Fixes + +* **batch:** bugfix to clear exceptions between executions ([#1022](https://github.com/awslabs/aws-lambda-powertools-python/issues/1022)) -**batch:** bugfix to clear exceptions between executions ([#1022](https://github.com/awslabs/aws-lambda-powertools-python/issues/1022)) +## Maintenance -## 1.25.0 - 2022-02-09 +* bump to 1.25.1 +* **layers:** bump to 10 for 1.25.0 -### Bug Fixes + + +## [v1.25.0] - 2022-02-09 +## Bug Fixes * **apigateway:** remove indentation in debug_mode ([#987](https://github.com/awslabs/aws-lambda-powertools-python/issues/987)) +* **batch:** delete >10 messages in legacy sqs processor ([#818](https://github.com/awslabs/aws-lambda-powertools-python/issues/818)) * **ci:** pr label regex for special chars in title * **logger:** exclude source_logger in copy_config_to_registered_loggers ([#1001](https://github.com/awslabs/aws-lambda-powertools-python/issues/1001)) * **logger:** test generates logfile -### Documentation +## Documentation +* fix syntax errors and line highlights ([#1004](https://github.com/awslabs/aws-lambda-powertools-python/issues/1004)) +* add better BDD coments * **event-handler:** improve testing section for graphql ([#996](https://github.com/awslabs/aws-lambda-powertools-python/issues/996)) * **layer:** update to 1.24.2 +* **parameters:** add testing your code section ([#1017](https://github.com/awslabs/aws-lambda-powertools-python/issues/1017)) * **theme:** upgrade mkdocs-material to 8.x ([#1002](https://github.com/awslabs/aws-lambda-powertools-python/issues/1002)) * **tutorial:** fix broken internal links ([#1000](https://github.com/awslabs/aws-lambda-powertools-python/issues/1000)) -* **general:** fix syntax errors and line highlights ([#1004](https://github.com/awslabs/aws-lambda-powertools-python/pull/1004)) -### Features +## Features * **event-handler:** new resolvers to fix current_event typing ([#978](https://github.com/awslabs/aws-lambda-powertools-python/issues/978)) * **logger:** log_event support event data classes (e.g. S3Event) ([#984](https://github.com/awslabs/aws-lambda-powertools-python/issues/984)) * **mypy:** complete mypy support for the entire codebase ([#943](https://github.com/awslabs/aws-lambda-powertools-python/issues/943)) -### Maintenance +## Maintenance +* bump to 1.25.0 +* correct docs +* correct docs +* use isinstance over type * **deps-dev:** bump flake8-bugbear from 21.11.29 to 22.1.11 ([#955](https://github.com/awslabs/aws-lambda-powertools-python/issues/955)) * **metrics:** fix tests when warnings are disabled ([#994](https://github.com/awslabs/aws-lambda-powertools-python/issues/994)) -## 1.24.2 - 2022-01-21 +## Pull Requests -### Bug Fixes +* Merge pull request [#971](https://github.com/awslabs/aws-lambda-powertools-python/issues/971) from gyft/fix-logger-util-tests -* **data-classes**: underscore support in api gateway authorizer resource name -## 1.24.1 - 2022-01-20 + +## [v1.24.2] - 2022-01-21 +## Bug Fixes + +* **data-classes:** underscore support in api gateway authorizer resource name ([#969](https://github.com/awslabs/aws-lambda-powertools-python/issues/969)) + +## Documentation + +* **layer:** update to 1.24.1 -### Bug Fixes +## Maintenance + +* bump to 1.24.2 + + + +## [v1.24.1] - 2022-01-20 +## Bug Fixes +* remove unused json import +* remove apigw contract when using event-handler, apigw tracing +* use decorators, split cold start to ease reading +* incorrect log keys, indentation, snippet consistency +* remove f-strings that doesn't evaluate expr * **batch:** report multiple failures ([#967](https://github.com/awslabs/aws-lambda-powertools-python/issues/967)) * **data-classes:** docstring typos and clean up ([#937](https://github.com/awslabs/aws-lambda-powertools-python/issues/937)) * **parameters:** appconfig internal _get docstrings ([#934](https://github.com/awslabs/aws-lambda-powertools-python/issues/934)) -### Documentation +## Documentation * rename quickstart to tutorial in readme +* rename to tutorial given the size +* add final consideration section * **batch:** snippet typo on batch processed messages iteration ([#951](https://github.com/awslabs/aws-lambda-powertools-python/issues/951)) * **batch:** fix typo in context manager keyword ([#938](https://github.com/awslabs/aws-lambda-powertools-python/issues/938)) * **homepage:** link to typescript version ([#950](https://github.com/awslabs/aws-lambda-powertools-python/issues/950)) @@ -315,33 +485,61 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **nav:** make REST and GraphQL event handlers more explicit ([#959](https://github.com/awslabs/aws-lambda-powertools-python/issues/959)) * **quickstart:** expand on intro line * **quickstart:** tidy requirements up +* **quickstart:** make section agnostic to json lib * **quickstart:** same process for Logger * **quickstart:** add sub-sections, fix highlight & code * **quickstart:** sentence fragmentation, tidy up -* **quickstart:** make section agnostic to json lib * **tenets:** make core, non-core more explicit -* **tracer:** update ServiceLens image w/ API GW, copywriting * **tracer:** warning to note on local traces * **tracer:** add initial image, requirements * **tracer:** add annotation, metadata, and image +* **tracer:** update ServiceLens image w/ API GW, copywriting +* **tutorial:** fix path to images ([#963](https://github.com/awslabs/aws-lambda-powertools-python/issues/963)) + +## Features + +* **ci:** auto-notify & close issues on release +* **logger:** clone powertools logger config to any Python logger ([#927](https://github.com/awslabs/aws-lambda-powertools-python/issues/927)) + +## Maintenance + +* bump to 1.24.1 +* bump to 1.24.1 +* **ci:** run codeql analysis on push only +* **ci:** fix mergify dependabot queue +* **ci:** add queue name in mergify +* **ci:** remove mergify legacy key +* **ci:** update mergify bot breaking change +* **ci:** safely label PR based on title +* **deps:** bump pydantic from 1.8.2 to 1.9.0 ([#933](https://github.com/awslabs/aws-lambda-powertools-python/issues/933)) +* **deps-dev:** bump mypy from 0.930 to 0.931 ([#941](https://github.com/awslabs/aws-lambda-powertools-python/issues/941)) + +## Regression -## 1.24.0 - 2021-12-31 +* order to APP logger/service name due to screenshots -### Bug Fixes +## Pull Requests + +* Merge pull request [#769](https://github.com/awslabs/aws-lambda-powertools-python/issues/769) from mploski/docs/quick-start + + + +## [v1.24.0] - 2021-12-31 +## Bug Fixes * **apigateway:** support [@app](https://github.com/app).not_found() syntax & housekeeping ([#926](https://github.com/awslabs/aws-lambda-powertools-python/issues/926)) * **event-sources:** handle dynamodb null type as none, not bool ([#929](https://github.com/awslabs/aws-lambda-powertools-python/issues/929)) -* **warning:** future distutils deprecation in 3.12 ([#921](https://github.com/awslabs/aws-lambda-powertools-python/issues/921)) +* **warning:** future distutils deprecation ([#921](https://github.com/awslabs/aws-lambda-powertools-python/issues/921)) -### Documentation +## Documentation -* **general**: consistency round admonitions and snippets ([#919](https://github.com/awslabs/aws-lambda-powertools-python/issues/919)) -* **homepage**: Added GraphQL Sample API to Examples section of README.md ([#930](https://github.com/awslabs/aws-lambda-powertools-python/issues/930)) +* consistency around admonitions and snippets ([#919](https://github.com/awslabs/aws-lambda-powertools-python/issues/919)) +* Added GraphQL Sample API to Examples section of README.md ([#930](https://github.com/awslabs/aws-lambda-powertools-python/issues/930)) * **batch:** remove leftover from legacy * **layer:** bump Lambda Layer to version 6 * **tracer:** new ignore_endpoint feature ([#931](https://github.com/awslabs/aws-lambda-powertools-python/issues/931)) -### Features +## Features * **event-sources:** cache parsed json in data class ([#909](https://github.com/awslabs/aws-lambda-powertools-python/issues/909)) * **feature_flags:** support beyond boolean values (JSON values) ([#804](https://github.com/awslabs/aws-lambda-powertools-python/issues/804)) @@ -349,28 +547,30 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **logger:** support use_datetime_directive for timestamps ([#920](https://github.com/awslabs/aws-lambda-powertools-python/issues/920)) * **tracer:** ignore tracing for certain hostname(s) or url(s) ([#910](https://github.com/awslabs/aws-lambda-powertools-python/issues/910)) -### Maintenance +## Maintenance +* bump to 1.24.0 * **deps-dev:** bump mypy from 0.920 to 0.930 ([#925](https://github.com/awslabs/aws-lambda-powertools-python/issues/925)) -## 1.23.0 - 2021-12-20 -### Bug Fixes + +## [v1.23.0] - 2021-12-20 +## Bug Fixes * **apigateway:** allow list of HTTP methods in route method ([#838](https://github.com/awslabs/aws-lambda-powertools-python/issues/838)) -* **event-sources:** pass authorizer data to APIGatewayEventAuthorizer ([#897](https://github.com/awslabs/aws-lambda-powertools-python/issues/897)) +* **event-sources:** Pass authorizer data to APIGatewayEventAuthorizer ([#897](https://github.com/awslabs/aws-lambda-powertools-python/issues/897)) * **event-sources:** handle claimsOverrideDetails set to null ([#878](https://github.com/awslabs/aws-lambda-powertools-python/issues/878)) * **idempotency:** include decorated fn name in hash ([#869](https://github.com/awslabs/aws-lambda-powertools-python/issues/869)) * **metrics:** explicit type to single_metric ctx manager ([#865](https://github.com/awslabs/aws-lambda-powertools-python/issues/865)) -* **parameters:** mypy appconfig transform and return types ([#877](https://github.com/awslabs/aws-lambda-powertools-python/issues/877)) -* **parser:** mypy overload parse when using envelope ([#885](https://github.com/awslabs/aws-lambda-powertools-python/issues/885)) +* **parameters:** appconfig transform and return types ([#877](https://github.com/awslabs/aws-lambda-powertools-python/issues/877)) +* **parser:** overload parse when using envelope ([#885](https://github.com/awslabs/aws-lambda-powertools-python/issues/885)) * **parser:** kinesis sequence number is str, not int ([#907](https://github.com/awslabs/aws-lambda-powertools-python/issues/907)) * **parser:** mypy support for payload type override as models ([#883](https://github.com/awslabs/aws-lambda-powertools-python/issues/883)) * **tracer:** add warm start annotation (ColdStart=False) ([#851](https://github.com/awslabs/aws-lambda-powertools-python/issues/851)) -### Documentation +## Documentation -* **nav**: reference cloudformation custom resource helper (CRD) ([#914](https://github.com/awslabs/aws-lambda-powertools-python/issues/914)) +* external reference to cloudformation custom resource helper ([#914](https://github.com/awslabs/aws-lambda-powertools-python/issues/914)) * add new public Slack invite * disable search blur in non-prod env * update Lambda Layers version @@ -379,7 +579,7 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **appsync:** fix users.py typo to locations [#830](https://github.com/awslabs/aws-lambda-powertools-python/issues/830) * **lambda_layer:** fix CDK layer syntax -### Features +## Features * **apigateway:** add exception_handler support ([#898](https://github.com/awslabs/aws-lambda-powertools-python/issues/898)) * **apigateway:** access parent api resolver from router ([#842](https://github.com/awslabs/aws-lambda-powertools-python/issues/842)) @@ -387,99 +587,111 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo * **logger:** allow handler with custom kwargs signature ([#913](https://github.com/awslabs/aws-lambda-powertools-python/issues/913)) * **tracer:** add service annotation when service is set ([#861](https://github.com/awslabs/aws-lambda-powertools-python/issues/861)) -### Maintenance +## Maintenance -* minor housekeeping before release ([#912](https://github.com/awslabs/aws-lambda-powertools-python/issues/912)) * correct pr label order +* minor housekeeping before release ([#912](https://github.com/awslabs/aws-lambda-powertools-python/issues/912)) +* bump to 1.23.0 * **ci:** split latest docs workflow * **deps:** bump fastjsonschema from 2.15.1 to 2.15.2 ([#891](https://github.com/awslabs/aws-lambda-powertools-python/issues/891)) * **deps:** bump actions/setup-python from 2.2.2 to 2.3.0 ([#831](https://github.com/awslabs/aws-lambda-powertools-python/issues/831)) +* **deps:** bump aws-xray-sdk from 2.8.0 to 2.9.0 ([#876](https://github.com/awslabs/aws-lambda-powertools-python/issues/876)) * **deps:** support arm64 when developing locally ([#862](https://github.com/awslabs/aws-lambda-powertools-python/issues/862)) * **deps:** bump actions/setup-python from 2.3.0 to 2.3.1 ([#852](https://github.com/awslabs/aws-lambda-powertools-python/issues/852)) -* **deps:** bump aws-xray-sdk from 2.8.0 to 2.9.0 ([#876](https://github.com/awslabs/aws-lambda-powertools-python/issues/876)) -* **deps-dev:** bump mypy from 0.910 to 0.920 ([#903](https://github.com/awslabs/aws-lambda-powertools-python/issues/903)) * **deps-dev:** bump flake8 from 3.9.2 to 4.0.1 ([#789](https://github.com/awslabs/aws-lambda-powertools-python/issues/789)) * **deps-dev:** bump black from 21.10b0 to 21.11b1 ([#839](https://github.com/awslabs/aws-lambda-powertools-python/issues/839)) * **deps-dev:** bump black from 21.11b1 to 21.12b0 ([#872](https://github.com/awslabs/aws-lambda-powertools-python/issues/872)) +* **deps-dev:** bump mypy from 0.910 to 0.920 ([#903](https://github.com/awslabs/aws-lambda-powertools-python/issues/903)) -## 1.22.0 - 2021-11-17 - -Tenet update! We've updated **Idiomatic** tenet to **Progressive** to reflect the new Router feature in Event Handler, and more importantly the new wave of customers coming from SRE, Data Analysis, and Data Science background. - -* BEFORE: **Idiomatic**. Utilities follow programming language idioms and language-specific best practices. -* AFTER: **Progressive**. Utilities are designed to be incrementally adoptable for customers at any stage of their Serverless journey. They follow language idioms and their community’s common practices. -### Bug Fixes + +## [v1.22.0] - 2021-11-17 +## Bug Fixes -* **ci:** change supported python version from 3.6.1 to 3.6.2, bump black ([#807](https://github.com/awslabs/aws-lambda-powertools-python/issues/807)) +* change supported python version from 3.6.1 to 3.6.2, bump black ([#807](https://github.com/awslabs/aws-lambda-powertools-python/issues/807)) +* **ci:** comment custom publish version checker * **ci:** skip sync master on docs hotfix -* **parser:** body and query strings can be null or omitted in ApiGatewayProxyEventModel and ApiGatewayProxyEventV2Model ([#820](https://github.com/awslabs/aws-lambda-powertools-python/issues/820)) +* **parser:** body/QS can be null or omitted in apigw v1/v2 ([#820](https://github.com/awslabs/aws-lambda-powertools-python/issues/820)) -### Code Refactoring +## Code Refactoring * **apigateway:** Add BaseRouter and duplicate route check ([#757](https://github.com/awslabs/aws-lambda-powertools-python/issues/757)) -### Documentation +## Documentation -* **docs:** updated Lambda Layers definition & limitations. ([#775](https://github.com/awslabs/aws-lambda-powertools-python/issues/775)) -* **docs:** Idiomatic tenet updated to Progressive -* **docs:** use higher contrast font to improve accessibility ([#822](https://github.com/awslabs/aws-lambda-powertools-python/issues/822)) -* **docs:** fix indentation of SAM snippets in install section ([#778](https://github.com/awslabs/aws-lambda-powertools-python/issues/778)) -* **docs:** improve public lambda layer wording, add clipboard buttons to improve UX ([#762](https://github.com/awslabs/aws-lambda-powertools-python/issues/762)) -* **docs:** add amplify-cli instructions for public layer ([#754](https://github.com/awslabs/aws-lambda-powertools-python/issues/754)) -* **api-gateway:** add new router feature to allow route splitting in API Gateway and ALB ([#767](https://github.com/awslabs/aws-lambda-powertools-python/issues/767)) +* updated Lambda Layers definition & limitations. ([#775](https://github.com/awslabs/aws-lambda-powertools-python/issues/775)) +* Idiomatic tenet updated to Progressive +* use higher contrast font ([#822](https://github.com/awslabs/aws-lambda-powertools-python/issues/822)) +* use higher contrast font +* fix indentation of SAM snippets in install section ([#778](https://github.com/awslabs/aws-lambda-powertools-python/issues/778)) +* improve public lambda layer wording, clipboard buttons ([#762](https://github.com/awslabs/aws-lambda-powertools-python/issues/762)) +* add amplify-cli instructions for public layer ([#754](https://github.com/awslabs/aws-lambda-powertools-python/issues/754)) +* **api-gateway:** add support for new router feature ([#767](https://github.com/awslabs/aws-lambda-powertools-python/issues/767)) * **apigateway:** re-add sample layout, add considerations ([#826](https://github.com/awslabs/aws-lambda-powertools-python/issues/826)) -* **appsync:** add new router feature to allow GraphQL Resolver composition ([#821](https://github.com/awslabs/aws-lambda-powertools-python/issues/821)) +* **appsync:** add new router feature ([#821](https://github.com/awslabs/aws-lambda-powertools-python/issues/821)) * **idempotency:** add support for DynamoDB composite keys ([#808](https://github.com/awslabs/aws-lambda-powertools-python/issues/808)) * **tenets:** update Idiomatic tenet to Progressive ([#823](https://github.com/awslabs/aws-lambda-powertools-python/issues/823)) -* **docs:** remove Lambda Layer version tag -### Features +## Features * **apigateway:** add Router to allow large routing composition ([#645](https://github.com/awslabs/aws-lambda-powertools-python/issues/645)) * **appsync:** add Router to allow large resolver composition ([#776](https://github.com/awslabs/aws-lambda-powertools-python/issues/776)) * **data-classes:** ActiveMQ and RabbitMQ support ([#770](https://github.com/awslabs/aws-lambda-powertools-python/issues/770)) * **logger:** add ALB correlation ID support ([#816](https://github.com/awslabs/aws-lambda-powertools-python/issues/816)) -### Maintenance +## Maintenance -* **deps:** bump boto3 from 1.19.6 to 1.20.3 ([#809](https://github.com/awslabs/aws-lambda-powertools-python/issues/809)) +* fix var expr +* remove Lambda Layer version tag +* bump to 1.22.0 +* conditional to publish docs only attempt 3 +* conditional to publish docs only attempt 2 +* conditional to publish docs only * **deps:** bump boto3 from 1.18.58 to 1.18.59 ([#760](https://github.com/awslabs/aws-lambda-powertools-python/issues/760)) +* **deps:** bump boto3 from 1.18.56 to 1.18.58 ([#755](https://github.com/awslabs/aws-lambda-powertools-python/issues/755)) * **deps:** bump urllib3 from 1.26.4 to 1.26.5 ([#787](https://github.com/awslabs/aws-lambda-powertools-python/issues/787)) +* **deps:** bump boto3 from 1.19.6 to 1.20.3 ([#809](https://github.com/awslabs/aws-lambda-powertools-python/issues/809)) * **deps:** bump boto3 from 1.18.61 to 1.19.6 ([#783](https://github.com/awslabs/aws-lambda-powertools-python/issues/783)) -* **deps:** bump boto3 from 1.18.56 to 1.18.58 ([#755](https://github.com/awslabs/aws-lambda-powertools-python/issues/755)) -* **deps:** bump boto3 from 1.18.59 to 1.18.61 ([#766](https://github.com/awslabs/aws-lambda-powertools-python/issues/766)) * **deps:** bump boto3 from 1.20.3 to 1.20.5 ([#817](https://github.com/awslabs/aws-lambda-powertools-python/issues/817)) +* **deps:** bump boto3 from 1.18.59 to 1.18.61 ([#766](https://github.com/awslabs/aws-lambda-powertools-python/issues/766)) * **deps-dev:** bump coverage from 6.0.1 to 6.0.2 ([#764](https://github.com/awslabs/aws-lambda-powertools-python/issues/764)) * **deps-dev:** bump pytest-asyncio from 0.15.1 to 0.16.0 ([#782](https://github.com/awslabs/aws-lambda-powertools-python/issues/782)) * **deps-dev:** bump flake8-eradicate from 1.1.0 to 1.2.0 ([#784](https://github.com/awslabs/aws-lambda-powertools-python/issues/784)) -* **deps-dev:** bump flake8-comprehensions from 3.6.1 to 3.7.0 ([#759](https://github.com/awslabs/aws-lambda-powertools-python/issues/759)) * **deps-dev:** bump flake8-isort from 4.0.0 to 4.1.1 ([#785](https://github.com/awslabs/aws-lambda-powertools-python/issues/785)) -* **deps-dev:** bump coverage from 6.0 to 6.0.1 ([#751](https://github.com/awslabs/aws-lambda-powertools-python/issues/751)) +* **deps-dev:** bump mkdocs-material from 7.3.2 to 7.3.3 ([#758](https://github.com/awslabs/aws-lambda-powertools-python/issues/758)) +* **deps-dev:** bump flake8-comprehensions from 3.6.1 to 3.7.0 ([#759](https://github.com/awslabs/aws-lambda-powertools-python/issues/759)) * **deps-dev:** bump mkdocs-material from 7.3.3 to 7.3.5 ([#781](https://github.com/awslabs/aws-lambda-powertools-python/issues/781)) +* **deps-dev:** bump coverage from 6.0 to 6.0.1 ([#751](https://github.com/awslabs/aws-lambda-powertools-python/issues/751)) * **deps-dev:** bump mkdocs-material from 7.3.5 to 7.3.6 ([#791](https://github.com/awslabs/aws-lambda-powertools-python/issues/791)) -* **deps-dev:** bump mkdocs-material from 7.3.2 to 7.3.3 ([#758](https://github.com/awslabs/aws-lambda-powertools-python/issues/758)) +* **deps-dev:** bump coverage from 6.0.2 to 6.1.2 ([#810](https://github.com/awslabs/aws-lambda-powertools-python/issues/810)) +* **deps-dev:** bump isort from 5.9.3 to 5.10.1 ([#811](https://github.com/awslabs/aws-lambda-powertools-python/issues/811)) -## 1.21.1 - 2021-10-07 -### Regression - -* **metrics:** typing regression on log_metrics callable ([#744](https://github.com/awslabs/aws-lambda-powertools-python/issues/744)) - -### Documentation + +## [v1.21.1] - 2021-10-07 +## Documentation * add new public layer ARNs ([#746](https://github.com/awslabs/aws-lambda-powertools-python/issues/746)) -### Maintenance +## Maintenance +* include public layers changelog +* bump to 1.21.1 +* include regression in changelog * ignore constants in test cov ([#745](https://github.com/awslabs/aws-lambda-powertools-python/issues/745)) -* github-actions: add support for publishing fallback +* ignore constants in tests cov +* add support for publishing fallback * **deps:** bump boto3 from 1.18.54 to 1.18.56 ([#742](https://github.com/awslabs/aws-lambda-powertools-python/issues/742)) * **deps-dev:** bump mkdocs-material from 7.3.1 to 7.3.2 ([#741](https://github.com/awslabs/aws-lambda-powertools-python/issues/741)) -## 1.21.0 - 2021-10-05 +## Regression + +* **metrics:** typing regression on log_metrics callable ([#744](https://github.com/awslabs/aws-lambda-powertools-python/issues/744)) -### Bug Fixes + + +## [v1.21.0] - 2021-10-05 +## Bug Fixes * **data-classes:** use correct asdict funciton ([#666](https://github.com/awslabs/aws-lambda-powertools-python/issues/666)) * **feature-flags:** rules should evaluate with an AND op ([#724](https://github.com/awslabs/aws-lambda-powertools-python/issues/724)) @@ -488,23 +700,24 @@ Tenet update! We've updated **Idiomatic** tenet to **Progressive** to reflect th * **logger:** push extra keys to the end ([#722](https://github.com/awslabs/aws-lambda-powertools-python/issues/722)) * **mypy:** a few return types, type signatures, and untyped areas ([#718](https://github.com/awslabs/aws-lambda-powertools-python/issues/718)) -### Code Refactoring +## Code Refactoring * **data-classes:** clean up internal logic for APIGatewayAuthorizerResponse ([#643](https://github.com/awslabs/aws-lambda-powertools-python/issues/643)) -### Documentation +## Documentation * Terraform reference for SAR Lambda Layer ([#716](https://github.com/awslabs/aws-lambda-powertools-python/issues/716)) +* add team behind it and email * **event-handler:** document catch-all routes ([#705](https://github.com/awslabs/aws-lambda-powertools-python/issues/705)) * **idempotency:** fix misleading idempotent examples ([#661](https://github.com/awslabs/aws-lambda-powertools-python/issues/661)) * **jmespath:** clarify envelope terminology * **parser:** fix incorrect import in root_validator example ([#735](https://github.com/awslabs/aws-lambda-powertools-python/issues/735)) -### Features +## Features * expose jmespath powertools functions ([#736](https://github.com/awslabs/aws-lambda-powertools-python/issues/736)) +* add get_raw_configuration property in store; expose store * boto3 sessions in batch, parameters & idempotency ([#717](https://github.com/awslabs/aws-lambda-powertools-python/issues/717)) -* **feature-flags**: add get_raw_configuration property in store; expose store ([#720](https://github.com/awslabs/aws-lambda-powertools-python/issues/720)) * **feature-flags:** Bring your own logger for debug ([#709](https://github.com/awslabs/aws-lambda-powertools-python/issues/709)) * **feature-flags:** improve "IN/NOT_IN"; new rule actions ([#710](https://github.com/awslabs/aws-lambda-powertools-python/issues/710)) * **feature-flags:** get_raw_configuration property in Store ([#720](https://github.com/awslabs/aws-lambda-powertools-python/issues/720)) @@ -512,187 +725,197 @@ Tenet update! We've updated **Idiomatic** tenet to **Progressive** to reflect th * **idempotency:** makes customers unit testing easier ([#719](https://github.com/awslabs/aws-lambda-powertools-python/issues/719)) * **validator:** include missing data elements from a validation error ([#686](https://github.com/awslabs/aws-lambda-powertools-python/issues/686)) -### Maintenance +## Maintenance * add python 3.9 support -* **deps:** bump boto3 from 1.18.51 to 1.18.54 ([#733](https://github.com/awslabs/aws-lambda-powertools-python/issues/733)) +* bump to 1.21.0 +* **deps:** bump boto3 from 1.18.41 to 1.18.49 ([#703](https://github.com/awslabs/aws-lambda-powertools-python/issues/703)) * **deps:** bump boto3 from 1.18.32 to 1.18.38 ([#671](https://github.com/awslabs/aws-lambda-powertools-python/issues/671)) * **deps:** bump boto3 from 1.18.38 to 1.18.41 ([#677](https://github.com/awslabs/aws-lambda-powertools-python/issues/677)) +* **deps:** bump boto3 from 1.18.51 to 1.18.54 ([#733](https://github.com/awslabs/aws-lambda-powertools-python/issues/733)) * **deps:** bump boto3 from 1.18.49 to 1.18.51 ([#713](https://github.com/awslabs/aws-lambda-powertools-python/issues/713)) -* **deps:** bump boto3 from 1.18.41 to 1.18.49 ([#703](https://github.com/awslabs/aws-lambda-powertools-python/issues/703)) * **deps:** bump codecov/codecov-action from 2.0.2 to 2.1.0 ([#675](https://github.com/awslabs/aws-lambda-powertools-python/issues/675)) -* **deps-dev:** bump coverage from 5.5 to 6.0 ([#732](https://github.com/awslabs/aws-lambda-powertools-python/issues/732)) +* **deps-dev:** bump flake8-bugbear from 21.9.1 to 21.9.2 ([#712](https://github.com/awslabs/aws-lambda-powertools-python/issues/712)) +* **deps-dev:** bump mkdocs-material from 7.3.0 to 7.3.1 ([#731](https://github.com/awslabs/aws-lambda-powertools-python/issues/731)) * **deps-dev:** bump mkdocs-material from 7.2.8 to 7.3.0 ([#695](https://github.com/awslabs/aws-lambda-powertools-python/issues/695)) * **deps-dev:** bump mkdocs-material from 7.2.6 to 7.2.8 ([#682](https://github.com/awslabs/aws-lambda-powertools-python/issues/682)) * **deps-dev:** bump flake8-bugbear from 21.4.3 to 21.9.1 ([#676](https://github.com/awslabs/aws-lambda-powertools-python/issues/676)) -* **deps-dev:** bump flake8-bugbear from 21.9.1 to 21.9.2 ([#712](https://github.com/awslabs/aws-lambda-powertools-python/issues/712)) +* **deps-dev:** bump coverage from 5.5 to 6.0 ([#732](https://github.com/awslabs/aws-lambda-powertools-python/issues/732)) * **deps-dev:** bump radon from 4.5.2 to 5.1.0 ([#673](https://github.com/awslabs/aws-lambda-powertools-python/issues/673)) -* **deps-dev:** bump mkdocs-material from 7.3.0 to 7.3.1 ([#731](https://github.com/awslabs/aws-lambda-powertools-python/issues/731)) +* **deps-dev:** bump pytest-cov from 2.12.1 to 3.0.0 ([#730](https://github.com/awslabs/aws-lambda-powertools-python/issues/730)) * **deps-dev:** bump xenon from 0.7.3 to 0.8.0 ([#669](https://github.com/awslabs/aws-lambda-powertools-python/issues/669)) -### Bug Fixes -* **event-handler:** fix issue with strip_prefixes and root level resolvers ([#646](https://github.com/awslabs/aws-lambda-powertools-python/issues/646)) - -### Maintenance - -* **deps:** bump boto3 from 1.18.26 to 1.18.32 ([#663](https://github.com/awslabs/aws-lambda-powertools-python/issues/663)) -* **deps-dev:** bump mkdocs-material from 7.2.4 to 7.2.6 ([#665](https://github.com/awslabs/aws-lambda-powertools-python/issues/665)) -* **deps-dev:** bump pytest from 6.2.4 to 6.2.5 ([#662](https://github.com/awslabs/aws-lambda-powertools-python/issues/662)) -* **deps-dev:** bump mike from 0.6.0 to 1.0.1 ([#453](https://github.com/awslabs/aws-lambda-powertools-python/issues/453)) -* **license:** add third party license to pyproject.toml ([#641](https://github.com/awslabs/aws-lambda-powertools-python/issues/641)) - -## 1.20.2 - 2021-09-02 - -### Bug Fixes + +## [v1.20.2] - 2021-09-02 +## Bug Fixes -* **event-handler:** fix issue with strip_prefixes and root level resolvers ([#646](https://github.com/awslabs/aws-lambda-powertools-python/issues/646)) +* Fix issue with strip_prefixes ([#647](https://github.com/awslabs/aws-lambda-powertools-python/issues/647)) -### Maintenance +## Maintenance +* bump to 1.20.2 * **deps:** bump boto3 from 1.18.26 to 1.18.32 ([#663](https://github.com/awslabs/aws-lambda-powertools-python/issues/663)) * **deps-dev:** bump mkdocs-material from 7.2.4 to 7.2.6 ([#665](https://github.com/awslabs/aws-lambda-powertools-python/issues/665)) * **deps-dev:** bump pytest from 6.2.4 to 6.2.5 ([#662](https://github.com/awslabs/aws-lambda-powertools-python/issues/662)) -* **deps-dev:** bump mike from 0.6.0 to 1.0.1 ([#453](https://github.com/awslabs/aws-lambda-powertools-python/issues/453)) -* **license:** add third party license to pyproject.toml ([#641](https://github.com/awslabs/aws-lambda-powertools-python/issues/641)) +* **license:** Add THIRD-PARTY-LICENSES ([#641](https://github.com/awslabs/aws-lambda-powertools-python/issues/641)) -## 1.20.1 - 2021-08-22 -### Bug Fixes + +## [v1.20.1] - 2021-08-22 +## Bug Fixes * **idempotency:** sorting keys before hashing ([#639](https://github.com/awslabs/aws-lambda-powertools-python/issues/639)) -### Maintenance +## Maintenance +* bump to 1.20.1 * markdown linter fixes ([#636](https://github.com/awslabs/aws-lambda-powertools-python/issues/636)) * setup codespaces ([#637](https://github.com/awslabs/aws-lambda-powertools-python/issues/637)) * **license:** add third party license ([#635](https://github.com/awslabs/aws-lambda-powertools-python/issues/635)) -## 1.20.0 - 2021-08-21 + +## [v1.20.0] - 2021-08-21 ## Bug Fixes * **api-gateway:** HTTP API strip stage name from request path ([#622](https://github.com/awslabs/aws-lambda-powertools-python/issues/622)) +* **docs:** correct feature_flags link and json exmaples ([#605](https://github.com/awslabs/aws-lambda-powertools-python/issues/605)) -### Code Refactoring +## Code Refactoring -* **event-handler:** match to match_results; 3.10 new keyword ([#616](https://github.com/awslabs/aws-lambda-powertools-python/issues/616)) +* **event_handler:** match to match_results; 3.10 new keyword ([#616](https://github.com/awslabs/aws-lambda-powertools-python/issues/616)) -### Documentation +## Documentation -* **data-classes:** make authorizer concise; use enum ([#630](https://github.com/awslabs/aws-lambda-powertools-python/issues/630)) -* **feature-flags:** correct link and json examples ([#605](https://github.com/awslabs/aws-lambda-powertools-python/issues/605)) -* **data-class:** fix invalid syntax in new AppSync Authorizer * **api-gateway:** add new API mapping support +* **data-class:** fix invalid syntax in new AppSync Authorizer +* **data-classes:** make authorizer concise; use enum ([#630](https://github.com/awslabs/aws-lambda-powertools-python/issues/630)) -### Features +## Features -* **data-classes:** authorizer for API Gateway HTTP and REST API ([#620](https://github.com/awslabs/aws-lambda-powertools-python/issues/620)) -* **data-classes:** new data_as_bytes property in KinesisStreamRecordPayload ([#628](https://github.com/awslabs/aws-lambda-powertools-python/issues/628)) +* **data-classes:** authorizer for http api and rest api ([#620](https://github.com/awslabs/aws-lambda-powertools-python/issues/620)) +* **data-classes:** data_as_bytes prop KinesisStreamRecordPayload ([#628](https://github.com/awslabs/aws-lambda-powertools-python/issues/628)) * **data-classes:** AppSync Lambda authorizer event ([#610](https://github.com/awslabs/aws-lambda-powertools-python/issues/610)) -* **event-handler:** prefixes to strip for custom domain mapping paths ([#579](https://github.com/awslabs/aws-lambda-powertools-python/issues/579)) +* **event-handler:** prefixes to strip for custom mappings ([#579](https://github.com/awslabs/aws-lambda-powertools-python/issues/579)) * **general:** support for Python 3.9 ([#626](https://github.com/awslabs/aws-lambda-powertools-python/issues/626)) * **idempotency:** support for any synchronous function ([#625](https://github.com/awslabs/aws-lambda-powertools-python/issues/625)) -### Maintenance +## Maintenance +* update changelog to reflect out-of-band commits +* bump to 1.20.0 +* update new changelog version tag * **actions:** include new labels * **api-docs:** enable allow_reuse to fix the docs ([#612](https://github.com/awslabs/aws-lambda-powertools-python/issues/612)) * **deps:** bump boto3 from 1.18.25 to 1.18.26 ([#627](https://github.com/awslabs/aws-lambda-powertools-python/issues/627)) * **deps:** bump boto3 from 1.18.24 to 1.18.25 ([#623](https://github.com/awslabs/aws-lambda-powertools-python/issues/623)) * **deps:** bump boto3 from 1.18.22 to 1.18.24 ([#619](https://github.com/awslabs/aws-lambda-powertools-python/issues/619)) -* **deps:** bump boto3 from 1.18.17 to 1.18.21 ([#608](https://github.com/awslabs/aws-lambda-powertools-python/issues/608)) * **deps:** bump boto3 from 1.18.21 to 1.18.22 ([#614](https://github.com/awslabs/aws-lambda-powertools-python/issues/614)) -* **deps-dev:** bump flake8-comprehensions from 3.5.0 to 3.6.0 ([#609](https://github.com/awslabs/aws-lambda-powertools-python/issues/609)) +* **deps:** bump boto3 from 1.18.17 to 1.18.21 ([#608](https://github.com/awslabs/aws-lambda-powertools-python/issues/608)) * **deps-dev:** bump flake8-comprehensions from 3.6.0 to 3.6.1 ([#615](https://github.com/awslabs/aws-lambda-powertools-python/issues/615)) +* **deps-dev:** bump flake8-comprehensions from 3.5.0 to 3.6.0 ([#609](https://github.com/awslabs/aws-lambda-powertools-python/issues/609)) * **deps-dev:** bump mkdocs-material from 7.2.3 to 7.2.4 ([#607](https://github.com/awslabs/aws-lambda-powertools-python/issues/607)) * **docs:** correct markdown based on markdown lint ([#603](https://github.com/awslabs/aws-lambda-powertools-python/issues/603)) * **shared:** fix cyclic import & refactor data extraction fn ([#613](https://github.com/awslabs/aws-lambda-powertools-python/issues/613)) -## 1.19.0 - 2021-08-11 -### Bug Fixes + +## [v1.19.0] - 2021-08-11 +## Bug Fixes * **deps:** bump poetry to latest ([#592](https://github.com/awslabs/aws-lambda-powertools-python/issues/592)) -* **feature-flags:** bug handling multiple conditions ([#599](https://github.com/awslabs/aws-lambda-powertools-python/issues/599)) -* **parser:** API Gateway WebSocket validation under check_message_id; plus some housekeeping ([#553](https://github.com/awslabs/aws-lambda-powertools-python/issues/553)) +* **feature-flags:** bug handling multiple conditions ([#599](https://github.com/awslabs/aws-lambda-powertools-python/issues/599)) * **feature-toggles:** correct cdk example ([#601](https://github.com/awslabs/aws-lambda-powertools-python/issues/601)) +* **parser:** apigw wss validation check_message_id; housekeeping ([#553](https://github.com/awslabs/aws-lambda-powertools-python/issues/553)) -### Code Refactoring +## Code Refactoring -* **feature-flags:** add debug statements for all feature evaluations ([#590](https://github.com/awslabs/aws-lambda-powertools-python/issues/590)) -* **feature-flags:** optimize UX and maintenance ([#563](https://github.com/awslabs/aws-lambda-powertools-python/issues/563)) +* **feature-flags:** add debug for all features evaluation" ([#590](https://github.com/awslabs/aws-lambda-powertools-python/issues/590)) +* **feature_flags:** optimize UX and maintenance ([#563](https://github.com/awslabs/aws-lambda-powertools-python/issues/563)) -### Documentation +## Documentation * **event-handler:** new custom serializer option +* **feature-flags:** add guidance when to use vs env vars vs parameters +* **feature-flags:** fix sample feature name in evaluate * **feature-flags:** create concrete documentation ([#594](https://github.com/awslabs/aws-lambda-powertools-python/issues/594)) -* **feature-flags:** correct docs and typing ([#588](https://github.com/awslabs/aws-lambda-powertools-python/issues/588)) +* **feature-toggles:** correct docs and typing ([#588](https://github.com/awslabs/aws-lambda-powertools-python/issues/588)) +* **feature_flags:** fix SAM infra, convert CDK to Python * **parameters:** auto-transforming values based on suffix ([#573](https://github.com/awslabs/aws-lambda-powertools-python/issues/573)) * **readme:** add code coverage badge ([#577](https://github.com/awslabs/aws-lambda-powertools-python/issues/577)) * **tracer:** update wording that it auto-disables on non-Lambda env -* **feature-flags:** fix SAM infra, convert CDK to Python -* **feature-flags:** fix sample feature name in evaluate method -* **feature-flags:** add guidance when to use vs env vars vs parameters -### Features +## Features * **api-gateway:** add support for custom serializer ([#568](https://github.com/awslabs/aws-lambda-powertools-python/issues/568)) * **data-classes:** decode json_body if based64 encoded ([#560](https://github.com/awslabs/aws-lambda-powertools-python/issues/560)) -* **feature-flags:** Add not_in action and rename contains to in ([#589](https://github.com/awslabs/aws-lambda-powertools-python/issues/589)) -* **params:** expose params `max_age`, `raise_on_transform_error` to high level functions ([#567](https://github.com/awslabs/aws-lambda-powertools-python/issues/567)) -* **tracer:** auto-disable tracer for non-Lambda environments to ease testing ([#598](https://github.com/awslabs/aws-lambda-powertools-python/issues/598)) +* **feature flags:** Add not_in action and rename contains to in ([#589](https://github.com/awslabs/aws-lambda-powertools-python/issues/589)) +* **params:** expose high level max_age, raise_on_transform_error ([#567](https://github.com/awslabs/aws-lambda-powertools-python/issues/567)) +* **tracer:** disable tracer when for non-Lambda envs ([#598](https://github.com/awslabs/aws-lambda-powertools-python/issues/598)) -### Maintenance +## Maintenance +* only build docs on docs path +* update pypi description, keywords +* bump to 1.19.0 +* enable autolabel based on PR title +* include feature-flags docs hotfix +* **deps:** bump boto3 from 1.18.15 to 1.18.17 ([#597](https://github.com/awslabs/aws-lambda-powertools-python/issues/597)) * **deps:** bump boto3 from 1.18.1 to 1.18.15 ([#591](https://github.com/awslabs/aws-lambda-powertools-python/issues/591)) * **deps:** bump codecov/codecov-action from 2.0.1 to 2.0.2 ([#558](https://github.com/awslabs/aws-lambda-powertools-python/issues/558)) -* **deps:** bump boto3 from 1.18.15 to 1.18.17 ([#597](https://github.com/awslabs/aws-lambda-powertools-python/issues/597)) -* **deps-dev:** bump mkdocs-material from 7.2.2 to 7.2.3 ([#596](https://github.com/awslabs/aws-lambda-powertools-python/issues/596)) * **deps-dev:** bump mkdocs-material from 7.2.1 to 7.2.2 ([#582](https://github.com/awslabs/aws-lambda-powertools-python/issues/582)) +* **deps-dev:** bump mkdocs-material from 7.2.2 to 7.2.3 ([#596](https://github.com/awslabs/aws-lambda-powertools-python/issues/596)) * **deps-dev:** bump pdoc3 from 0.9.2 to 0.10.0 ([#584](https://github.com/awslabs/aws-lambda-powertools-python/issues/584)) * **deps-dev:** bump isort from 5.9.2 to 5.9.3 ([#574](https://github.com/awslabs/aws-lambda-powertools-python/issues/574)) * **deps-dev:** bump mkdocs-material from 7.2.0 to 7.2.1 ([#566](https://github.com/awslabs/aws-lambda-powertools-python/issues/566)) * **deps-dev:** bump mkdocs-material from 7.1.11 to 7.2.0 ([#551](https://github.com/awslabs/aws-lambda-powertools-python/issues/551)) * **deps-dev:** bump flake8-black from 0.2.1 to 0.2.3 ([#541](https://github.com/awslabs/aws-lambda-powertools-python/issues/541)) -## 1.18.1 - 2021-07-23 -### Bug Fixes + +## [v1.18.1] - 2021-07-23 +## Bug Fixes + +* **api-gateway:** route regression non-word and unsafe URI chars ([#556](https://github.com/awslabs/aws-lambda-powertools-python/issues/556)) + +## Maintenance -* **api-gateway:** route regression for non-word and unsafe URI chars ([#556](https://github.com/awslabs/aws-lambda-powertools-python/issues/556)) +* bump 1.18.1 -## 1.18.0 - 2021-07-20 -### Bug Fixes + +## [v1.18.0] - 2021-07-20 +## Bug Fixes -* **api-gateway:** non-greedy route pattern regex which incorrectly mapped certain route params to function params ([#533](https://github.com/awslabs/aws-lambda-powertools-python/issues/533)) -* **api-gateway:** incorrect plain text mimetype constant [#506](https://github.com/awslabs/aws-lambda-powertools-python/issues/506) -* **data-classes:** include milliseconds in scalar types to correctly align with AppSync scalars ([#504](https://github.com/awslabs/aws-lambda-powertools-python/issues/504)) -* **mypy:** addresses lack of optional types ([#521](https://github.com/awslabs/aws-lambda-powertools-python/issues/521)) -* **parser:** make ApiGateway version, authorizer fields optional ([#532](https://github.com/awslabs/aws-lambda-powertools-python/issues/532)) +* **api-gateway:** non-greedy route pattern regex ([#533](https://github.com/awslabs/aws-lambda-powertools-python/issues/533)) +* **api-gateway:** incorrect plain text mimetype [#506](https://github.com/awslabs/aws-lambda-powertools-python/issues/506) +* **data-classes:** include milliseconds in scalar types ([#504](https://github.com/awslabs/aws-lambda-powertools-python/issues/504)) +* **mypy:** fixes to resolve no implicit optional errors ([#521](https://github.com/awslabs/aws-lambda-powertools-python/issues/521)) +* **parser:** Make ApiGateway version, authorizer fields optional ([#532](https://github.com/awslabs/aws-lambda-powertools-python/issues/532)) * **tracer:** mypy generic to preserve decorated method signature ([#529](https://github.com/awslabs/aws-lambda-powertools-python/issues/529)) -### Code Refactoring +## Code Refactoring -* **feature-toggles:** code coverage and housekeeping ([#530](https://github.com/awslabs/aws-lambda-powertools-python/issues/530)) +* **feature-toggles:** Code coverage and housekeeping ([#530](https://github.com/awslabs/aws-lambda-powertools-python/issues/530)) -### Documentation +## Documentation -* **api-gateway:** new HTTP service error exceptions ([#546](https://github.com/awslabs/aws-lambda-powertools-python/issues/546)) -* **logger:** new get_correlation_id method ([#545](https://github.com/awslabs/aws-lambda-powertools-python/issues/545)) +* **api-gateway:** document new HTTP service error exceptions ([#546](https://github.com/awslabs/aws-lambda-powertools-python/issues/546)) +* **logger:** document new get_correlation_id method ([#545](https://github.com/awslabs/aws-lambda-powertools-python/issues/545)) -### Features +## Features * **api-gateway:** add debug mode ([#507](https://github.com/awslabs/aws-lambda-powertools-python/issues/507)) -* **api-gateway:** add common HTTP service errors ([#506](https://github.com/awslabs/aws-lambda-powertools-python/issues/506)) +* **api-gateway:** add common service errors ([#506](https://github.com/awslabs/aws-lambda-powertools-python/issues/506)) * **event-handler:** Support AppSyncResolverEvent subclassing ([#526](https://github.com/awslabs/aws-lambda-powertools-python/issues/526)) * **feat-toggle:** New simple feature toggles rule engine (WIP) ([#494](https://github.com/awslabs/aws-lambda-powertools-python/issues/494)) * **logger:** add get_correlation_id method ([#516](https://github.com/awslabs/aws-lambda-powertools-python/issues/516)) +* **mypy:** add mypy support to makefile ([#508](https://github.com/awslabs/aws-lambda-powertools-python/issues/508)) -### Maintenance +## Maintenance -* **mypy:** add mypy support to makefile ([#508](https://github.com/awslabs/aws-lambda-powertools-python/issues/508)) +* bump 1.18.0 ([#547](https://github.com/awslabs/aws-lambda-powertools-python/issues/547)) * **deps:** bump codecov/codecov-action from 1 to 2.0.1 ([#539](https://github.com/awslabs/aws-lambda-powertools-python/issues/539)) * **deps:** bump boto3 from 1.18.0 to 1.18.1 ([#528](https://github.com/awslabs/aws-lambda-powertools-python/issues/528)) * **deps:** bump boto3 from 1.17.110 to 1.18.0 ([#527](https://github.com/awslabs/aws-lambda-powertools-python/issues/527)) @@ -700,22 +923,25 @@ Tenet update! We've updated **Idiomatic** tenet to **Progressive** to reflect th * **deps-dev:** bump mkdocs-material from 7.1.10 to 7.1.11 ([#542](https://github.com/awslabs/aws-lambda-powertools-python/issues/542)) * **deps-dev:** bump mkdocs-material from 7.1.9 to 7.1.10 ([#522](https://github.com/awslabs/aws-lambda-powertools-python/issues/522)) * **deps-dev:** bump isort from 5.9.1 to 5.9.2 ([#514](https://github.com/awslabs/aws-lambda-powertools-python/issues/514)) -* **event-handler:** adjusts API Gateway/ALB service errors exception docstrings to not confuse AppSync customers +* **event-handler:** adjusts exception docstrings to not confuse AppSync customers -## 1.17.1 - 2021-07-02 -### Bug Fixes + +## [v1.17.1] - 2021-07-02 +## Bug Fixes -* **Validator:** Handle built-in custom formats like `date-time` when type is `string` ([#498](https://github.com/awslabs/aws-lambda-powertools-python/issues/498)) +* **validator:** handle built-in custom formats correctly ([#498](https://github.com/awslabs/aws-lambda-powertools-python/issues/498)) -### Documentation +## Documentation -* **Layers:** Add Layers example for Serverless framework & CDK ([#500](https://github.com/awslabs/aws-lambda-powertools-python/issues/500)) -* **Misc.:** Enable dark mode switch ([#471](https://github.com/awslabs/aws-lambda-powertools-python/issues/471)) -* **Tracer:** Additional scenario when to disable auto-capture for responses larger than 64K ([#499](https://github.com/awslabs/aws-lambda-powertools-python/issues/499)) +* add Layers example for Serverless framework & CDK ([#500](https://github.com/awslabs/aws-lambda-powertools-python/issues/500)) +* enable dark mode switch ([#471](https://github.com/awslabs/aws-lambda-powertools-python/issues/471)) +* **logger:** add FAQ for cross-account searches ([#501](https://github.com/awslabs/aws-lambda-powertools-python/issues/501)) +* **tracer:** additional scenario when to disable auto-capture ([#499](https://github.com/awslabs/aws-lambda-powertools-python/issues/499)) -### Maintenance +## Maintenance +* bump 1.17.1 ([#502](https://github.com/awslabs/aws-lambda-powertools-python/issues/502)) * **deps:** bump boto3 from 1.17.101 to 1.17.102 ([#493](https://github.com/awslabs/aws-lambda-powertools-python/issues/493)) * **deps:** bump boto3 from 1.17.91 to 1.17.101 ([#490](https://github.com/awslabs/aws-lambda-powertools-python/issues/490)) * **deps:** bump email-validator from 1.1.2 to 1.1.3 ([#478](https://github.com/awslabs/aws-lambda-powertools-python/issues/478)) @@ -724,27 +950,42 @@ Tenet update! We've updated **Idiomatic** tenet to **Progressive** to reflect th * **deps-dev:** bump isort from 5.8.0 to 5.9.1 ([#487](https://github.com/awslabs/aws-lambda-powertools-python/issues/487)) * **deps-dev:** bump mkdocs-material from 7.1.7 to 7.1.9 ([#491](https://github.com/awslabs/aws-lambda-powertools-python/issues/491)) -## 1.17.0 - 2021-06-08 -### Added + +## [v1.17.0] - 2021-06-08 +## Documentation -* **Documentation**: Include new public roadmap ([#452](https://github.com/awslabs/aws-lambda-powertools-python/issues/452)) -* **Documentation**: Remove old todo in idempotency docs -* **Data classes:** New `AttributeValueType` to get type and value from data in `DynamoDBStreamEvent` ([#462](https://github.com/awslabs/aws-lambda-powertools-python/issues/462)) -* **Data classes:** New decorator `event_source` to instantiate data_classes ([#442](https://github.com/awslabs/aws-lambda-powertools-python/issues/442)) -* **Logger:** New `clear_state` parameter to clear previously added custom keys upon invocation ([#467](https://github.com/awslabs/aws-lambda-powertools-python/issues/467)) -* **Parser:** Support for API Gateway HTTP API [#434](https://github.com/awslabs/aws-lambda-powertools-python/issues/434) ([#441](https://github.com/awslabs/aws-lambda-powertools-python/issues/441)) +* include new public roadmap ([#452](https://github.com/awslabs/aws-lambda-powertools-python/issues/452)) +* **data_classes:** fix missing dynamodb stream get_type/value +* **idempotency:** remove old todo -### Maintenance +## Features -* **deps**: bump xenon from 0.7.1 to 0.7.3 ([#446](https://github.com/awslabs/aws-lambda-powertools-python/issues/446)) +* **data-classes:** add AttributeValueType to DynamoDBStreamEvent ([#462](https://github.com/awslabs/aws-lambda-powertools-python/issues/462)) +* **data-classes:** decorator to instantiate data_classes and docs updates ([#442](https://github.com/awslabs/aws-lambda-powertools-python/issues/442)) +* **logger:** add option to clear state per invocation ([#467](https://github.com/awslabs/aws-lambda-powertools-python/issues/467)) +* **parser:** add support for API Gateway HTTP API [#434](https://github.com/awslabs/aws-lambda-powertools-python/issues/434) ([#441](https://github.com/awslabs/aws-lambda-powertools-python/issues/441)) + +## Maintenance + +* bump xenon from 0.7.1 to 0.7.3 ([#446](https://github.com/awslabs/aws-lambda-powertools-python/issues/446)) +* fix changelog file redirection +* include dependencies label under maintenance +* ignore codecov upload +* reintroduce codecov token +* fix path for PR auto-labelling * assited changelog pre-generation, auto-label PR ([#443](https://github.com/awslabs/aws-lambda-powertools-python/issues/443)) * enable dependabot for dep upgrades ([#444](https://github.com/awslabs/aws-lambda-powertools-python/issues/444)) * enable mergify ([#450](https://github.com/awslabs/aws-lambda-powertools-python/issues/450)) -* **deps**: bump mkdocs-material from 7.1.5 to 7.1.6 ([#451](https://github.com/awslabs/aws-lambda-powertools-python/issues/451)) -* **deps**: bump boto3 from 1.17.78 to 1.17.84 ([#449](https://github.com/awslabs/aws-lambda-powertools-python/issues/449)) +* dependabot/mergify guardrail for major versions +* fix dependabot commit messages prefix +* fix dependabot unique set config +* bump mkdocs-material from 7.1.5 to 7.1.6 ([#451](https://github.com/awslabs/aws-lambda-powertools-python/issues/451)) +* bump version to 1.17.0 +* bump boto3 from 1.17.78 to 1.17.84 ([#449](https://github.com/awslabs/aws-lambda-powertools-python/issues/449)) * update mergify to require approval on dependabot ([#456](https://github.com/awslabs/aws-lambda-powertools-python/issues/456)) -* **deps**: bump actions/setup-python from 1 to 2.2.2 ([#445](https://github.com/awslabs/aws-lambda-powertools-python/issues/445)) +* bump actions/setup-python from 1 to 2.2.2 ([#445](https://github.com/awslabs/aws-lambda-powertools-python/issues/445)) +* trial boring cyborg automation * **deps:** bump boto3 from 1.17.87 to 1.17.88 ([#463](https://github.com/awslabs/aws-lambda-powertools-python/issues/463)) * **deps:** bump boto3 from 1.17.88 to 1.17.89 ([#466](https://github.com/awslabs/aws-lambda-powertools-python/issues/466)) * **deps:** bump boto3 from 1.17.84 to 1.17.85 ([#455](https://github.com/awslabs/aws-lambda-powertools-python/issues/455)) @@ -752,406 +993,1101 @@ Tenet update! We've updated **Idiomatic** tenet to **Progressive** to reflect th * **deps:** bump boto3 from 1.17.86 to 1.17.87 ([#459](https://github.com/awslabs/aws-lambda-powertools-python/issues/459)) * **deps-dev:** bump mkdocs-material from 7.1.6 to 7.1.7 ([#464](https://github.com/awslabs/aws-lambda-powertools-python/issues/464)) * **deps-dev:** bump pytest-cov from 2.12.0 to 2.12.1 ([#454](https://github.com/awslabs/aws-lambda-powertools-python/issues/454)) -* **mergify:** disable check for matrix jobs * **mergify:** use job name to match GH Actions +* **mergify:** disable check for matrix jobs + + + +## [v1.16.1] - 2021-05-23 +## Features + +* **parser:** security issue in Pydantic [#436](https://github.com/awslabs/aws-lambda-powertools-python/issues/436) ([#437](https://github.com/awslabs/aws-lambda-powertools-python/issues/437)) + +## Maintenance + +* bump to 1.16.1 + + + +## [v1.16.0] - 2021-05-17 +## Features + +* **data-classes:** decode base64 encoded body ([#425](https://github.com/awslabs/aws-lambda-powertools-python/issues/425)) +* **data-classes:** support for code pipeline job event ([#416](https://github.com/awslabs/aws-lambda-powertools-python/issues/416)) + +## Maintenance + +* bump to 1.16.0 + + + +## [v1.15.1] - 2021-05-13 +## Bug Fixes + +* **docs:** Use updated names for ProxyEventType ([#424](https://github.com/awslabs/aws-lambda-powertools-python/issues/424)) + +## Documentation + +* update list of features +* **event_handler:** add missing note on trimmed responses + +## Maintenance -## 1.16.1 - 2021-05-23 +* bump to 1.15.1 -### Fixed -* **Parser**: Upgrade Pydantic to 1.8.2 due to CVE-2021-29510 + +## [v1.15.0] - 2021-05-06 +## Bug Fixes -## 1.16.0 - 2021-05-17 +* **deps:** Bump aws-xray-sdk from 2.6.0 to 2.8.0 ([#413](https://github.com/awslabs/aws-lambda-powertools-python/issues/413)) +* **docs:** workflow to include api ref in latest alias ([#408](https://github.com/awslabs/aws-lambda-powertools-python/issues/408)) +* **parser:** Improve types for parser.py ([#419](https://github.com/awslabs/aws-lambda-powertools-python/issues/419)) +* **validator:** event type annotation as any in validate fn ([#405](https://github.com/awslabs/aws-lambda-powertools-python/issues/405)) -### Features -* **data-classes(API Gateway, ALB):** New method to decode base64 encoded body ([#425](https://github.com/awslabs/aws-lambda-powertools-python/issues/425)) -* **data-classes(CodePipeline):** Support for CodePipeline job event and methods to handle artifacts more easily ([#416](https://github.com/awslabs/aws-lambda-powertools-python/issues/416)) +## Code Refactoring -## 1.15.1 - 2021-05-13 +* simplify custom formatter for minor changes ([#417](https://github.com/awslabs/aws-lambda-powertools-python/issues/417)) +* **event-handler:** api gateway handler review changes ([#420](https://github.com/awslabs/aws-lambda-powertools-python/issues/420)) +* **event-handler:** Add ResponseBuilder and more docs ([#412](https://github.com/awslabs/aws-lambda-powertools-python/issues/412)) +* **logger:** BYOFormatter and Handler, UTC support, and more ([#404](https://github.com/awslabs/aws-lambda-powertools-python/issues/404)) -### Fixed +## Documentation -* **Logger**: Fix a regression with the `%s` operator +* **api_gateway:** new event handler for API Gateway and ALB ([#418](https://github.com/awslabs/aws-lambda-powertools-python/issues/418)) +* **event_handler:** fix closing brackets in CORS sample +* **event_handler:** remove beta flag from new HTTP utility +* **idempotency:** remove beta flag +* **logger:** improvements extensibility & new features ([#415](https://github.com/awslabs/aws-lambda-powertools-python/issues/415)) +* **parser:** fix table and heading syntax +* **tracer:** Fix line highlighting ([#395](https://github.com/awslabs/aws-lambda-powertools-python/issues/395)) -## 1.15.0 - 2021-05-06 +## Features -### Added +* add support to persist default dimensions ([#410](https://github.com/awslabs/aws-lambda-powertools-python/issues/410)) +* **event-handle:** allow for cors=None setting ([#421](https://github.com/awslabs/aws-lambda-powertools-python/issues/421)) +* **event-handler:** add http ProxyEvent handler ([#369](https://github.com/awslabs/aws-lambda-powertools-python/issues/369)) +* **parser:** Support for API GW v1 proxy schema & envelope ([#403](https://github.com/awslabs/aws-lambda-powertools-python/issues/403)) -* **Event handlers**: New API Gateway and ALB utility to reduce routing boilerplate and more -* **Documentation**: Logger enhancements such as bring your own formatter, handler, UTC support, and testing for Python 3.6 -* **Parser**: Support for API Gateway REST Proxy event and envelope -* **Logger**: Support for bringing custom formatter, custom handler, custom JSON serializer and deserializer, UTC support, expose `LambdaPowertoolsFormatter` -* **Metrics**: Support for persisting default dimensions that should always be added +## Maintenance -### Fixed +* bump to 1.15.0 ([#422](https://github.com/awslabs/aws-lambda-powertools-python/issues/422)) -* **Documentation**: Fix highlights, Parser types -* **Validator**: Fix event type annotations for `validate` standalone function -* **Parser**: Improve and fix types -* **Internal**: Remove X-Ray SDK version pinning as serialization regression has been fixed in 2.8.0 -* **Internal**: Latest documentation correctly includes a copy of API docs reference -## 1.14.0 - 2021-04-09 + +## [v1.14.0] - 2021-04-09 +## Bug Fixes -### Added +* perf tests for Logger and fail str msgs +* downgrade poetry to 1.1.4 ([#385](https://github.com/awslabs/aws-lambda-powertools-python/issues/385)) +* lock X-Ray SDK to 2.6.0 ([#384](https://github.com/awslabs/aws-lambda-powertools-python/issues/384)) +* **data-classes:** Add missing operationName ([#373](https://github.com/awslabs/aws-lambda-powertools-python/issues/373)) +* **idempotent:** Correctly raise IdempotencyKeyError ([#378](https://github.com/awslabs/aws-lambda-powertools-python/issues/378)) +* **metrics:** AttributeError raised by MediaManager and Typing and docs ([#357](https://github.com/awslabs/aws-lambda-powertools-python/issues/357)) +* **parser:** S3Model support empty keys ([#375](https://github.com/awslabs/aws-lambda-powertools-python/issues/375)) +* **tracer:** Correct type hint for MyPy ([#365](https://github.com/awslabs/aws-lambda-powertools-python/issues/365)) +* **workflow:** github actions depends on for release + +## Documentation + +* Fix doc links and line highlights ([#380](https://github.com/awslabs/aws-lambda-powertools-python/issues/380)) +* fix extra key for versioning +* update mkdocs-material to 7.1.0 +* Correct link targets and line highlights ([#390](https://github.com/awslabs/aws-lambda-powertools-python/issues/390)) +* introduce event handlers utility section ([#388](https://github.com/awslabs/aws-lambda-powertools-python/issues/388)) +* enable versioning feature ([#374](https://github.com/awslabs/aws-lambda-powertools-python/issues/374)) +* **idempotency:** add default configuration for those not using CFN ([#391](https://github.com/awslabs/aws-lambda-powertools-python/issues/391)) +* **index:** fix link to event handler +* **logger:** add example on how to set UTC timestamp ([#392](https://github.com/awslabs/aws-lambda-powertools-python/issues/392)) +* **validator:** include more complete examples & intro to JSON Schema ([#389](https://github.com/awslabs/aws-lambda-powertools-python/issues/389)) + +## Features + +* **event-handler:** Add AppSync handler decorator ([#363](https://github.com/awslabs/aws-lambda-powertools-python/issues/363)) +* **parameter:** add dynamodb_endpoint_url for local_testing ([#376](https://github.com/awslabs/aws-lambda-powertools-python/issues/376)) +* **parser:** Add S3 Object Lambda Event ([#362](https://github.com/awslabs/aws-lambda-powertools-python/issues/362)) + +## Maintenance + +* bump to 1.14.0 +* add approved by field in RFC template +* make RFC proposal more explicit +* update automated steps in release process + + + +## [v1.13.0] - 2021-03-23 +## Bug Fixes -* **Event handlers**: New core utility to easily handle incoming requests tightly integrated with Data Classes; AppSync being the first as we gauge from the community what additional ones would be helpful -* **Documentation**: Enabled versioning to access docs on a per release basis or staging docs (`develop` branch) -* **Documentation**: Links now open in a new tab and improved snippet line highlights -* **Documentation(validation)**: JSON Schema snippets and more complete examples -* **Documentation(idempotency)**: Table with expected configuration values for hash key and TTL attribute name when using the default behaviour -* **Documentation(logger)**: New example on how to set logging record timestamps in UTC -* **Parser(S3)**: Support for the new S3 Object Lambda Event model (`S3ObjectLambdaEvent`) -* **Parameters**: Support for DynamoDB Local via `endpoint_url` parameter, including docs -* **Internal**: Include `make pr` in pre-commit hooks when contributing to shorten feedback loop on pre-commit specific linting +* **deps:** Bump dependencies and fix some of the dev tooling ([#354](https://github.com/awslabs/aws-lambda-powertools-python/issues/354)) +* **lint:** Move `tests/THIRD-PARTY-LICENSES` to root ([#352](https://github.com/awslabs/aws-lambda-powertools-python/issues/352)) -### Fixed +## Features -* **Parser**: S3Model now supports keys with 0 length -* **Tracer**: Lock X-Ray SDK to 2.6.0 as there's been a regression upstream in 2.7.0 on serializing & capturing exceptions -* **Data Classes(API Gateway)**: Add missing property `operationName` within request context -* **Misc.**: Numerous typing fixes to better to support MyPy across all utilities -* **Internal**: Downgraded poetry to 1.1.4 as there's been a regression with `importlib-metadata` in 1.1.5 not yet fixed +* **data-classes:** Add S3 Object Lambda Event ([#353](https://github.com/awslabs/aws-lambda-powertools-python/issues/353)) -## 1.13.0 - 2021-03-23 +## Maintenance -### Added +* include internals in release template +* bump to 1.13.0 +* correct 3rd party license -* **Data Classes**: New S3 Object Lambda event -### Fixed + +## [v1.12.0] - 2021-03-17 +## Bug Fixes -* **Docs**: Lambda Layer SAM template reference example +* **idempotency:** TypeError when calling is_missing_idempotency_key with an int ([#315](https://github.com/awslabs/aws-lambda-powertools-python/issues/315)) +* **idempotency:** Correctly handle save_inprogress errors ([#313](https://github.com/awslabs/aws-lambda-powertools-python/issues/313)) -## 1.12.0 - 2021-03-17 +## Code Refactoring -### Added +* **parameters:** Consistently reference env ([#319](https://github.com/awslabs/aws-lambda-powertools-python/issues/319)) -* **Parameters**: New `force_fetch` param to always fetch the latest and bypass cache, if available -* **Data Classes**: New AppSync Lambda Resolver event covering both Direct Lambda Resolver and Amplify GraphQL Transformer Resolver `@function` -* **Data Classes**: New AppSync scalar utilities to easily compose Lambda Resolvers with date utils, uuid, etc. -* **Logger**: Support for Correlation ID both in `inject_lambda_context` decorator and `set_correlation_id` method -* **Logger**: Include new `exception_name` key to help customers easily enumerate exceptions across all functions +## Documentation -### Fixed +* surface new 1.12.0 features and enhancements ([#344](https://github.com/awslabs/aws-lambda-powertools-python/issues/344)) +* Correct code examples ([#317](https://github.com/awslabs/aws-lambda-powertools-python/issues/317)) +* **data-classes:** Add more cognito code examples ([#340](https://github.com/awslabs/aws-lambda-powertools-python/issues/340)) +* **idempotency:** Correct examples and line highlights ([#312](https://github.com/awslabs/aws-lambda-powertools-python/issues/312)) +* **metrics:** Corrections to the code examples ([#314](https://github.com/awslabs/aws-lambda-powertools-python/issues/314)) +* **metrics:** remove minimum dimensions +* **metrics:** Correct code examples in markdown ([#316](https://github.com/awslabs/aws-lambda-powertools-python/issues/316)) +* **tracer:** Fix Tracer typing hinting for Pycharm ([#345](https://github.com/awslabs/aws-lambda-powertools-python/issues/345)) -* **Tracer**: Type hint on return instance that made PyCharm no longer recognize autocompletion -* **Idempotency**: Error handling for missing idempotency key and `save_in_progress` errors +## Features -## 1.11.0 - 2021-03-05 +* **data-classes:** Add appsync scalar_types_utils ([#339](https://github.com/awslabs/aws-lambda-powertools-python/issues/339)) +* **data-classes:** AppSync Resolver Event ([#323](https://github.com/awslabs/aws-lambda-powertools-python/issues/323)) +* **idempotent:** Include function name in the idempotent key ([#326](https://github.com/awslabs/aws-lambda-powertools-python/issues/326)) +* **logging:** Add correlation_id support ([#321](https://github.com/awslabs/aws-lambda-powertools-python/issues/321)) +* **logging:** Include exception_name ([#320](https://github.com/awslabs/aws-lambda-powertools-python/issues/320)) +* **parameters:** Add force_fetch option ([#341](https://github.com/awslabs/aws-lambda-powertools-python/issues/341)) -### Fixed +## Maintenance -* **Tracer**: Lazy loads X-Ray SDK to increase perf by 75% for those not instantiating Tracer -* **Metrics**: Optimize validation and serialization to increase perf by nearly 50% for large operations (<1ms) +* bump to 1.12.0 +* remove auto-label as restrictions prevent it from working +* increase perf SLA due to slow GitHub Actions machine +* add PR size labelling action # 2 +* add PR size labelling action +* add PR auto-label action +* remove gatsby mention as migrated completed -### Added -* **Dataclass**: Add new Amazon Connect contact flow event -* **Idempotency**: New Idempotency utility -* **Docs**: Add example on how to integrate Batch utility with Sentry.io -* **Internal**: Added performance SLA tests for high level imports and Metrics validation/serialization + +## [v1.11.0] - 2021-03-05 +## Bug Fixes -## 1.10.5 - 2021-02-17 +* import time latency by lazily loading high level modules ([#301](https://github.com/awslabs/aws-lambda-powertools-python/issues/301)) +* correct behaviour to avoid caching "INPROGRESS" records ([#295](https://github.com/awslabs/aws-lambda-powertools-python/issues/295)) +* **idempotency:** PR feedback on config and kwargs -No changes. Bumped version to trigger new pipeline build for layer publishing. +## Code Refactoring -## 1.10.4 - 2021-02-17 +* **idempotent:** Change UX to use a config class for non-persistence related features ([#306](https://github.com/awslabs/aws-lambda-powertools-python/issues/306)) +* **metrics:** optimize validation and serialization ([#307](https://github.com/awslabs/aws-lambda-powertools-python/issues/307)) -### Fixed +## Documentation -* **Docs**: Fix anchor tags to be lower case -* **Docs**: Correct the docs location for the labeller +* **batch:** add example on how to integrate with sentry.io ([#308](https://github.com/awslabs/aws-lambda-powertools-python/issues/308)) +* **data-classes:** Correct import for DynamoDBRecordEventName ([#299](https://github.com/awslabs/aws-lambda-powertools-python/issues/299)) +* **dataclasses:** new Connect Contact Flow ([#310](https://github.com/awslabs/aws-lambda-powertools-python/issues/310)) +* **idempotency:** tidy up doc before release ([#309](https://github.com/awslabs/aws-lambda-powertools-python/issues/309)) +* **idempotent:** Fix typos and code formatting ([#305](https://github.com/awslabs/aws-lambda-powertools-python/issues/305)) -## 1.10.3 - 2021-02-04 +## Features -### Added +* Idempotency helper utility ([#245](https://github.com/awslabs/aws-lambda-powertools-python/issues/245)) +* **data-classes:** Add connect contact flow event ([#304](https://github.com/awslabs/aws-lambda-powertools-python/issues/304)) +* **idempotency:** Add raise_on_no_idempotency_key flag ([#297](https://github.com/awslabs/aws-lambda-powertools-python/issues/297)) +* **idempotency:** Fix KeyError when local_cache is True and an error is raised in the lambda handler ([#300](https://github.com/awslabs/aws-lambda-powertools-python/issues/300)) +* **idempotent:** Add support for jmespath_options ([#302](https://github.com/awslabs/aws-lambda-powertools-python/issues/302)) -* **Docs**: Migrated from Gatsby to MKdocs documentation system -* **Docs**: Included Getting started and Advanced sections in Core utilities, including additional examples +## Maintenance -### Fixed +* update changelog ([#311](https://github.com/awslabs/aws-lambda-powertools-python/issues/311)) +* adjusts Metrics SLA for slow py36 interpreters +* remove unsuccessful labeler bot +* update labeler bot to sync upon PR changes +* attempt 1 to fix PR labeler -* **Tracer**: Disabled batching segments as X-Ray SDK does not flush traces upon reaching limits -* **Parser**: Model type is now compliant with mypy -## 1.10.2 - 2021-02-04 + +## [v1.10.5] - 2021-02-17 +## Maintenance -### Fixed +* version bump to 1.10.5 ([#292](https://github.com/awslabs/aws-lambda-powertools-python/issues/292)) -* **Utilities**: Correctly handle and list multiple exceptions in SQS batch processing utility. -* **Docs*:: Fix typos on AppConfig docstring import, and `SnsModel` typo in parser. -* **Utilities**: `typing_extensions` package is now only installed in Python < 3.8 -## 1.10.1 - 2021-01-19 + +## [v1.10.4] - 2021-02-17 +## Bug Fixes + +* sync features in main page +* meta tags, and ext link to open in new tab -### Fixed +## Documentation -* **Utilities**: Added `SnsSqsEnvelope` in `parser` to dynamically adjust model mismatch when customers use SNS + SQS instead of SNS + Lambda, since we've discovered three payload keys are slightly different. +* **data-classes:** Fix anchor tags to be lower case ([#288](https://github.com/awslabs/aws-lambda-powertools-python/issues/288)) -## 1.10.0 - 2021-01-18 +## Maintenance -### Added -* **Utilities**: Added support for AppConfig in Parameters utility -* **Logger**: Added support for `extra` parameter to add additional root fields when logging messages -* **Logger**: Added support to Pytest Live Log feat. via feature toggle `POWERTOOLS_LOG_DEDUPLICATION_DISABLED` -* **Tracer**: Added support to disable auto-capturing response and exception as metadata -* **Utilities**: Added support to handle custom string/integer formats in JSON Schema in Validator utility -* **Install**: Added new Lambda Layer with all extra dependencies installed, available in Serverless Application Repository (SAR) +* version bump to 1.10.4 ([#291](https://github.com/awslabs/aws-lambda-powertools-python/issues/291)) +* add default runtime key +* Correct the docs location ([#289](https://github.com/awslabs/aws-lambda-powertools-python/issues/289)) +* enable PR labeler workflow +* add auto-label for known files -### Fixed +## Regression -* **Docs**: Added missing SNS parser model -* **Docs**: Added new environment variables for toggling features in Logger and Tracer: `POWERTOOLS_LOG_DEDUPLICATION_DISABLED`, `POWERTOOLS_TRACER_CAPTURE_RESPONSE`, `POWERTOOLS_TRACER_CAPTURE_ERROR` -* **Docs**: Fixed incorrect import for Cognito data classes in Event Sources utility +* search input size -## 1.9.1 - 2020-12-21 -### Fixed -* **Logger**: Bugfix to prevent parent loggers with the same name being configured more than once + +## [v1.10.3] - 2021-02-12 +## Bug Fixes + +* sfix typing hit for envelope parse model ([#286](https://github.com/awslabs/aws-lambda-powertools-python/issues/286)) +* disable batching of X-Ray subsegments ([#284](https://github.com/awslabs/aws-lambda-powertools-python/issues/284)) -### Added -* **Docs**: Add clarification to Tracer docs for how `capture_method` decorator can cause function responses to be read and serialized. -* **Utilities**: Added equality to ease testing Event source data classes -* **Package**: Added `py.typed` for initial work needed for PEP 561 compliance +## Documentation -## 1.9.0 - 2020-12-04 +* migrate documentation from Gatsby to MkDocs material ([#279](https://github.com/awslabs/aws-lambda-powertools-python/issues/279)) -### Added -* **Utilities**: Added Kinesis, S3, CloudWatch Logs, Application Load Balancer, and SES support in `Parser` -* **Docs**: Sidebar menu are now always expanded +## Maintenance -### Fixed -* **Docs**: Broken link to GitHub to homepage +* bump to 1.10.3 ([#287](https://github.com/awslabs/aws-lambda-powertools-python/issues/287)) -## 1.8.0 - 2020-11-20 -### Added -* **Utilities**: Added support for new EventBridge Replay field in `Parser` and `Event source data classes` -* **Utilities**: Added SNS support in `Parser` -* **Utilities**: Added API Gateway HTTP API data class support for new IAM and Lambda authorizer in `Event source data classes` -* **Docs**: Add new FAQ section for Logger on how to enable debug logging for boto3 -* **Docs**: Add explicit minimal set of permissions required to use Layers provided by Serverless Application Repository (SAR) + +## [v1.10.2] - 2021-02-04 +## Bug Fixes -### Fixed -* **Docs**: Fix typo in Dataclasses example for SES when fetching common email headers +* remove unnecessary typing-extensions for py3.8 ([#281](https://github.com/awslabs/aws-lambda-powertools-python/issues/281)) +* batch processing exceptions ([#276](https://github.com/awslabs/aws-lambda-powertools-python/issues/276)) -## 1.7.0 - 2020-10-26 +## Documentation -### Added -* **Utilities**: Add new `Parser` utility to provide parsing and deep data validation using Pydantic Models -* **Utilities**: Add case insensitive header lookup, and Cognito custom auth triggers to `Event source data classes` +* **appconfig:** Use correct import for docstring ([#271](https://github.com/awslabs/aws-lambda-powertools-python/issues/271)) -### Fixed -* **Logger**: keeps Lambda root logger handler, and add log filter instead to prevent child log records duplication -* **Docs**: Improve wording on adding log keys conditionally +## Maintenance -## 1.6.1 - 2020-09-23 +* bump to 1.10.2 ([#282](https://github.com/awslabs/aws-lambda-powertools-python/issues/282)) +* fix immer and socket.io CVEs ([#278](https://github.com/awslabs/aws-lambda-powertools-python/issues/278)) +* typo in parser docs -### Fixed -* **Utilities**: Fix issue with boolean values in DynamoDB stream event data class. -## 1.6.0 - 2020-09-22 + +## [v1.10.1] - 2021-01-19 +## Features -### Added -* **Metrics**: Support adding multiple metric values to a single metric name -* **Utilities**: Add new `Validator` utility to validate inbound events and responses using JSON Schema -* **Utilities**: Add new `Event source data classes` utility to easily describe event schema of popular event sources -* **Docs**: Add new `Testing your code` section to both Logger and Metrics page, and content width is now wider -* **Tracer**: Support for automatically disable Tracer when running a Chalice app +* add support for SNS->SQS protocol ([#272](https://github.com/awslabs/aws-lambda-powertools-python/issues/272)) -### Fixed -* **Docs**: Improve wording on log sampling feature in Logger, and removed duplicate content on main page -* **Utilities**: Remove DeleteMessageBatch API call when there are no messages to delete +## Maintenance -## 1.5.0 - 2020-09-04 +* bump to 1.10.1 ([#273](https://github.com/awslabs/aws-lambda-powertools-python/issues/273)) -### Added -* **Logger**: Add `xray_trace_id` to log output to improve integration with CloudWatch Service Lens -* **Logger**: Allow reordering of logged output -* **Utilities**: Add new `SQS batch processing` utility to handle partial failures in processing message batches -* **Utilities**: Add typing utility providing static type for lambda context object -* **Utilities**: Add `transform=auto` in parameters utility to deserialize parameter values based on the key name -### Fixed -* **Logger**: The value of `json_default` formatter is no longer written to logs + +## [v1.10.0] - 2021-01-18 +## Documentation -## 1.4.0 - 2020-08-25 +* fix import ([#267](https://github.com/awslabs/aws-lambda-powertools-python/issues/267)) +* add info about extras layer ([#260](https://github.com/awslabs/aws-lambda-powertools-python/issues/260)) +* fix note whitespace +* add missing parser models ([#254](https://github.com/awslabs/aws-lambda-powertools-python/issues/254)) -### Added -* **All**: Official Lambda Layer via [Serverless Application Repository](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer) -* **Tracer**: `capture_method` and `capture_lambda_handler` now support **capture_response=False** parameter to prevent Tracer to capture response as metadata to allow customers running Tracer with sensitive workloads +## Features -### Fixed -* **Metrics**: Cold start metric is now completely separate from application metrics dimensions, making it easier and cheaper to visualize. - * This is a breaking change if you were graphing/alerting on both application metrics with the same name to compensate this previous malfunctioning - * Marked as bugfix as this is the intended behaviour since the beginning, as you shouldn't have the same application metric with different dimensions -* **Utilities**: SSMProvider within Parameters utility now have decrypt and recursive parameters correctly defined to support autocompletion +* toggle to disable log deduplication locally for pytest live log [#262](https://github.com/awslabs/aws-lambda-powertools-python/issues/262) ([#268](https://github.com/awslabs/aws-lambda-powertools-python/issues/268)) +* Add AppConfig parameter provider ([#236](https://github.com/awslabs/aws-lambda-powertools-python/issues/236)) +* support extra parameter in Logger messages ([#257](https://github.com/awslabs/aws-lambda-powertools-python/issues/257)) +* support custom formats in JSON Schema validation ([#247](https://github.com/awslabs/aws-lambda-powertools-python/issues/247)) -### Added -* **Tracer**: capture_lambda_handler and capture_method decorators now support `capture_response` parameter to not include function's response as part of tracing metadata +## Maintenance -## 1.3.1 - 2020-08-22 +* bump to 1.10.0 ([#270](https://github.com/awslabs/aws-lambda-powertools-python/issues/270)) +* move env names to constant file ([#264](https://github.com/awslabs/aws-lambda-powertools-python/issues/264)) +* update stale bot +* general simplifications and cleanup ([#255](https://github.com/awslabs/aws-lambda-powertools-python/issues/255)) +* hardcode axios transitive resolution ([#256](https://github.com/awslabs/aws-lambda-powertools-python/issues/256)) -### Fixed -* **Tracer**: capture_method decorator did not properly handle nested context managers -## 1.3.0 - 2020-08-21 + +## [v1.9.1] - 2020-12-21 +## Bug Fixes -### Added -* **Utilities**: Add new `parameters` utility to retrieve a single or multiple parameters from SSM Parameter Store, Secrets Manager, DynamoDB, or your very own +* ensures all Loggers have unique service names -## 1.2.0 - 2020-08-20 +## Code Refactoring -### Added -* **Tracer**: capture_method decorator now supports generator functions (including context managers) +* convert dict into a literal dict object and re-use it -## 1.1.3 - 2020-08-18 +## Documentation -### Fixed -* **Logger**: Logs emitted twice, structured and unstructured, due to Lambda configuring the root handler +* add clarification to Tracer docs for how `capture_method` decorator can cause function responses to be read and serialized. -## 1.1.2 - 2020-08-16 +## Features -### Fixed -* **Docs**: Clarify confusion on Tracer reuse and `auto_patch=False` statement -* **Logger**: Autocomplete for log statements in PyCharm +* **pep-561:** Create py.typed file and include into pyproject. -## 1.1.1 - 2020-08-14 +## Maintenance -### Fixed -* **Logger**: Regression on `Logger` level not accepting `int` i.e. `Logger(level=logging.INFO)` +* bump to 1.9.1 ([#252](https://github.com/awslabs/aws-lambda-powertools-python/issues/252)) +* add changelog +* implement phony targets correctly +* **deps:** bump ini from 1.3.5 to 1.3.8 in /docs -## 1.1.0 - 2020-08-14 +## Pull Requests -### Added -* **Logger**: Support for logger inheritance with `child` parameter +* Merge pull request [#250](https://github.com/awslabs/aws-lambda-powertools-python/issues/250) from heitorlessa/fix/[#249](https://github.com/awslabs/aws-lambda-powertools-python/issues/249) +* Merge pull request [#235](https://github.com/awslabs/aws-lambda-powertools-python/issues/235) from Nr18/phony +* Merge pull request [#244](https://github.com/awslabs/aws-lambda-powertools-python/issues/244) from awslabs/docs/capture_method_clarification +* Merge pull request [#241](https://github.com/awslabs/aws-lambda-powertools-python/issues/241) from awslabs/dependabot/npm_and_yarn/docs/ini-1.3.8 +* Merge pull request [#237](https://github.com/awslabs/aws-lambda-powertools-python/issues/237) from gmcrocetti/pep-561 +* Merge pull request [#234](https://github.com/awslabs/aws-lambda-powertools-python/issues/234) from Nr18/test-equal +* Merge pull request [#233](https://github.com/awslabs/aws-lambda-powertools-python/issues/233) from GroovyDan/improv/add_equality_check_to_dict_wrapper +* Merge pull request [#232](https://github.com/awslabs/aws-lambda-powertools-python/issues/232) from gyft/add-missing-tests -### Fixed -* **Logger**: Log level is now case insensitive via params and env var -## 1.0.2 - 2020-07-16 + +## [v1.9.0] - 2020-12-04 +## Bug Fixes -### Fixed -* **Tracer**: Correct AWS X-Ray SDK dependency to support 2.5.0 and higher +* s3 model import +* cloudwatch logs envelope typo -## 1.0.1 - 2020-07-06 +## Documentation -### Fixed -* **Logger**: Fix a bug with `inject_lambda_context` causing existing Logger keys to be overridden if `structure_logs` was called before +* add Kinesis Streams as a supported model & envelope +* add S3 as a supported model +* add CW Logs as a supported envelope +* add CW Logs as a supported model +* add Alb as a supported model +* shadow sidebar to remain expanded +* add source code link in nav bar +* fix broken link for github -## 1.0.0 - 2020-06-18 +## Features -### Added -* **Metrics**: `add_metadata` method to add any metric metadata you'd like to ease finding metric related data via CloudWatch Logs -* Set status as General Availability +* Add Kinesis lambda event support to Parser utility +* Add cloudwatch lambda event support to Parser utility +* Add alb lambda event support to Parser utility [#228](https://github.com/awslabs/aws-lambda-powertools-python/issues/228) +* Add Kinesis lambda event support to Parser utility +* Add S3 lambda event support to Parser utility [#224](https://github.com/awslabs/aws-lambda-powertools-python/issues/224) +* Add Ses lambda event support to Parser utility [#213](https://github.com/awslabs/aws-lambda-powertools-python/issues/213) -## 0.11.0 - 2020-06-08 +## Maintenance -### Added -* Imports can now be made from top level of module, e.g.: `from aws_lambda_powertools import Logger, Metrics, Tracer` +* bump version to 1.9.0 -### Fixed -* **Metrics**: Fix a bug with Metrics causing an exception to be thrown when logging metrics if dimensions were not explicitly added. +## Pull Requests -### Changed -* **Metrics**: No longer throws exception by default in case no metrics are emitted when using the log_metrics decorator. +* Merge pull request [#227](https://github.com/awslabs/aws-lambda-powertools-python/issues/227) from risenberg-cyberark/kinesis +* Merge pull request [#225](https://github.com/awslabs/aws-lambda-powertools-python/issues/225) from risenberg-cyberark/s3 +* Merge pull request [#231](https://github.com/awslabs/aws-lambda-powertools-python/issues/231) from risenberg-cyberark/cloudwatch +* Merge pull request [#229](https://github.com/awslabs/aws-lambda-powertools-python/issues/229) from risenberg-cyberark/alb +* Merge pull request [#223](https://github.com/awslabs/aws-lambda-powertools-python/issues/223) from heitorlessa/docs/add-source-code-link +* Merge pull request [#222](https://github.com/awslabs/aws-lambda-powertools-python/issues/222) from awslabs/docs-fix-broken-link +* Merge pull request [#219](https://github.com/awslabs/aws-lambda-powertools-python/issues/219) from igorlg/docs/logger-supress-clarify +* Merge pull request [#214](https://github.com/awslabs/aws-lambda-powertools-python/issues/214) from risenberg-cyberark/ses -## 0.10.0 - 2020-06-08 -### Added -* **Metrics**: `capture_cold_start_metric` parameter added to `log_metrics` decorator -* **Metrics**: Optional `namespace` and `service` parameters added to Metrics constructor to more closely resemble other core utils + +## [v1.8.0] - 2020-11-20 +## Bug Fixes -### Changed -* **Metrics**: Default dimension is now created based on `service` parameter or `POWERTOOLS_SERVICE_NAME` env var +* replace now deprecated set-env with new GitHub Env file +* remove dummy heading to prevent htmlAst bug -### Deprecated -* **Metrics**: `add_namespace` method deprecated in favor of using `namespace` parameter to Metrics constructor or `POWERTOOLS_METRICS_NAMESPACE` env var +## Documentation -## 0.9.5 - 2020-06-02 +* correct example usage of SES data class +* add faq section +* add minimal permission set for using layer -### Fixed -* **Metrics**: Coerce non-string dimension values to string -* **Logger**: Correct `cold_start`, `function_memory_size` values from string to bool and int respectively +## Features -## 0.9.4 - 2020-05-29 +* include new replay-name field in parser and data_classes +* **data_classes:** API Gateway V2 IAM and Lambda -### Fixed -* **Metrics**: Fix issue where metrics were not correctly flushed, and cleared on every invocation +## Maintenance -## 0.9.3 - 2020-05-16 +* bump to 1.8.0 +* bump dependencies +* **docs:** Add some of the missing docstrings -### Fixed -* **Tracer**: Fix Runtime Error for nested sync due to incorrect loop usage +## Pull Requests -## 0.9.2 - 2020-05-14 +* Merge pull request [#212](https://github.com/awslabs/aws-lambda-powertools-python/issues/212) from heitorlessa/chore/bump-1.8.0 +* Merge pull request [#211](https://github.com/awslabs/aws-lambda-powertools-python/issues/211) from heitorlessa/feat/eventbridge-replay-support +* Merge pull request [#209](https://github.com/awslabs/aws-lambda-powertools-python/issues/209) from awslabs/docs/correct_ses_dataclass_example +* Merge pull request [#207](https://github.com/awslabs/aws-lambda-powertools-python/issues/207) from risenberg-cyberark/sns +* Merge pull request [#205](https://github.com/awslabs/aws-lambda-powertools-python/issues/205) from heitorlessa/chore/update-docs-dep +* Merge pull request [#202](https://github.com/awslabs/aws-lambda-powertools-python/issues/202) from Nr18/logger-faq +* Merge pull request [#204](https://github.com/awslabs/aws-lambda-powertools-python/issues/204) from am29d/docs/add-iam-permissions-for-layer +* Merge pull request [#201](https://github.com/awslabs/aws-lambda-powertools-python/issues/201) from gyft/feat-data-classes-event-updates -### Fixed -* **Tracer**: Import aiohttp lazily so it's not a hard dependency -## 0.9.0 - 2020-05-12 + +## [v1.7.0] - 2020-10-26 +## Bug Fixes -### Added -* **Tracer**: Support for async functions in `Tracer` via `capture_method` decorator -* **Tracer**: Support for `aiohttp` via `aiohttp_trace_config` trace config -* **Tracer**: Support for patching specific modules via `patch_modules` param -* **Tracer**: Document escape hatch mechanisms via `tracer.provider` +* _parse return type +* high and security peer dependency vulnerabilities +* change to Yarn to support manual resolutions +* generic type to match ABC bound class +* debug logging in envelopes before each parsing +* remove malformed 3.1. sentence +* ensures parser can take json strings as input +* parse high level import +* code inspect issues +* unnecessary return; better error handling +* snake_case +* comment out validators [#118](https://github.com/awslabs/aws-lambda-powertools-python/issues/118) +* CR fixes Merge branch 'develop' of https://github.com/awslabs/aws-lambda-powertools-python into pydantic +* reduce complexity of dynamo envelope +* poetry update + pydantic, typing_extensions as optional +* add only pydantic (+1 squashed commit) Squashed commits: [804f251] fix poetry.lock, revert changes +* Correct typo +* remove only dev extras +* remove jmespath extras in Make + +## Code Refactoring + +* pydantic as optional dependancy, remove lambdaContext +* change to advanced parser + +## Documentation + +* reorder parser's payload sample position +* add more info on conditional keys [#195](https://github.com/awslabs/aws-lambda-powertools-python/issues/195) +* add a note that decorator will replace the event +* address Ran's feedback +* reorder data validation; improve envelopes section +* reorder extending models as parse fn wasn't introduced +* use yarn's resolution to fix incompatible dependency +* add cold start data +* add a FAQ section +* ensure examples can be copied/pasted as-is +* add extending built-in models +* add envelope section +* add data model validation section +* use non-hello world model to better exemplify parsing +* add 101 parsing events content +* initial structure for parser docs +* initial sketch of parser docs +* update examples in README + +## Features + +* experiment with codeQL over LGTM +* add standalone parse function +* Advanced parser utility (pydantic) +* RFC: Validate incoming and outgoing events utility [#95](https://github.com/awslabs/aws-lambda-powertools-python/issues/95) +* **data_classes:** case insensitive header lookup +* **data_classes:** Cognito custom auth triggers + +## Maintenance + +* fix repository URL +* bump version to 1.7.0 +* spacing +* typo in list +* typo on code generation tool +* remove flake8 polyfill as explicit dep +* explicit DynamoDB Stream schema naming +* lint +* kwarg over arg to ease refactoring +* remove test for commented code +* fix make build syntax for internal build whl +* upgrade docs dep +* remove dev deps from example project +* remove kitchen sink example +* upgrade gatsby +* upgrade amplify, antd, and gatsby plugins +* upgrade apollo-docs theme +* remove dev deps from example project +* remove kitchen sink example + +## Reverts +* fix: remove jmespath extras in Make +* fix: remove jmespath extras in Make + +## Pull Requests + +* Merge pull request [#200](https://github.com/awslabs/aws-lambda-powertools-python/issues/200) from heitorlessa/chore/bump-1.7.0 +* Merge pull request [#199](https://github.com/awslabs/aws-lambda-powertools-python/issues/199) from heitorlessa/docs/clarify-dynamic-log-keys +* Merge pull request [#198](https://github.com/awslabs/aws-lambda-powertools-python/issues/198) from awslabs/improv/suppress-logger-propagation +* Merge pull request [#192](https://github.com/awslabs/aws-lambda-powertools-python/issues/192) from heitorlessa/docs/parser +* Merge pull request [#196](https://github.com/awslabs/aws-lambda-powertools-python/issues/196) from awslabs/dependabot/npm_and_yarn/docs/object-path-0.11.5 +* Merge pull request [#189](https://github.com/awslabs/aws-lambda-powertools-python/issues/189) from heitorlessa/improv/parser[#118](https://github.com/awslabs/aws-lambda-powertools-python/issues/118) +* Merge pull request [#186](https://github.com/awslabs/aws-lambda-powertools-python/issues/186) from gyft/feat-case-insensitive-dict +* Merge pull request [#188](https://github.com/awslabs/aws-lambda-powertools-python/issues/188) from gyft/tests-pydantic +* Merge pull request [#178](https://github.com/awslabs/aws-lambda-powertools-python/issues/178) from gyft/cognito-custom-auth +* Merge pull request [#118](https://github.com/awslabs/aws-lambda-powertools-python/issues/118) from risenberg-cyberark/pydantic +* Merge pull request [#181](https://github.com/awslabs/aws-lambda-powertools-python/issues/181) from awslabs/fix/docs-sec-vuln +* Merge pull request [#180](https://github.com/awslabs/aws-lambda-powertools-python/issues/180) from heitorlessa/chore/remove-example + + + +## [v1.6.1] - 2020-09-23 +## Maintenance + +* bump to 1.6.1 ([#177](https://github.com/awslabs/aws-lambda-powertools-python/issues/177)) + + + +## [v1.6.0] - 2020-09-22 +## Bug Fixes -## 0.8.1 - 2020-05-1 +* apply Tom's suggestion +* branding +* Correct description for data classes util +* duplicate features content +* navigation, branding +* remove DeleteMessageBatch call to SQS api if there are no messages to delete ([#170](https://github.com/awslabs/aws-lambda-powertools-python/issues/170)) +* correct type hint Dict instead of dict -### Fixed +## Code Refactoring -* **Metrics**: Fix metric unit casting logic if one passes plain string (value or key) -* **Metrics:**: Fix `MetricUnit` enum values for - * `BytesPerSecond` - * `KilobytesPerSecond` - * `MegabytesPerSecond` - * `GigabytesPerSecond` - * `TerabytesPerSecond` - * `BitsPerSecond` - * `KilobitsPerSecond` - * `MegabitsPerSecond` - * `GigabitsPerSecond` - * `TerabitsPerSecond` - * `CountPerSecond` +* correct type hint -## 0.8.0 - 2020-04-24 +## Documentation -### Added -* **Logger**: Introduced `Logger` class for structured logging as a replacement for `logger_setup` -* **Logger**: Introduced `Logger.inject_lambda_context` decorator as a replacement for `logger_inject_lambda_context` +* fixed more typos, correct index reference to new util +* fix typo in DynamoDB example +* add docs for data classes utility +* improve wording on jmespath fns +* document validator utility -### Removed -* **Logger**: Raise `DeprecationWarning` exception for both `logger_setup`, `logger_inject_lambda_context` +## Features -## 0.7.0 - 2020-04-20 +* add custom jmespath functions support +* emf multiple metric values ([#167](https://github.com/awslabs/aws-lambda-powertools-python/issues/167)) +* add initial validator tests +* add cloudwatch_logs based on Bryan's feedback +* add powertools_base64 custom fn +* add built-in envelopes +* add jmespath as optional dependency +* add initial draft simple validator +* **trigger:** data class and helper functions for lambda trigger events ([#159](https://github.com/awslabs/aws-lambda-powertools-python/issues/159)) -### Added -* **Middleware factory**: Introduced Middleware Factory to build your own middleware via `lambda_handler_decorator` +## Maintenance -### Fixed -* **Metrics**: Fixed metrics dimensions not being included correctly in EMF +* typo +* bump to 1.6.0 +* better type hinting +* update changelog +* fix docstring; import order -## 0.6.3 - 2020-04-09 +## Pull Requests -### Fixed -* **Logger**: Fix `log_metrics` decorator logic not calling the decorated function, and exception handling +* Merge pull request [#175](https://github.com/awslabs/aws-lambda-powertools-python/issues/175) from heitorlessa/chore/bump-1.6.0 +* Merge pull request [#171](https://github.com/awslabs/aws-lambda-powertools-python/issues/171) from awslabs/docs/data_classes +* Merge pull request [#174](https://github.com/awslabs/aws-lambda-powertools-python/issues/174) from heitorlessa/improv/docs-logger-metrics-testing +* Merge pull request [#168](https://github.com/awslabs/aws-lambda-powertools-python/issues/168) from gyft/tests-missing +* Merge pull request [#153](https://github.com/awslabs/aws-lambda-powertools-python/issues/153) from heitorlessa/feat/validator-utility -## 0.6.1 - 2020-04-08 -### Added -* **Metrics**: Introduces Metrics middleware to utilise CloudWatch Embedded Metric Format + +## [v1.5.0] - 2020-09-04 +## Bug Fixes -### Deprecated -* **Metrics**: Added deprecation warning for `log_metrics` +* throw exception by default if messages processing fails +* add sqs_batch_processor as its own method +* ensure debug log event has latest ctx +* update image with correct sample +* ensures xray_trace_id is refreshed +* typo in example +* include proposed suggestions +* **base-partial:** append record instead of entry +* **logging:** Don't include `json_default` in logs ([#132](https://github.com/awslabs/aws-lambda-powertools-python/issues/132)) + +## Code Refactoring + +* changes partial_sqs middleware in favor of a generic interface always expecting a BatchProcessor +* replace LambdaEvent with Dict[str, Any] +* remove initial reference +* fix import issues and provide context in docblocks +* split properties and add docblocks +* split the objects into seperate files +* make requested changes +* use None instead of +* batch middleware +* remove references to BaseProcessor. Left BasePartialProcessor +* change return for failure/success handlers +* **sqs:** add module middlewares +* **sqs:** change methods to protected +* **tests:** update tests to new batch processor middleware +* **tests:** processor using default config + +## Documentation + +* address readability feedbacks +* add detail to batch processing +* simplify documentation more SQS specific focus Update for sqs_batch_processor interface +* rephrase the wording to make it more clear +* refactor example; improve docs about creating your own processor +* add newly created Slack Channel +* describe the typing utility +* add troubleshooting section +* add xray_trace_id key +* fix suggestions made by [@heitorlessa](https://github.com/heitorlessa) +* add description where to find the layer arn ([#145](https://github.com/awslabs/aws-lambda-powertools-python/issues/145)) +* new section "Migrating from other Loggers" ([#148](https://github.com/awslabs/aws-lambda-powertools-python/issues/148)) +* minor edit to letter case part 2 +* user specific documentation +* Fix doc for log sampling ([#135](https://github.com/awslabs/aws-lambda-powertools-python/issues/135)) +* **partial-processor:** add simple docstrings to success/failure handlers +* **sqs:** docstrings for PartialSQS +* **sqs-base:** docstring for base class + +## Features + +* add xray_trace_id key when tracing is active [#137](https://github.com/awslabs/aws-lambda-powertools-python/issues/137) +* initial implementation as the proposed gist is +* add sqs failure processors +* include base processors +* add batch module +* add package level import for batch utility +* **logger:** readable log_dict seq +* **logging:** suppress some log keys +* **logging:** allow for custom json order +* **parameters:** transform = "auto" ([#133](https://github.com/awslabs/aws-lambda-powertools-python/issues/133)) +* **sqs:** add optional config parameter +* **sqs:** improve validation for queue_url + +## Maintenance + +* bump version to 1.5.0 ([#158](https://github.com/awslabs/aws-lambda-powertools-python/issues/158)) +* tiny changes for readability +* add debug logging for sqs batch processing +* remove middlewares module, moving decorator functionality to base and sqs +* add test for sqs_batch_processor interface +* add sqs_batch_processor decorator to simplify interface +* fix typos, docstrings and type hints ([#154](https://github.com/awslabs/aws-lambda-powertools-python/issues/154)) +* doc typo +* **batch:** Housekeeping for recent changes ([#157](https://github.com/awslabs/aws-lambda-powertools-python/issues/157)) + +## Pull Requests + +* Merge pull request [#149](https://github.com/awslabs/aws-lambda-powertools-python/issues/149) from Nr18/static-types +* Merge pull request [#155](https://github.com/awslabs/aws-lambda-powertools-python/issues/155) from awslabs/docs/batch_processing_util +* Merge pull request [#100](https://github.com/awslabs/aws-lambda-powertools-python/issues/100) from gmcrocetti/partial-sqs-batch +* Merge pull request [#151](https://github.com/awslabs/aws-lambda-powertools-python/issues/151) from Nr18/troubleshooting +* Merge pull request [#150](https://github.com/awslabs/aws-lambda-powertools-python/issues/150) from heitorlessa/feat/logger-add-xray-trace-id +* Merge pull request [#140](https://github.com/awslabs/aws-lambda-powertools-python/issues/140) from gyft/fix-log-key-order +* Merge pull request [#142](https://github.com/awslabs/aws-lambda-powertools-python/issues/142) from gyft/fix-letter-case + + + +## [v1.4.0] - 2020-08-25 +## Bug Fixes -## 0.5.0 - 2020-02-20 +* upgrade dot-prop, serialize-javascript +* remove actual response from debug logs +* naming and staticmethod consistency +* correct in_subsegment assertion +* update cold_start doc to reflect [#125](https://github.com/awslabs/aws-lambda-powertools-python/issues/125) +* split ColdStart metric to its own EMF blob [#125](https://github.com/awslabs/aws-lambda-powertools-python/issues/125) +* **ssm:** Make decrypt an explicit option and refactoring ([#123](https://github.com/awslabs/aws-lambda-powertools-python/issues/123)) + +## Documentation + +* add Lambda Layer SAR App url and ARN +* move tenets; remove extra space +* use table for clarity +* add blog post, and quick example +* subtle rewording for better clarity +* fix typos, log_event & sampling wording +* make sensitive info more explicit with an example +* create Patching modules section; cleanup response wording +* move concurrent asynchronous under escape hatch +* grammar +* bring new feature upfront when returning sensitive info + +## Features + +* capture_response as metadata option [#127](https://github.com/awslabs/aws-lambda-powertools-python/issues/127) + +## Maintenance + +* bump to 1.4.0 +* update internal docstrings for consistency +* update changelog to reflect new feature +* clarify changelog bugfix vs breaking change +* remove/correct unnecessary debug logs +* fix debug log adding unused obj +* grammar +* add metrics fix description +* correct typos + +## Pull Requests + +* Merge pull request [#129](https://github.com/awslabs/aws-lambda-powertools-python/issues/129) from am29d/feat/lambda-layers +* Merge pull request [#130](https://github.com/awslabs/aws-lambda-powertools-python/issues/130) from heitorlessa/docs/readability-improvements +* Merge pull request [#128](https://github.com/awslabs/aws-lambda-powertools-python/issues/128) from heitorlessa/feat/tracer-disallow-response-metadata +* Merge pull request [#126](https://github.com/awslabs/aws-lambda-powertools-python/issues/126) from heitorlessa/fix/metrics-cold-start-split + + + +## [v1.3.1] - 2020-08-22 +## Bug Fixes -### Added -* **Logger**: Introduced log sampling for debug - Thanks to [Danilo's contribution](https://github.com/awslabs/aws-lambda-powertools/pull/7) +* **capture_method:** should yield inside with ([#124](https://github.com/awslabs/aws-lambda-powertools-python/issues/124)) + +## Maintenance + +* version bump to 1.3.1 +* **deps:** bump prismjs from 1.20.0 to 1.21.0 in /docs +* **deps:** bump elliptic from 6.5.2 to 6.5.3 in /docs + +## Pull Requests + +* Merge pull request [#120](https://github.com/awslabs/aws-lambda-powertools-python/issues/120) from awslabs/dependabot/npm_and_yarn/docs/elliptic-6.5.3 +* Merge pull request [#121](https://github.com/awslabs/aws-lambda-powertools-python/issues/121) from awslabs/dependabot/npm_and_yarn/docs/prismjs-1.21.0 + + + +## [v1.3.0] - 2020-08-21 +## Features + +* add parameter utility ([#96](https://github.com/awslabs/aws-lambda-powertools-python/issues/96)) + +## Maintenance + +* bump version to 1.3.0 ([#122](https://github.com/awslabs/aws-lambda-powertools-python/issues/122)) + + + +## [v1.2.0] - 2020-08-20 +## Features + +* add support for tracing of generators using capture_method decorator ([#113](https://github.com/awslabs/aws-lambda-powertools-python/issues/113)) + +## Maintenance + +* bump version to 1.2.0 ([#119](https://github.com/awslabs/aws-lambda-powertools-python/issues/119)) + + + +## [v1.1.3] - 2020-08-18 +## Bug Fixes -## 0.1.0 - 2019-11-15 +* remove root logger handler set by Lambda [#115](https://github.com/awslabs/aws-lambda-powertools-python/issues/115) + +## Maintenance + +* bump to 1.1.3 + +## Pull Requests + +* Merge pull request [#117](https://github.com/awslabs/aws-lambda-powertools-python/issues/117) from heitorlessa/chore/bump-1.1.3 +* Merge pull request [#116](https://github.com/awslabs/aws-lambda-powertools-python/issues/116) from heitorlessa/fix/remove-root-logger-handler + + + +## [v1.1.2] - 2020-08-16 +## Bug Fixes + +* return subclass [#107](https://github.com/awslabs/aws-lambda-powertools-python/issues/107) + +## Documentation + +* clarify auto_patch as per [#108](https://github.com/awslabs/aws-lambda-powertools-python/issues/108) + +## Maintenance + +* bump version to 1.1.2 +* suppress LGTM alert +* add autocomplete as unreleased +* remove unused stdout fixture +* update Tracer docs as per [#108](https://github.com/awslabs/aws-lambda-powertools-python/issues/108) + +## Pull Requests + +* Merge pull request [#111](https://github.com/awslabs/aws-lambda-powertools-python/issues/111) from heitorlessa/chore/bump-1.1.2 +* Merge pull request [#110](https://github.com/awslabs/aws-lambda-powertools-python/issues/110) from heitorlessa/improv/logger-auto-complete +* Merge pull request [#109](https://github.com/awslabs/aws-lambda-powertools-python/issues/109) from heitorlessa/docs/tracer-reuse + + + +## [v1.1.1] - 2020-08-14 +## Bug Fixes + +* regression 104 ([#105](https://github.com/awslabs/aws-lambda-powertools-python/issues/105)) +* return log level int immediately +* add test covering logging constant + +## Maintenance + +* bump patch version +* fix unused fixture +* fix docstring on level [str,int] consistency +* fix test level typo +* trigger docs on new release ([#102](https://github.com/awslabs/aws-lambda-powertools-python/issues/102)) ([#103](https://github.com/awslabs/aws-lambda-powertools-python/issues/103)) +* trigger docs on new release ([#102](https://github.com/awslabs/aws-lambda-powertools-python/issues/102)) +* trigger docs on new release + +## Regression + +* log level docstring as str + +## Pull Requests + +* Merge pull request [#106](https://github.com/awslabs/aws-lambda-powertools-python/issues/106) from heitorlessa/fix/regression-104 + + + +## [v1.1.0] - 2020-08-14 +## Bug Fixes + +* auto-assigner filename as per docs + +## Features + +* add support for logger inheritance ([#99](https://github.com/awslabs/aws-lambda-powertools-python/issues/99)) +* enable issue auto-assigner to core team + +## Maintenance + +* bump to 1.1.0 ([#101](https://github.com/awslabs/aws-lambda-powertools-python/issues/101)) +* **deps:** bump lodash from 4.17.15 to 4.17.19 in /docs ([#93](https://github.com/awslabs/aws-lambda-powertools-python/issues/93)) + + + +## [v1.0.2] - 2020-07-16 +## Maintenance + +* bump to 1.0.2 ([#90](https://github.com/awslabs/aws-lambda-powertools-python/issues/90)) +* support aws-xray-sdk >=2.5.0 till <3.0.0 ([#89](https://github.com/awslabs/aws-lambda-powertools-python/issues/89)) + + + +## [v1.0.1] - 2020-07-05 +## Bug Fixes + +* append structured logs when injecting lambda context ([#86](https://github.com/awslabs/aws-lambda-powertools-python/issues/86)) + +## Documentation + +* add blog post in the readme + + + +## [v1.0.0] - 2020-06-18 +## Documentation + +* customize contributing guide ([#77](https://github.com/awslabs/aws-lambda-powertools-python/issues/77)) + +## Features + +* docs anonymized page view ([#82](https://github.com/awslabs/aws-lambda-powertools-python/issues/82)) +* add metrics metadata ([#81](https://github.com/awslabs/aws-lambda-powertools-python/issues/81)) + +## Maintenance + +* bump to 1.0.0 GA ([#83](https://github.com/awslabs/aws-lambda-powertools-python/issues/83)) +* add missing ':' and identation in examples +* cleanup tests ([#79](https://github.com/awslabs/aws-lambda-powertools-python/issues/79)) +* remove deprecated code before GA ([#78](https://github.com/awslabs/aws-lambda-powertools-python/issues/78)) +* move blockquotes as hidden comments + + + +## [v0.11.0] - 2020-06-10 +## Bug Fixes + +* default dimension creation now happens when metrics are serialized instead of on metrics constructor ([#74](https://github.com/awslabs/aws-lambda-powertools-python/issues/74)) + +## Maintenance + +* update CHANGELOG +* bump version to 0.11.0 ([#76](https://github.com/awslabs/aws-lambda-powertools-python/issues/76)) + + + +## [v0.10.1] - 2020-06-10 +## Bug Fixes + +* default dimension creation now happens when metrics are serialized instead of on metrics constructor ([#74](https://github.com/awslabs/aws-lambda-powertools-python/issues/74)) + +## Documentation + +* fix contrast on highlighted code text ([#73](https://github.com/awslabs/aws-lambda-powertools-python/issues/73)) + +## Features + +* improve error handling for log_metrics decorator ([#71](https://github.com/awslabs/aws-lambda-powertools-python/issues/71)) +* add high level imports ([#70](https://github.com/awslabs/aws-lambda-powertools-python/issues/70)) + +## Maintenance + +* version bump 0.10.1 +* **deps:** bump graphql-playground-html from 1.6.19 to 1.6.25 in /docs + +## Pull Requests + +* Merge pull request [#72](https://github.com/awslabs/aws-lambda-powertools-python/issues/72) from awslabs/dependabot/npm_and_yarn/docs/graphql-playground-html-1.6.25 + + + +## v0.10.0 - 2020-06-08 +## Bug Fixes -### Added -* Public beta release +* correct env var name for publish to pypi test ([#69](https://github.com/awslabs/aws-lambda-powertools-python/issues/69)) +* release-drafter action syntax +* release-drafter label for new feature/major non-breaking changes +* cast dimension value to str to avoid issue where EMF silently fails ([#52](https://github.com/awslabs/aws-lambda-powertools-python/issues/52)) +* ignore path that might seem a broken link [#49](https://github.com/awslabs/aws-lambda-powertools-python/issues/49) +* open api ref in a new tab [#48](https://github.com/awslabs/aws-lambda-powertools-python/issues/48) +* metrics not being flushed on every invocation ([#45](https://github.com/awslabs/aws-lambda-powertools-python/issues/45)) +* [#35](https://github.com/awslabs/aws-lambda-powertools-python/issues/35) duplicate changelog to project root +* [#24](https://github.com/awslabs/aws-lambda-powertools-python/issues/24) correct example test and docs +* CI attempt 4 +* CI attempt 3 +* CI attempt 3 +* CI attempt 2 +* add missing single_metric example; test var name +* fix import of aws_lambda_logging to relative import +* **Makefile:** format before linting +* **make:** add twine as a dev dep +* **setup:** correct invalid license classifier +* **setup:** correct license to MIT-0 in meta + +## Documentation + +* build on master only +* clarify logger debug sampling message +* clean up readme in favour of docs website +* add install in main docs website +* add pypi badge + +## Features + +* add capture_cold_start_metric for log_metrics ([#67](https://github.com/awslabs/aws-lambda-powertools-python/issues/67)) +* automate publishing to pypi ([#58](https://github.com/awslabs/aws-lambda-powertools-python/issues/58)) +* add pre-commit hooks ([#64](https://github.com/awslabs/aws-lambda-powertools-python/issues/64)) +* update Metrics interface to resemble tracer & logger: use "service" as its namespace. +* add codecov service ([#59](https://github.com/awslabs/aws-lambda-powertools-python/issues/59)) +* add security and complexity baseline [#33](https://github.com/awslabs/aws-lambda-powertools-python/issues/33) ([#57](https://github.com/awslabs/aws-lambda-powertools-python/issues/57)) +* add pull request template [#33](https://github.com/awslabs/aws-lambda-powertools-python/issues/33) +* add RFC template for proposals +* create issue templates +* readd release drafter action [#33](https://github.com/awslabs/aws-lambda-powertools-python/issues/33) +* add release drafter ([#56](https://github.com/awslabs/aws-lambda-powertools-python/issues/56)) +* add stale issues config [#33](https://github.com/awslabs/aws-lambda-powertools-python/issues/33) ([#55](https://github.com/awslabs/aws-lambda-powertools-python/issues/55)) +* enforce semantic PR titles ([#54](https://github.com/awslabs/aws-lambda-powertools-python/issues/54)) +* add algolia search for docs and api ref ([#39](https://github.com/awslabs/aws-lambda-powertools-python/issues/39)) +* add documentation website ([#37](https://github.com/awslabs/aws-lambda-powertools-python/issues/37)) +* add docs to CI +* Add Python3.8 support +* **logger:** add log sampling +* **pypi:** add bumpversion, public release pypi +* **pyproject.toml:** move to poetry + +## Maintenance + +* version bump ([#68](https://github.com/awslabs/aws-lambda-powertools-python/issues/68)) +* public beta version +* rename Makefile target docs-dev to docs-local ([#65](https://github.com/awslabs/aws-lambda-powertools-python/issues/65)) +* correct docstring for log_metrics +* fix typo in metrics doc +* Correct test comment +* remove unused import +* formatting +* plat wheels are not needed +* reformat changelog to follow KeepAChangelog standard ([#50](https://github.com/awslabs/aws-lambda-powertools-python/issues/50)) +* bump to release candidate +* renamed history to changelog dependabot +* grammar issues +* bump example to use 0.8.0 features +* clean up CI workflows +* fix github badge typo +* pypi monthly download badge +* lint +* bump 0.3.1 with logging patch +* bump history +* lint +* add Python 3.8 in badge as it's supported +* CI badge +* public beta version +* **deps:** bump bleach from 3.1.0 to 3.1.1 in /python +* **deps:** bump websocket-extensions from 0.1.3 to 0.1.4 in /docs ([#66](https://github.com/awslabs/aws-lambda-powertools-python/issues/66)) + +## Pull Requests + +* Merge pull request [#60](https://github.com/awslabs/aws-lambda-powertools-python/issues/60) from awslabs/improv/metrics_interface +* Merge pull request [#8](https://github.com/awslabs/aws-lambda-powertools-python/issues/8) from awslabs/dependabot/pip/python/bleach-3.1.1 +* Merge pull request [#7](https://github.com/awslabs/aws-lambda-powertools-python/issues/7) from danilohgds/sampling_feature +* 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.26.4...HEAD +[v1.26.4]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.26.3...v1.26.4 +[v1.26.3]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.26.2...v1.26.3 +[v1.26.2]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.26.1...v1.26.2 +[v1.26.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.26.0...v1.26.1 +[v1.26.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.10...v1.26.0 +[v1.25.10]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.9...v1.25.10 +[v1.25.9]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.8...v1.25.9 +[v1.25.8]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.7...v1.25.8 +[v1.25.7]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.6...v1.25.7 +[v1.25.6]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.5...v1.25.6 +[v1.25.5]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.4...v1.25.5 +[v1.25.4]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.3...v1.25.4 +[v1.25.3]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.2...v1.25.3 +[v1.25.2]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.1...v1.25.2 +[v1.25.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.25.0...v1.25.1 +[v1.25.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.24.2...v1.25.0 +[v1.24.2]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.24.1...v1.24.2 +[v1.24.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.24.0...v1.24.1 +[v1.24.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.23.0...v1.24.0 +[v1.23.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.22.0...v1.23.0 +[v1.22.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.21.1...v1.22.0 +[v1.21.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.21.0...v1.21.1 +[v1.21.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.20.2...v1.21.0 +[v1.20.2]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.20.1...v1.20.2 +[v1.20.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.20.0...v1.20.1 +[v1.20.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.19.0...v1.20.0 +[v1.19.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.18.1...v1.19.0 +[v1.18.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.18.0...v1.18.1 +[v1.18.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.17.1...v1.18.0 +[v1.17.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.17.0...v1.17.1 +[v1.17.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.16.1...v1.17.0 +[v1.16.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.16.0...v1.16.1 +[v1.16.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.15.1...v1.16.0 +[v1.15.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.15.0...v1.15.1 +[v1.15.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.14.0...v1.15.0 +[v1.14.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.13.0...v1.14.0 +[v1.13.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.12.0...v1.13.0 +[v1.12.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.11.0...v1.12.0 +[v1.11.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.10.5...v1.11.0 +[v1.10.5]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.10.4...v1.10.5 +[v1.10.4]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.10.3...v1.10.4 +[v1.10.3]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.10.2...v1.10.3 +[v1.10.2]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.10.1...v1.10.2 +[v1.10.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.10.0...v1.10.1 +[v1.10.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.9.1...v1.10.0 +[v1.9.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.9.0...v1.9.1 +[v1.9.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.8.0...v1.9.0 +[v1.8.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.7.0...v1.8.0 +[v1.7.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.6.1...v1.7.0 +[v1.6.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.6.0...v1.6.1 +[v1.6.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.5.0...v1.6.0 +[v1.5.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.4.0...v1.5.0 +[v1.4.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.3.1...v1.4.0 +[v1.3.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.3.0...v1.3.1 +[v1.3.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.2.0...v1.3.0 +[v1.2.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.1.3...v1.2.0 +[v1.1.3]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.1.2...v1.1.3 +[v1.1.2]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.1.1...v1.1.2 +[v1.1.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.1.0...v1.1.1 +[v1.1.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.0.2...v1.1.0 +[v1.0.2]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.0.1...v1.0.2 +[v1.0.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v1.0.0...v1.0.1 +[v1.0.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v0.11.0...v1.0.0 +[v0.11.0]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v0.10.1...v0.11.0 +[v0.10.1]: https://github.com/awslabs/aws-lambda-powertools-python/compare/v0.10.0...v0.10.1 diff --git a/pyproject.toml b/pyproject.toml index f10a2a45234..6afeb020903 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "1.26.3" +version = "1.26.4" description = "A suite of utilities for AWS Lambda functions to ease adopting best practices such as tracing, structured logging, custom metrics, batching, idempotency, feature flags, and more." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From df058ba83b21953b3156316edabdfcdd2069dd90 Mon Sep 17 00:00:00 2001 From: Ruben Fonseca Date: Mon, 18 Jul 2022 14:29:14 +0200 Subject: [PATCH 18/30] chore(ci): adds caching when installing python dependencies (#1311) --- .github/workflows/publish.yml | 8 ++++++++ .github/workflows/python_build.yml | 1 + .github/workflows/python_docs.yml | 1 + .github/workflows/rebuild_latest_docs.yml | 1 + .github/workflows/run-e2e-tests.yml | 1 + 5 files changed, 12 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1473fba2fcb..a36231bcf16 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,6 +44,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: "3.8" + cache: "poetry" - name: Set release notes tag id: release_version # transform tag format `v Date: Tue, 19 Jul 2022 12:04:51 +0200 Subject: [PATCH 19/30] fix(ci): install poetry before calling setup/python with cache (#1315) --- .github/workflows/publish.yml | 4 ++++ .github/workflows/publish_layer.yml | 2 ++ .github/workflows/python_build.yml | 2 ++ .github/workflows/python_docs.yml | 2 ++ .github/workflows/rebuild_latest_docs.yml | 2 ++ .github/workflows/run-e2e-tests.yml | 2 ++ 6 files changed, 14 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a36231bcf16..1c7cd4c2002 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,6 +40,8 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Install poetry + run: pipx install poetry - name: Set up Python uses: actions/setup-python@v4 with: @@ -106,6 +108,8 @@ jobs: run: | git config user.name "Release bot" git config user.email aws-devax-open-source@amazon.com + - name: Install poetry + run: pipx install poetry - name: Set up Python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index 3fe6afd6098..35ae1fd731b 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -29,6 +29,8 @@ jobs: uses: actions/setup-node@v3 with: node-version: "16.12" + - name: Install poetry + run: pipx install poetry - name: Setup python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/python_build.yml b/.github/workflows/python_build.yml index f8491e965b4..4280fe531e5 100644 --- a/.github/workflows/python_build.yml +++ b/.github/workflows/python_build.yml @@ -32,6 +32,8 @@ jobs: PYTHON: ${{ matrix.python-version }} steps: - uses: actions/checkout@v3 + - name: Install poetry + run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: diff --git a/.github/workflows/python_docs.yml b/.github/workflows/python_docs.yml index 405a59beb5a..ace4b28dc3f 100644 --- a/.github/workflows/python_docs.yml +++ b/.github/workflows/python_docs.yml @@ -23,6 +23,8 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Install poetry + run: pipx install poetry - name: Set up Python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/rebuild_latest_docs.yml b/.github/workflows/rebuild_latest_docs.yml index b664f922d10..2189eb76171 100644 --- a/.github/workflows/rebuild_latest_docs.yml +++ b/.github/workflows/rebuild_latest_docs.yml @@ -26,6 +26,8 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Install poetry + run: pipx install poetry - name: Set up Python uses: actions/setup-python@v4 with: diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 7268479e13f..a020410823c 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -16,6 +16,8 @@ jobs: steps: - name: "Checkout" uses: actions/checkout@v3 + - name: Install poetry + run: pipx install poetry - name: "Use Python" uses: actions/setup-python@v3 with: From d440e99d241867d388cba1611ea7b39f199e7883 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 19 Jul 2022 15:04:51 +0200 Subject: [PATCH 20/30] fix(ci): remove additional quotes in PR action (#1317) --- .github/scripts/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/constants.js b/.github/scripts/constants.js index 2c1d6f9ab76..3447bef0ac2 100644 --- a/.github/scripts/constants.js +++ b/.github/scripts/constants.js @@ -1,7 +1,7 @@ module.exports = Object.freeze({ /** @type {string} */ // Values: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request - "PR_ACTION": process.env.PR_ACTION || "", + "PR_ACTION": process.env.PR_ACTION?.replace(/"/g, '') || "", /** @type {string} */ "PR_AUTHOR": process.env.PR_AUTHOR?.replace(/"/g, '') || "", From 24d7b5fb67159634adb685d2b6f60f02dade471e Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Tue, 19 Jul 2022 15:09:35 +0200 Subject: [PATCH 21/30] fix(ci): lambda layer workflow release version and conditionals (#1316) --- .github/workflows/publish_layer.yml | 8 ++-- .../workflows/reusable_deploy_layer_stack.yml | 46 ++++++++++--------- layer/layer/layer_stack.py | 3 +- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index 35ae1fd731b..3597f0d8253 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -16,9 +16,11 @@ on: types: - completed + jobs: build-layer: runs-on: ubuntu-latest + if: ${{ (github.event.workflow_run.conclusion == 'success') || (github.event_name == 'workflow_dispatch') }} defaults: run: working-directory: ./layer @@ -29,8 +31,6 @@ jobs: uses: actions/setup-node@v3 with: node-version: "16.12" - - name: Install poetry - run: pipx install poetry - name: Setup python uses: actions/setup-python@v4 with: @@ -39,8 +39,8 @@ jobs: - name: Set release notes tag run: | RELEASE_INPUT=${{ inputs.latest_published_version }} - GITHUB_EVENT_RELEASE_TAG=${{ github.event.release.tag_name }} - RELEASE_TAG_VERSION=${GITHUB_EVENT_RELEASE_TAG:-$RELEASE_INPUT} + LATEST_TAG=$(git describe --tag --abbrev=0) + RELEASE_TAG_VERSION=${RELEASE_INPUT:-$LATEST_TAG} echo "RELEASE_TAG_VERSION=${RELEASE_TAG_VERSION:1}" >> $GITHUB_ENV - name: install cdk and deps run: | diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 74d2dc19767..45c97860438 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -26,28 +26,30 @@ jobs: strategy: fail-fast: false matrix: - region: ["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" + region: [ + "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" + ] steps: - name: checkout uses: actions/checkout@v3 diff --git a/layer/layer/layer_stack.py b/layer/layer/layer_stack.py index 8b32de9c206..15f3d3fdcb8 100644 --- a/layer/layer/layer_stack.py +++ b/layer/layer/layer_stack.py @@ -1,4 +1,4 @@ -from aws_cdk import Stack +from aws_cdk import RemovalPolicy, Stack from aws_cdk.aws_ssm import StringParameter from cdk_lambda_powertools_python_layer import LambdaPowertoolsLayer from constructs import Construct @@ -15,5 +15,6 @@ def __init__( ) layer.add_permission("PublicLayerAccess", account_id="*") + layer.apply_removal_policy(RemovalPolicy.RETAIN) StringParameter(self, "VersionArn", parameter_name=ssm_paramter_layer_arn, string_value=layer.layer_version_arn) From 36f22e90bdfa787ce295b99c0727728912640b85 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Tue, 19 Jul 2022 15:24:11 +0200 Subject: [PATCH 22/30] fix(ci): fetch all git info so we can check tags --- .github/workflows/publish_layer.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index 3597f0d8253..81d46226a4c 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -27,6 +27,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v3 with: From 29f654b70a7caf575c74ae5ef63cf4e67d851b01 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Tue, 19 Jul 2022 15:09:35 +0200 Subject: [PATCH 23/30] fix(ci): lambda layer workflow release version and conditionals (#1316) --- .github/workflows/publish_layer.yml | 10 ++-- .../workflows/reusable_deploy_layer_stack.yml | 46 ++++++++++--------- layer/layer/layer_stack.py | 3 +- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index 35ae1fd731b..81d46226a4c 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -16,21 +16,23 @@ on: types: - completed + jobs: build-layer: runs-on: ubuntu-latest + if: ${{ (github.event.workflow_run.conclusion == 'success') || (github.event_name == 'workflow_dispatch') }} defaults: run: working-directory: ./layer steps: - name: checkout uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: "16.12" - - name: Install poetry - run: pipx install poetry - name: Setup python uses: actions/setup-python@v4 with: @@ -39,8 +41,8 @@ jobs: - name: Set release notes tag run: | RELEASE_INPUT=${{ inputs.latest_published_version }} - GITHUB_EVENT_RELEASE_TAG=${{ github.event.release.tag_name }} - RELEASE_TAG_VERSION=${GITHUB_EVENT_RELEASE_TAG:-$RELEASE_INPUT} + LATEST_TAG=$(git describe --tag --abbrev=0) + RELEASE_TAG_VERSION=${RELEASE_INPUT:-$LATEST_TAG} echo "RELEASE_TAG_VERSION=${RELEASE_TAG_VERSION:1}" >> $GITHUB_ENV - name: install cdk and deps run: | diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 74d2dc19767..45c97860438 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -26,28 +26,30 @@ jobs: strategy: fail-fast: false matrix: - region: ["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" + region: [ + "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" + ] steps: - name: checkout uses: actions/checkout@v3 diff --git a/layer/layer/layer_stack.py b/layer/layer/layer_stack.py index 8b32de9c206..15f3d3fdcb8 100644 --- a/layer/layer/layer_stack.py +++ b/layer/layer/layer_stack.py @@ -1,4 +1,4 @@ -from aws_cdk import Stack +from aws_cdk import RemovalPolicy, Stack from aws_cdk.aws_ssm import StringParameter from cdk_lambda_powertools_python_layer import LambdaPowertoolsLayer from constructs import Construct @@ -15,5 +15,6 @@ def __init__( ) layer.add_permission("PublicLayerAccess", account_id="*") + layer.apply_removal_policy(RemovalPolicy.RETAIN) StringParameter(self, "VersionArn", parameter_name=ssm_paramter_layer_arn, string_value=layer.layer_version_arn) From 182531d57857a57d2e9e15807ebd2cc30a8237e6 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 19 Jul 2022 16:21:21 +0200 Subject: [PATCH 24/30] docs(governance): add security doc to the root --- SECURITY.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..9ac1494b13d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,8 @@ + + +## Reporting a Vulnerability + +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security +via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com. + +Please do **not** create a public GitHub issue. From 1aef472c911f504664e49e0464af9d431db2592f Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 19 Jul 2022 16:25:21 +0200 Subject: [PATCH 25/30] docs(governance): typos on PR template fixes #1314 --- .github/PULL_REQUEST_TEMPLATE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 806bbebcedb..73b5a3b8ab8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,4 @@ + **Issue number:** ## Summary @@ -15,11 +16,10 @@ If your change doesn't seem to apply, please leave them unchecked. * [ ] [Meet tenets criteria](https://awslabs.github.io/aws-lambda-powertools-python/#tenets) -* [ ] I have performed a self-review of my this change -* [ ] Changes are tested +* [ ] I have performed a self-review of this change +* [ ] Changes have been tested * [ ] Changes are documented -* [ ] PR title follows [conventional commit semantics](https://github.com/awslabs/aws-lambda-powertools-python/blob/376ec0a2ac0d2a40e0af5717bef42ff84ca0d1b9/.github/semantic.yml#L2) - +* [ ] PR title follows [conventional commit semantics](https://github.com/awslabs/aws-lambda-powertools-dotnet/blob/develop/.github/semantic.yml)
Is this a breaking change? From b6ed979b1f3ddc10fa830c1041c99371bba51468 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Tue, 19 Jul 2022 17:54:05 +0200 Subject: [PATCH 26/30] fix(ci): keep layer version permission (#1318) --- layer/layer/layer_stack.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/layer/layer/layer_stack.py b/layer/layer/layer_stack.py index 15f3d3fdcb8..c29c3816f55 100644 --- a/layer/layer/layer_stack.py +++ b/layer/layer/layer_stack.py @@ -1,4 +1,5 @@ from aws_cdk import RemovalPolicy, Stack +from aws_cdk.aws_lambda import CfnLayerVersionPermission from aws_cdk.aws_ssm import StringParameter from cdk_lambda_powertools_python_layer import LambdaPowertoolsLayer from constructs import Construct @@ -14,7 +15,15 @@ def __init__( self, "Layer", layer_version_name="AWSLambdaPowertoolsPython", version=powertools_version ) - layer.add_permission("PublicLayerAccess", account_id="*") + layer_permission = CfnLayerVersionPermission( + self, + "PublicLayerAccess", + action="lambda:GetLayerVersion", + layer_version_arn=layer.layer_version_arn, + principal="*", + ) + + layer_permission.apply_removal_policy(RemovalPolicy.RETAIN) layer.apply_removal_policy(RemovalPolicy.RETAIN) StringParameter(self, "VersionArn", parameter_name=ssm_paramter_layer_arn, string_value=layer.layer_version_arn) From a1fda405d3c2fd8fb0cf28500db29e13e1b6ecba Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 20 Jul 2022 09:00:00 +0200 Subject: [PATCH 27/30] fix(deps): correct mypy types as dev dependency (#1322) --- poetry.lock | 44 ++++---------------------------------------- pyproject.toml | 8 ++++---- 2 files changed, 8 insertions(+), 44 deletions(-) diff --git a/poetry.lock b/poetry.lock index a1f72d121a1..da01a58a7e2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -743,7 +743,7 @@ typing-extensions = ">=4.1.0" name = "mypy-boto3-cloudwatch" version = "1.24.0" description = "Type annotations for boto3.CloudWatch 1.24.0 service generated with mypy-boto3-builder 7.6.1" -category = "main" +category = "dev" optional = false python-versions = ">=3.6" @@ -765,7 +765,7 @@ typing-extensions = ">=4.1.0" name = "mypy-boto3-lambda" version = "1.24.0" description = "Type annotations for boto3.Lambda 1.24.0 service generated with mypy-boto3-builder 7.6.1" -category = "main" +category = "dev" optional = false python-versions = ">=3.6" @@ -798,7 +798,7 @@ typing-extensions = ">=4.1.0" name = "mypy-boto3-xray" version = "1.24.0" description = "Type annotations for boto3.XRay 1.24.0 service generated with mypy-boto3-builder 7.6.1" -category = "main" +category = "dev" optional = false python-versions = ">=3.6" @@ -1323,7 +1323,7 @@ pydantic = ["pydantic", "email-validator"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "160d80d73190474a97b16859405adf04618bc26564b9b927e6c31ab706f247d1" +content-hash = "1146855891d6902b7452d2dc53fd12a4753bebe10a2511d75e0cd99beffcd31b" [metadata.files] atomicwrites = [ @@ -1563,28 +1563,12 @@ markdown = [ {file = "Markdown-3.3.5.tar.gz", hash = "sha256:26e9546bfbcde5fcd072bd8f612c9c1b6e2677cb8aadbdf65206674f46dde069"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1593,27 +1577,14 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1623,12 +1594,6 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1730,7 +1695,6 @@ pbr = [ {file = "pbr-5.8.0.tar.gz", hash = "sha256:672d8ebee84921862110f23fcec2acea191ef58543d34dfe9ef3d9f13c31cddf"}, ] pdoc3 = [ - {file = "pdoc3-0.10.0-py3-none-any.whl", hash = "sha256:ba45d1ada1bd987427d2bf5cdec30b2631a3ff5fb01f6d0e77648a572ce6028b"}, {file = "pdoc3-0.10.0.tar.gz", hash = "sha256:5f22e7bcb969006738e1aa4219c75a32f34c2d62d46dc9d2fb2d3e0b0287e4b7"}, ] platformdirs = [ diff --git a/pyproject.toml b/pyproject.toml index 6afeb020903..b6258d19664 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,12 +26,9 @@ fastjsonschema = "^2.14.5" boto3 = "^1.18" pydantic = {version = "^1.8.2", optional = true } email-validator = {version = "*", optional = true } -mypy-boto3-cloudwatch = "^1.24.0" -mypy-boto3-lambda = "^1.24.0" -mypy-boto3-xray = "^1.24.0" [tool.poetry.dev-dependencies] -# 2022-04-21: jmespath was removed, to be re-added once we drop python 3.6. +# Maintenance: 2022-04-21 jmespath was removed, to be re-added once we drop python 3.6. # issue #1148 coverage = {extras = ["toml"], version = "^6.2"} pytest = "^7.0.1" @@ -66,6 +63,9 @@ retry = "^0.9.2" pytest-xdist = "^2.5.0" aws-cdk-lib = "^2.23.0" pytest-benchmark = "^3.4.1" +mypy-boto3-cloudwatch = "^1.24.0" +mypy-boto3-lambda = "^1.24.0" +mypy-boto3-xray = "^1.24.0" [tool.poetry.extras] From ecb95613921d9263ba8e52c80ca2f177f46e01c3 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 20 Jul 2022 09:01:40 +0200 Subject: [PATCH 28/30] chore(governance): fix typo on semantic commit link introduced in #1aef4 --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 73b5a3b8ab8..de2d40678ba 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -19,7 +19,7 @@ If your change doesn't seem to apply, please leave them unchecked. * [ ] I have performed a self-review of this change * [ ] Changes have been tested * [ ] Changes are documented -* [ ] PR title follows [conventional commit semantics](https://github.com/awslabs/aws-lambda-powertools-dotnet/blob/develop/.github/semantic.yml) +* [ ] PR title follows [conventional commit semantics](https://github.com/awslabs/aws-lambda-powertools-python/blob/develop/.github/semantic.yml)
Is this a breaking change? From ab2349151cc00e7c41ce0651bd08be8abb37a231 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Jul 2022 07:07:43 +0000 Subject: [PATCH 29/30] chore(deps-dev): bump mypy from 0.961 to 0.971 (#1320) --- poetry.lock | 86 +++++++++++++++++++++++++++++++++++--------------- pyproject.toml | 2 +- 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/poetry.lock b/poetry.lock index da01a58a7e2..0a91ac12ac6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -711,7 +711,7 @@ python-versions = ">=3.6" [[package]] name = "mypy" -version = "0.961" +version = "0.971" description = "Optional static typing for Python" category = "dev" optional = false @@ -1323,7 +1323,7 @@ pydantic = ["pydantic", "email-validator"] [metadata] lock-version = "1.1" python-versions = "^3.6.2" -content-hash = "1146855891d6902b7452d2dc53fd12a4753bebe10a2511d75e0cd99beffcd31b" +content-hash = "2ad17737aa164a36280e47d1578946adae4548376fe6f4584d458d3f00ad56fe" [metadata.files] atomicwrites = [ @@ -1563,12 +1563,28 @@ markdown = [ {file = "Markdown-3.3.5.tar.gz", hash = "sha256:26e9546bfbcde5fcd072bd8f612c9c1b6e2677cb8aadbdf65206674f46dde069"}, ] markupsafe = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1577,14 +1593,27 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1594,6 +1623,12 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -1626,29 +1661,29 @@ mkdocs-material-extensions = [ {file = "mkdocs_material_extensions-1.0.3-py3-none-any.whl", hash = "sha256:a82b70e533ce060b2a5d9eb2bc2e1be201cf61f901f93704b4acf6e3d5983a44"}, ] mypy = [ - {file = "mypy-0.961-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0"}, - {file = "mypy-0.961-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15"}, - {file = "mypy-0.961-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3"}, - {file = "mypy-0.961-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e"}, - {file = "mypy-0.961-cp310-cp310-win_amd64.whl", hash = "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24"}, - {file = "mypy-0.961-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723"}, - {file = "mypy-0.961-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b"}, - {file = "mypy-0.961-cp36-cp36m-win_amd64.whl", hash = "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d"}, - {file = "mypy-0.961-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813"}, - {file = "mypy-0.961-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e"}, - {file = "mypy-0.961-cp37-cp37m-win_amd64.whl", hash = "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a"}, - {file = "mypy-0.961-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6"}, - {file = "mypy-0.961-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6"}, - {file = "mypy-0.961-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d"}, - {file = "mypy-0.961-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b"}, - {file = "mypy-0.961-cp38-cp38-win_amd64.whl", hash = "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569"}, - {file = "mypy-0.961-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932"}, - {file = "mypy-0.961-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5"}, - {file = "mypy-0.961-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648"}, - {file = "mypy-0.961-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950"}, - {file = "mypy-0.961-cp39-cp39-win_amd64.whl", hash = "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56"}, - {file = "mypy-0.961-py3-none-any.whl", hash = "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66"}, - {file = "mypy-0.961.tar.gz", hash = "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492"}, + {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"}, ] mypy-boto3-appconfig = [ {file = "mypy-boto3-appconfig-1.24.29.tar.gz", hash = "sha256:10583d309a9db99babfbe85d3b6467b49b3509a57e4f8771da239f6d5cb3731b"}, @@ -1695,6 +1730,7 @@ pbr = [ {file = "pbr-5.8.0.tar.gz", hash = "sha256:672d8ebee84921862110f23fcec2acea191ef58543d34dfe9ef3d9f13c31cddf"}, ] pdoc3 = [ + {file = "pdoc3-0.10.0-py3-none-any.whl", hash = "sha256:ba45d1ada1bd987427d2bf5cdec30b2631a3ff5fb01f6d0e77648a572ce6028b"}, {file = "pdoc3-0.10.0.tar.gz", hash = "sha256:5f22e7bcb969006738e1aa4219c75a32f34c2d62d46dc9d2fb2d3e0b0287e4b7"}, ] platformdirs = [ diff --git a/pyproject.toml b/pyproject.toml index b6258d19664..4d5fdc56adc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ flake8-eradicate = "^1.2.1" flake8-bugbear = "^22.7.1" mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^0.6.0" -mypy = "^0.961" +mypy = "^0.971" mkdocs-material = "^8.2.7" mypy-boto3-secretsmanager = "^1.24.11" mypy-boto3-ssm = "^1.24.0" From 43bd38b0cff64b449942ef41cde1435fb1979646 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Jul 2022 07:08:11 +0000 Subject: [PATCH 30/30] chore(deps): bump constructs from 10.1.1 to 10.1.51 (#1323) --- layer/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/layer/requirements.txt b/layer/requirements.txt index ca8c53b1eaf..5fb9d0f54b8 100644 --- a/layer/requirements.txt +++ b/layer/requirements.txt @@ -27,9 +27,9 @@ cdk-lambda-powertools-python-layer==2.0.49 \ --hash=sha256:8055fc691539f16e22a40e3d3df9c3f59fb28012437b08c47c639aefb001f1b2 \ --hash=sha256:9b0a7b7344f9ccb486564af728cefeac743687bfb131631e6d9171a55800dbac # via -r requirements.txt -constructs==10.1.49 \ - --hash=sha256:3abba3e9e06f35f0a5e15c10e2e080f4f1fd449fe008fd650f2a5fcc6f729cc3 \ - --hash=sha256:89f0984b64bb987b428c3bfec51e2d5524b8605c9e2c2043491de9e3b007a3cf +constructs==10.1.51 \ + --hash=sha256:b4abc463c368d8c01806a361faaa0799dc45985b6a4c9c99569daf9bbc0a79c4 \ + --hash=sha256:e42ade042c836c347c563e93366c19462e6db3ed50f2db7d78a75812304d1ec5 # via # -r requirements.txt # aws-cdk-lib