diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 9e7272b032e..f5a364fda11 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -28,7 +28,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index c2b9ca78375..3ef8303b1e0 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -17,6 +17,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: 'Dependency Review'
uses: actions/dependency-review-action@0c155c5e8556a497adf53f2c18edabf945ed8e70 # v4.3.2
diff --git a/.github/workflows/label_pr_on_title.yml b/.github/workflows/label_pr_on_title.yml
index c5c57e6bee2..f70f8e6f53e 100644
--- a/.github/workflows/label_pr_on_title.yml
+++ b/.github/workflows/label_pr_on_title.yml
@@ -50,7 +50,7 @@ jobs:
pull-requests: write # label respective PR
steps:
- name: Checkout repository
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: "Label PR based on title"
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
diff --git a/.github/workflows/on_label_added.yml b/.github/workflows/on_label_added.yml
index c8d7007b1d4..149c7599ee2 100644
--- a/.github/workflows/on_label_added.yml
+++ b/.github/workflows/on_label_added.yml
@@ -47,7 +47,7 @@ jobs:
permissions:
pull-requests: write # comment on PR
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
# Maintenance: Persist state per PR as an artifact to avoid spam on label add
- name: "Suggest split large Pull Request"
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
diff --git a/.github/workflows/on_merged_pr.yml b/.github/workflows/on_merged_pr.yml
index 9745f4ee0f3..ee7b625c2f2 100644
--- a/.github/workflows/on_merged_pr.yml
+++ b/.github/workflows/on_merged_pr.yml
@@ -49,7 +49,7 @@ jobs:
issues: write # label issue with pending-release
if: needs.get_pr_details.outputs.prIsMerged == 'true'
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: "Label PR related issue for release"
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
diff --git a/.github/workflows/on_opened_pr.yml b/.github/workflows/on_opened_pr.yml
index 065d9a6baed..3989b1d5fe5 100644
--- a/.github/workflows/on_opened_pr.yml
+++ b/.github/workflows/on_opened_pr.yml
@@ -47,7 +47,7 @@ jobs:
needs: get_pr_details
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: "Ensure related issue is present"
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
@@ -66,7 +66,7 @@ jobs:
permissions:
pull-requests: write # label and comment on PR if missing acknowledge section (requirement)
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: "Ensure acknowledgement section is present"
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml
index c94e0fd38b4..4a61d09777a 100644
--- a/.github/workflows/ossf_scorecard.yml
+++ b/.github/workflows/ossf_scorecard.yml
@@ -22,12 +22,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
+ uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml
index acde1fa840f..2726b7514b0 100644
--- a/.github/workflows/publish_v2_layer.yml
+++ b/.github/workflows/publish_v2_layer.yml
@@ -88,7 +88,7 @@ jobs:
working-directory: ./layer
steps:
- name: checkout
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
@@ -247,7 +247,7 @@ jobs:
pages: none
steps:
- name: Checkout repository # reusable workflows start clean, so we need to checkout again
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml
index 8a197501aa9..5f8a213517e 100644
--- a/.github/workflows/quality_check.yml
+++ b/.github/workflows/quality_check.yml
@@ -52,7 +52,7 @@ jobs:
permissions:
contents: read # checkout code only
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Install poetry
run: pipx install poetry
- name: Set up Python ${{ matrix.python-version }}
@@ -73,7 +73,7 @@ jobs:
- name: Complexity baseline
run: make complexity-baseline
- name: Upload coverage to Codecov
- uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # 4.3.1
+ uses: codecov/codecov-action@6d798873df2b1b8e5846dba6fb86631229fbcb17 # 4.4.0
with:
file: ./coverage.xml
env_vars: PYTHON
diff --git a/.github/workflows/quality_check_pydanticv2.yml b/.github/workflows/quality_check_pydanticv2.yml
index 8b4fd72dda6..7b6414cb904 100644
--- a/.github/workflows/quality_check_pydanticv2.yml
+++ b/.github/workflows/quality_check_pydanticv2.yml
@@ -49,7 +49,7 @@ jobs:
permissions:
contents: read # checkout code only
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Install poetry
run: pipx install poetry
- name: Set up Python ${{ matrix.python-version }}
diff --git a/.github/workflows/record_pr.yml b/.github/workflows/record_pr.yml
index 038c51e9733..c79143b3b68 100644
--- a/.github/workflows/record_pr.yml
+++ b/.github/workflows/record_pr.yml
@@ -46,7 +46,7 @@ jobs:
permissions:
contents: read # NOTE: treat as untrusted location
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: "Extract PR details"
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 1fca9c67940..9ebe8be23ff 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -80,7 +80,7 @@ jobs:
RELEASE_VERSION="${RELEASE_TAG_VERSION:1}"
echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "$GITHUB_OUTPUT"
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
@@ -115,7 +115,7 @@ jobs:
contents: read
steps:
# NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev)
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
@@ -156,7 +156,7 @@ jobs:
attestation_hashes: ${{ steps.encoded_hash.outputs.attestation_hashes }}
steps:
# NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev)
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
@@ -225,7 +225,7 @@ jobs:
RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }}
steps:
# NOTE: we need actions/checkout in order to use our local actions (e.g., ./.github/actions)
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
@@ -259,7 +259,7 @@ jobs:
contents: write
steps:
# NOTE: we need actions/checkout to authenticate and configure git first
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
@@ -303,7 +303,7 @@ jobs:
runs-on: ubuntu-latest
steps:
# NOTE: we need actions/checkout to authenticate and configure git first
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
@@ -357,7 +357,7 @@ jobs:
env:
RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }}
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml
index 686ae608e70..adec36baa9d 100644
--- a/.github/workflows/reusable_deploy_v2_layer_stack.yml
+++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml
@@ -140,7 +140,7 @@ jobs:
has_arm64_support: "true"
steps:
- name: checkout
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
diff --git a/.github/workflows/reusable_deploy_v2_sar.yml b/.github/workflows/reusable_deploy_v2_sar.yml
index 519148abcc2..f45f51bc496 100644
--- a/.github/workflows/reusable_deploy_v2_sar.yml
+++ b/.github/workflows/reusable_deploy_v2_sar.yml
@@ -79,7 +79,7 @@ jobs:
architecture: ["x86_64", "arm64"]
steps:
- name: checkout
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
ref: ${{ env.RELEASE_COMMIT }}
diff --git a/.github/workflows/reusable_export_pr_details.yml b/.github/workflows/reusable_export_pr_details.yml
index 220f081593d..6cbb03b375d 100644
--- a/.github/workflows/reusable_export_pr_details.yml
+++ b/.github/workflows/reusable_export_pr_details.yml
@@ -76,7 +76,7 @@ jobs:
prLabels: ${{ steps.prLabels.outputs.prLabels }}
steps:
- name: Checkout repository # in case caller workflow doesn't checkout thus failing with file not found
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: "Download previously saved PR"
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
diff --git a/.github/workflows/reusable_publish_changelog.yml b/.github/workflows/reusable_publish_changelog.yml
index 422afd158fe..d63ca16c2a0 100644
--- a/.github/workflows/reusable_publish_changelog.yml
+++ b/.github/workflows/reusable_publish_changelog.yml
@@ -26,7 +26,7 @@ jobs:
pull-requests: write # create PR
steps:
- name: Checkout repository # reusable workflows start clean, so we need to checkout again
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
fetch-depth: 0
- name: "Generate latest changelog"
diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml
index e61ff2bfffd..1d39f2028b7 100644
--- a/.github/workflows/reusable_publish_docs.yml
+++ b/.github/workflows/reusable_publish_docs.yml
@@ -44,7 +44,7 @@ jobs:
id-token: write # trade JWT token for AWS credentials in AWS Docs account
pages: write # uncomment if mike fails as we migrated to S3 hosting
steps:
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
fetch-depth: 0
ref: ${{ inputs.git_ref }}
diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml
index 64308ba17db..99292411a42 100644
--- a/.github/workflows/run-e2e-tests.yml
+++ b/.github/workflows/run-e2e-tests.yml
@@ -52,7 +52,7 @@ jobs:
if: ${{ github.actor != 'dependabot[bot]' && github.repository == 'aws-powertools/powertools-lambda-python' }}
steps:
- name: "Checkout"
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Install poetry
run: pipx install poetry
- name: "Use Python"
diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml
index 99c59cff754..8810f082c75 100644
--- a/.github/workflows/secure_workflows.yml
+++ b/.github/workflows/secure_workflows.yml
@@ -30,9 +30,9 @@ jobs:
contents: read # checkout code and subsequently GitHub action workflows
steps:
- name: Checkout code
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Ensure 3rd party workflows have SHA pinned
- uses: zgosalvez/github-actions-ensure-sha-pinned-actions@19ebcb0babbd282ae1822a0b9c28f3f1f25cea45 # v3.0.4
+ uses: zgosalvez/github-actions-ensure-sha-pinned-actions@40e45e738b3cad2729f599d8afc6ed02184e1dbd # v3.0.5
with:
allowlist: |
slsa-framework/slsa-github-generator
diff --git a/.gitignore b/.gitignore
index 2a814459161..990f6517fe9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -314,4 +314,4 @@ examples/**/sam/.aws-sam
cdk.out
# NOTE: different accounts will be used for E2E thus creating unnecessary git clutter
-cdk.context.json
+cdk.context.json
\ No newline at end of file
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
index 4d571206e07..4529480ad19 100644
--- a/.markdownlint.yaml
+++ b/.markdownlint.yaml
@@ -73,8 +73,6 @@ MD013:
tables: false
# Include headings
headings: true
- # Include headings
- headers: true
# Strict length checking
strict: false
# Stern length checking
@@ -107,8 +105,6 @@ MD023: true
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
MD024:
- # Only check sibling headings
- allow_different_nesting: false
# Only check sibling headings
siblings_only: false
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4694093ac65..9d5c61200e7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@
## Bug Fixes
* **ci:** apply lessons learned to monthly roadmap reminder cross-repo ([#4078](https://github.com/aws-powertools/powertools-lambda-python/issues/4078))
+* **event-sources:** sane defaults for authorizer v1 and v2 ([#4298](https://github.com/aws-powertools/powertools-lambda-python/issues/4298))
+* **logger:** correctly pick powertools or custom handler in custom environments ([#4295](https://github.com/aws-powertools/powertools-lambda-python/issues/4295))
+* **parser:** make etag optional field on S3 notification events ([#4173](https://github.com/aws-powertools/powertools-lambda-python/issues/4173))
+* **typing:** resolved_headers_field is not Optional ([#4148](https://github.com/aws-powertools/powertools-lambda-python/issues/4148))
## Code Refactoring
@@ -15,61 +19,104 @@
## Documentation
* **general:** update documentation to add info about v3 ([#4234](https://github.com/aws-powertools/powertools-lambda-python/issues/4234))
+* **homepage:** add link to new and official workshop ([#4292](https://github.com/aws-powertools/powertools-lambda-python/issues/4292))
* **idempotency:** fix highlight and import path ([#4154](https://github.com/aws-powertools/powertools-lambda-python/issues/4154))
* **roadmap:** april updates ([#4181](https://github.com/aws-powertools/powertools-lambda-python/issues/4181))
+## Features
+
+* **event_handler:** add support for persisting authorization session in OpenAPI ([#4312](https://github.com/aws-powertools/powertools-lambda-python/issues/4312))
+* **event_handler:** add decorator for HTTP HEAD verb ([#4275](https://github.com/aws-powertools/powertools-lambda-python/issues/4275))
+
## Maintenance
* **ci:** add branch v3 to quality check and e2e actions ([#4232](https://github.com/aws-powertools/powertools-lambda-python/issues/4232))
-* **deps:** bump actions/dependency-review-action from 4.2.5 to 4.3.1 ([#4240](https://github.com/aws-powertools/powertools-lambda-python/issues/4240))
+* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#4302](https://github.com/aws-powertools/powertools-lambda-python/issues/4302))
+* **deps:** bump redis from 5.0.3 to 5.0.4 ([#4187](https://github.com/aws-powertools/powertools-lambda-python/issues/4187))
* **deps:** bump actions/download-artifact from 4.1.5 to 4.1.6 ([#4178](https://github.com/aws-powertools/powertools-lambda-python/issues/4178))
+* **deps:** bump zgosalvez/github-actions-ensure-sha-pinned-actions from 3.0.4 to 3.0.5 ([#4281](https://github.com/aws-powertools/powertools-lambda-python/issues/4281))
+* **deps:** bump actions/checkout from 4.1.4 to 4.1.5 ([#4282](https://github.com/aws-powertools/powertools-lambda-python/issues/4282))
+* **deps:** bump jinja2 from 3.1.3 to 3.1.4 in /docs ([#4284](https://github.com/aws-powertools/powertools-lambda-python/issues/4284))
+* **deps:** bump actions/download-artifact from 4.1.6 to 4.1.7 ([#4205](https://github.com/aws-powertools/powertools-lambda-python/issues/4205))
+* **deps:** bump actions/upload-artifact from 4.3.2 to 4.3.3 ([#4177](https://github.com/aws-powertools/powertools-lambda-python/issues/4177))
+* **deps:** bump squidfunk/mkdocs-material from `521644b` to `e309089` in /docs ([#4216](https://github.com/aws-powertools/powertools-lambda-python/issues/4216))
+* **deps:** bump ossf/scorecard-action from 2.3.1 to 2.3.3 ([#4315](https://github.com/aws-powertools/powertools-lambda-python/issues/4315))
+* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.27.12 to 1.27.13 in /layer/scripts/layer-balancer in the layer-balancer group ([#4319](https://github.com/aws-powertools/powertools-lambda-python/issues/4319))
+* **deps:** bump squidfunk/mkdocs-material from `98c9809` to `11d7ec0` in /docs ([#4269](https://github.com/aws-powertools/powertools-lambda-python/issues/4269))
* **deps:** bump actions/checkout from 4.1.2 to 4.1.3 ([#4168](https://github.com/aws-powertools/powertools-lambda-python/issues/4168))
-* **deps:** bump actions/dependency-review-action from 4.3.1 to 4.3.2 ([#4244](https://github.com/aws-powertools/powertools-lambda-python/issues/4244))
+* **deps:** bump datadog-lambda from 5.92.0 to 5.93.0 ([#4211](https://github.com/aws-powertools/powertools-lambda-python/issues/4211))
+* **deps:** bump squidfunk/mkdocs-material from `11d7ec0` to `8ef47d7` in /docs ([#4323](https://github.com/aws-powertools/powertools-lambda-python/issues/4323))
+* **deps:** bump actions/download-artifact from 4.1.4 to 4.1.5 ([#4161](https://github.com/aws-powertools/powertools-lambda-python/issues/4161))
* **deps:** bump squidfunk/mkdocs-material from `e309089` to `98c9809` in /docs ([#4236](https://github.com/aws-powertools/powertools-lambda-python/issues/4236))
+* **deps:** bump actions/dependency-review-action from 4.2.5 to 4.3.1 ([#4240](https://github.com/aws-powertools/powertools-lambda-python/issues/4240))
+* **deps:** bump actions/upload-artifact from 4.3.1 to 4.3.2 ([#4162](https://github.com/aws-powertools/powertools-lambda-python/issues/4162))
+* **deps:** bump actions/dependency-review-action from 4.3.1 to 4.3.2 ([#4244](https://github.com/aws-powertools/powertools-lambda-python/issues/4244))
+* **deps:** bump actions/checkout from 4.1.3 to 4.1.4 ([#4206](https://github.com/aws-powertools/powertools-lambda-python/issues/4206))
+* **deps:** bump slsa-framework/slsa-github-generator from 1.10.0 to 2.0.0 ([#4179](https://github.com/aws-powertools/powertools-lambda-python/issues/4179))
* **deps:** bump codecov/codecov-action from 4.3.0 to 4.3.1 ([#4252](https://github.com/aws-powertools/powertools-lambda-python/issues/4252))
* **deps:** bump datadog-lambda from 5.93.0 to 5.94.0 ([#4253](https://github.com/aws-powertools/powertools-lambda-python/issues/4253))
-* **deps:** bump redis from 5.0.3 to 5.0.4 ([#4187](https://github.com/aws-powertools/powertools-lambda-python/issues/4187))
-* **deps:** bump actions/download-artifact from 4.1.4 to 4.1.5 ([#4161](https://github.com/aws-powertools/powertools-lambda-python/issues/4161))
-* **deps:** bump actions/download-artifact from 4.1.6 to 4.1.7 ([#4205](https://github.com/aws-powertools/powertools-lambda-python/issues/4205))
-* **deps:** bump actions/checkout from 4.1.3 to 4.1.4 ([#4206](https://github.com/aws-powertools/powertools-lambda-python/issues/4206))
-* **deps:** bump actions/upload-artifact from 4.3.1 to 4.3.2 ([#4162](https://github.com/aws-powertools/powertools-lambda-python/issues/4162))
-* **deps:** bump datadog-lambda from 5.92.0 to 5.93.0 ([#4211](https://github.com/aws-powertools/powertools-lambda-python/issues/4211))
-* **deps:** bump actions/upload-artifact from 4.3.2 to 4.3.3 ([#4177](https://github.com/aws-powertools/powertools-lambda-python/issues/4177))
-* **deps:** bump squidfunk/mkdocs-material from `521644b` to `e309089` in /docs ([#4216](https://github.com/aws-powertools/powertools-lambda-python/issues/4216))
-* **deps-dev:** bump the boto-typing group with 2 updates ([#4210](https://github.com/aws-powertools/powertools-lambda-python/issues/4210))
+* **deps-dev:** bump aws-cdk from 2.139.0 to 2.139.1 ([#4245](https://github.com/aws-powertools/powertools-lambda-python/issues/4245))
+* **deps-dev:** bump mypy-boto3-dynamodb from 1.34.91 to 1.34.97 in the boto-typing group ([#4257](https://github.com/aws-powertools/powertools-lambda-python/issues/4257))
+* **deps-dev:** bump aws-cdk from 2.139.1 to 2.140.0 ([#4256](https://github.com/aws-powertools/powertools-lambda-python/issues/4256))
+* **deps-dev:** bump aws-cdk-lib from 2.139.0 to 2.139.1 ([#4248](https://github.com/aws-powertools/powertools-lambda-python/issues/4248))
+* **deps-dev:** bump cfn-lint from 0.86.4 to 0.87.0 ([#4249](https://github.com/aws-powertools/powertools-lambda-python/issues/4249))
+* **deps-dev:** bump pytest-xdist from 3.5.0 to 3.6.1 ([#4247](https://github.com/aws-powertools/powertools-lambda-python/issues/4247))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.133 to 0.1.134 ([#4260](https://github.com/aws-powertools/powertools-lambda-python/issues/4260))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.132 to 0.1.133 ([#4246](https://github.com/aws-powertools/powertools-lambda-python/issues/4246))
+* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.139.0a0 to 2.139.1a0 ([#4261](https://github.com/aws-powertools/powertools-lambda-python/issues/4261))
+* **deps-dev:** bump aws-cdk-lib from 2.139.1 to 2.140.0 ([#4259](https://github.com/aws-powertools/powertools-lambda-python/issues/4259))
+* **deps-dev:** bump mike from 1.1.2 to 2.1.0 ([#4258](https://github.com/aws-powertools/powertools-lambda-python/issues/4258))
+* **deps-dev:** bump filelock from 3.13.4 to 3.14.0 ([#4241](https://github.com/aws-powertools/powertools-lambda-python/issues/4241))
+* **deps-dev:** bump hvac from 2.1.0 to 2.2.0 ([#4238](https://github.com/aws-powertools/powertools-lambda-python/issues/4238))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.131 to 0.1.132 ([#4239](https://github.com/aws-powertools/powertools-lambda-python/issues/4239))
+* **deps-dev:** bump mkdocs-material from 9.5.19 to 9.5.20 ([#4242](https://github.com/aws-powertools/powertools-lambda-python/issues/4242))
+* **deps-dev:** bump mike from 2.1.0 to 2.1.1 ([#4268](https://github.com/aws-powertools/powertools-lambda-python/issues/4268))
+* **deps-dev:** bump pytest from 8.1.1 to 8.2.0 ([#4237](https://github.com/aws-powertools/powertools-lambda-python/issues/4237))
+* **deps-dev:** bump mkdocs-material from 9.5.20 to 9.5.21 ([#4271](https://github.com/aws-powertools/powertools-lambda-python/issues/4271))
+* **deps-dev:** bump cfn-lint from 0.87.0 to 0.87.1 ([#4272](https://github.com/aws-powertools/powertools-lambda-python/issues/4272))
+* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.139.1a0 to 2.140.0a0 ([#4270](https://github.com/aws-powertools/powertools-lambda-python/issues/4270))
+* **deps-dev:** bump sentry-sdk from 1.45.0 to 2.0.1 ([#4223](https://github.com/aws-powertools/powertools-lambda-python/issues/4223))
+* **deps-dev:** bump mkdocs-material from 9.5.18 to 9.5.19 ([#4224](https://github.com/aws-powertools/powertools-lambda-python/issues/4224))
+* **deps-dev:** bump black from 24.4.1 to 24.4.2 ([#4222](https://github.com/aws-powertools/powertools-lambda-python/issues/4222))
+* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.138.0a0 to 2.139.0a0 ([#4225](https://github.com/aws-powertools/powertools-lambda-python/issues/4225))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.130 to 0.1.131 ([#4221](https://github.com/aws-powertools/powertools-lambda-python/issues/4221))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.134 to 0.1.135 ([#4273](https://github.com/aws-powertools/powertools-lambda-python/issues/4273))
+* **deps-dev:** bump ruff from 0.4.1 to 0.4.2 ([#4212](https://github.com/aws-powertools/powertools-lambda-python/issues/4212))
+* **deps-dev:** bump aws-cdk-lib from 2.138.0 to 2.139.0 ([#4213](https://github.com/aws-powertools/powertools-lambda-python/issues/4213))
* **deps-dev:** bump aws-cdk from 2.138.0 to 2.139.0 ([#4215](https://github.com/aws-powertools/powertools-lambda-python/issues/4215))
+* **deps-dev:** bump coverage from 7.5.0 to 7.5.1 ([#4288](https://github.com/aws-powertools/powertools-lambda-python/issues/4288))
* **deps-dev:** bump types-redis from 4.6.0.20240423 to 4.6.0.20240425 ([#4214](https://github.com/aws-powertools/powertools-lambda-python/issues/4214))
-* **deps-dev:** bump aws-cdk-lib from 2.138.0 to 2.139.0 ([#4213](https://github.com/aws-powertools/powertools-lambda-python/issues/4213))
-* **deps-dev:** bump ruff from 0.4.1 to 0.4.2 ([#4212](https://github.com/aws-powertools/powertools-lambda-python/issues/4212))
+* **deps-dev:** bump sentry-sdk from 2.0.1 to 2.1.1 ([#4287](https://github.com/aws-powertools/powertools-lambda-python/issues/4287))
+* **deps-dev:** bump the boto-typing group with 2 updates ([#4210](https://github.com/aws-powertools/powertools-lambda-python/issues/4210))
* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.126 to 0.1.130 ([#4209](https://github.com/aws-powertools/powertools-lambda-python/issues/4209))
-* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.130 to 0.1.131 ([#4221](https://github.com/aws-powertools/powertools-lambda-python/issues/4221))
-* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.138.0a0 to 2.139.0a0 ([#4225](https://github.com/aws-powertools/powertools-lambda-python/issues/4225))
-* **deps-dev:** bump black from 24.4.1 to 24.4.2 ([#4222](https://github.com/aws-powertools/powertools-lambda-python/issues/4222))
+* **deps-dev:** bump ruff from 0.4.2 to 0.4.3 ([#4286](https://github.com/aws-powertools/powertools-lambda-python/issues/4286))
+* **deps-dev:** bump cfn-lint from 0.86.3 to 0.86.4 ([#4180](https://github.com/aws-powertools/powertools-lambda-python/issues/4180))
+* **deps-dev:** bump jinja2 from 3.1.3 to 3.1.4 ([#4283](https://github.com/aws-powertools/powertools-lambda-python/issues/4283))
* **deps-dev:** bump black from 24.4.0 to 24.4.1 ([#4203](https://github.com/aws-powertools/powertools-lambda-python/issues/4203))
* **deps-dev:** bump mypy from 1.9.0 to 1.10.0 ([#4202](https://github.com/aws-powertools/powertools-lambda-python/issues/4202))
* **deps-dev:** bump mypy-boto3-ssm from 1.34.61 to 1.34.91 in the boto-typing group ([#4201](https://github.com/aws-powertools/powertools-lambda-python/issues/4201))
* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.123 to 0.1.126 ([#4188](https://github.com/aws-powertools/powertools-lambda-python/issues/4188))
-* **deps-dev:** bump mkdocs-material from 9.5.18 to 9.5.19 ([#4224](https://github.com/aws-powertools/powertools-lambda-python/issues/4224))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.135 to 0.1.136 ([#4285](https://github.com/aws-powertools/powertools-lambda-python/issues/4285))
* **deps-dev:** bump coverage from 7.4.4 to 7.5.0 ([#4186](https://github.com/aws-powertools/powertools-lambda-python/issues/4186))
-* **deps-dev:** bump sentry-sdk from 1.45.0 to 2.0.1 ([#4223](https://github.com/aws-powertools/powertools-lambda-python/issues/4223))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.136 to 0.1.139 ([#4293](https://github.com/aws-powertools/powertools-lambda-python/issues/4293))
* **deps-dev:** bump types-redis from 4.6.0.20240417 to 4.6.0.20240423 ([#4185](https://github.com/aws-powertools/powertools-lambda-python/issues/4185))
-* **deps-dev:** bump pytest from 8.1.1 to 8.2.0 ([#4237](https://github.com/aws-powertools/powertools-lambda-python/issues/4237))
-* **deps-dev:** bump mkdocs-material from 9.5.19 to 9.5.20 ([#4242](https://github.com/aws-powertools/powertools-lambda-python/issues/4242))
-* **deps-dev:** bump ruff from 0.3.7 to 0.4.1 ([#4166](https://github.com/aws-powertools/powertools-lambda-python/issues/4166))
-* **deps-dev:** bump cfn-lint from 0.86.3 to 0.86.4 ([#4180](https://github.com/aws-powertools/powertools-lambda-python/issues/4180))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.139 to 0.1.140 ([#4301](https://github.com/aws-powertools/powertools-lambda-python/issues/4301))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.140 to 0.1.142 ([#4307](https://github.com/aws-powertools/powertools-lambda-python/issues/4307))
+* **deps-dev:** bump aws-cdk from 2.140.0 to 2.141.0 ([#4306](https://github.com/aws-powertools/powertools-lambda-python/issues/4306))
+* **deps-dev:** bump ruff from 0.4.3 to 0.4.4 ([#4309](https://github.com/aws-powertools/powertools-lambda-python/issues/4309))
* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.121 to 0.1.123 ([#4176](https://github.com/aws-powertools/powertools-lambda-python/issues/4176))
-* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.131 to 0.1.132 ([#4239](https://github.com/aws-powertools/powertools-lambda-python/issues/4239))
+* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.140.0a0 to 2.141.0a0 ([#4318](https://github.com/aws-powertools/powertools-lambda-python/issues/4318))
* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.137.0a0 to 2.138.0a0 ([#4169](https://github.com/aws-powertools/powertools-lambda-python/issues/4169))
-* **deps-dev:** bump hvac from 2.1.0 to 2.2.0 ([#4238](https://github.com/aws-powertools/powertools-lambda-python/issues/4238))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.142 to 0.1.144 ([#4316](https://github.com/aws-powertools/powertools-lambda-python/issues/4316))
* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.119 to 0.1.121 ([#4167](https://github.com/aws-powertools/powertools-lambda-python/issues/4167))
-* **deps-dev:** bump filelock from 3.13.4 to 3.14.0 ([#4241](https://github.com/aws-powertools/powertools-lambda-python/issues/4241))
-* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.132 to 0.1.133 ([#4246](https://github.com/aws-powertools/powertools-lambda-python/issues/4246))
+* **deps-dev:** bump ruff from 0.3.7 to 0.4.1 ([#4166](https://github.com/aws-powertools/powertools-lambda-python/issues/4166))
+* **deps-dev:** bump cfn-lint from 0.87.1 to 0.87.2 ([#4317](https://github.com/aws-powertools/powertools-lambda-python/issues/4317))
* **deps-dev:** bump aws-cdk from 2.137.0 to 2.138.0 ([#4157](https://github.com/aws-powertools/powertools-lambda-python/issues/4157))
* **deps-dev:** bump aws-cdk-lib from 2.137.0 to 2.138.0 ([#4160](https://github.com/aws-powertools/powertools-lambda-python/issues/4160))
-* **deps-dev:** bump pytest-xdist from 3.5.0 to 3.6.1 ([#4247](https://github.com/aws-powertools/powertools-lambda-python/issues/4247))
-* **deps-dev:** bump cfn-lint from 0.86.4 to 0.87.0 ([#4249](https://github.com/aws-powertools/powertools-lambda-python/issues/4249))
-* **deps-dev:** bump aws-cdk-lib from 2.139.0 to 2.139.1 ([#4248](https://github.com/aws-powertools/powertools-lambda-python/issues/4248))
-* **deps-dev:** bump aws-cdk from 2.139.0 to 2.139.1 ([#4245](https://github.com/aws-powertools/powertools-lambda-python/issues/4245))
+* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.144 to 0.1.145 ([#4325](https://github.com/aws-powertools/powertools-lambda-python/issues/4325))
+* **deps-dev:** bump mkdocs-material from 9.5.21 to 9.5.22 ([#4324](https://github.com/aws-powertools/powertools-lambda-python/issues/4324))
+* **deps-dev:** bump aws-cdk-lib from 2.140.0 to 2.141.0 ([#4308](https://github.com/aws-powertools/powertools-lambda-python/issues/4308))
+* **governance:** add FastAPI third party license attribution ([#4297](https://github.com/aws-powertools/powertools-lambda-python/issues/4297))
diff --git a/THIRD-PARTY-LICENSES b/THIRD-PARTY-LICENSES
index 3712eac88cf..f6d647c54a7 100644
--- a/THIRD-PARTY-LICENSES
+++ b/THIRD-PARTY-LICENSES
@@ -1,3 +1,27 @@
+** FastAPI - https://github.com/tiangolo/fastapi/ - Used in the OpenAPI feature
+
+ The MIT License (MIT)
+
+ Copyright (c) 2018 Sebastián RamÃrez
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
** Tensorflow - https://github.com/tensorflow/tensorflow/
Apache License
diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py
index cba008d455f..35915c02004 100644
--- a/aws_lambda_powertools/event_handler/api_gateway.py
+++ b/aws_lambda_powertools/event_handler/api_gateway.py
@@ -1224,6 +1224,63 @@ def lambda_handler(event, context):
middlewares,
)
+ def head(
+ self,
+ rule: str,
+ cors: Optional[bool] = None,
+ compress: bool = False,
+ cache_control: Optional[str] = None,
+ summary: Optional[str] = None,
+ description: Optional[str] = None,
+ responses: Optional[Dict[int, OpenAPIResponse]] = None,
+ response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION,
+ tags: Optional[List[str]] = None,
+ operation_id: Optional[str] = None,
+ include_in_schema: bool = True,
+ security: Optional[List[Dict[str, List[str]]]] = None,
+ middlewares: Optional[List[Callable]] = None,
+ ):
+ """Head route decorator with HEAD `method`
+
+ Examples
+ --------
+ Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator
+
+ ```python
+ from aws_lambda_powertools import Tracer
+ from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response, content_types
+
+ tracer = Tracer()
+ app = APIGatewayRestResolver()
+
+ @app.head("/head-call")
+ def simple_head():
+ return Response(status_code=200,
+ content_type=content_types.APPLICATION_JSON,
+ headers={"Content-Length": "123"})
+
+ @tracer.capture_lambda_handler
+ def lambda_handler(event, context):
+ return app.resolve(event, context)
+ ```
+ """
+ return self.route(
+ rule,
+ "HEAD",
+ cors,
+ compress,
+ cache_control,
+ summary,
+ description,
+ responses,
+ response_description,
+ tags,
+ operation_id,
+ include_in_schema,
+ security,
+ middlewares,
+ )
+
def _push_processed_stack_frame(self, frame: str):
"""
Add Current Middleware to the Middleware Stack Frames
@@ -1596,7 +1653,6 @@ def _determine_openapi_version(openapi_version: str):
stacklevel=2,
)
openapi_version = "3.1.0"
-
return openapi_version
def get_openapi_json_schema(
@@ -1692,6 +1748,7 @@ def enable_swagger(
security_schemes: Optional[Dict[str, "SecurityScheme"]] = None,
security: Optional[List[Dict[str, List[str]]]] = None,
oauth2_config: Optional["OAuth2Config"] = None,
+ persist_authorization: bool = False,
):
"""
Returns the OpenAPI schema as a JSON serializable dict
@@ -1732,6 +1789,8 @@ def enable_swagger(
A declaration of which security mechanisms are applied globally across the API.
oauth2_config: OAuth2Config, optional
The OAuth2 configuration for the Swagger UI.
+ persist_authorization: bool, optional
+ Whether to persist authorization data on browser close/refresh.
"""
from aws_lambda_powertools.event_handler.openapi.compat import model_json
from aws_lambda_powertools.event_handler.openapi.models import Server
@@ -1810,6 +1869,7 @@ def swagger_handler():
swagger_css,
swagger_base_url,
oauth2_config,
+ persist_authorization,
)
return Response(
@@ -2131,7 +2191,7 @@ def not_found(self, func: Optional[Callable] = None):
def exception_handler(self, exc_class: Union[Type[Exception], List[Type[Exception]]]):
def register_exception_handler(func: Callable):
- if isinstance(exc_class, list):
+ if isinstance(exc_class, list): # pragma: no cover
for exp in exc_class:
self._exception_handlers[exp] = func
else:
diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py
index a57560a3ad1..2eafb0d67bb 100644
--- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py
+++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py
@@ -410,7 +410,7 @@ def _normalize_multi_query_string_with_param(
return resolved_query_string
-def _normalize_multi_header_values_with_param(headers: Optional[Dict[str, str]], params: Sequence[ModelField]):
+def _normalize_multi_header_values_with_param(headers: Dict[str, Any], params: Sequence[ModelField]):
"""
Extract and normalize resolved_headers_field
diff --git a/aws_lambda_powertools/event_handler/openapi/pydantic_loader.py b/aws_lambda_powertools/event_handler/openapi/pydantic_loader.py
new file mode 100644
index 00000000000..225f7e88096
--- /dev/null
+++ b/aws_lambda_powertools/event_handler/openapi/pydantic_loader.py
@@ -0,0 +1,6 @@
+try:
+ from pydantic.version import VERSION as PYDANTIC_VERSION
+
+ PYDANTIC_V2 = PYDANTIC_VERSION.startswith("2.")
+except ImportError:
+ PYDANTIC_V2 = False # pragma: no cover # false positive; dropping in v3
diff --git a/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py b/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py
index 8b748d9338a..85e041f2f56 100644
--- a/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py
+++ b/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py
@@ -10,6 +10,7 @@ def generate_swagger_html(
swagger_css: str,
swagger_base_url: str,
oauth2_config: Optional[OAuth2Config],
+ persist_authorization: bool = False,
) -> str:
"""
Generate Swagger UI HTML page
@@ -28,6 +29,8 @@ def generate_swagger_html(
The base URL for Swagger UI
oauth2_config: OAuth2Config, optional
The OAuth2 configuration.
+ persist_authorization: bool, optional
+ Whether to persist authorization data on browser close/refresh.
"""
# If Swagger base URL is present, generate HTML content with linked CSS and JavaScript files
@@ -86,6 +89,7 @@ def generate_swagger_html(
SwaggerUIBundle.plugins.DownloadUrl
],
withCredentials: true,
+ persistAuthorization: {str(persist_authorization).lower()},
oauth2RedirectUrl: baseUrl + "?format=oauth2-redirect",
}}
diff --git a/aws_lambda_powertools/logging/constants.py b/aws_lambda_powertools/logging/constants.py
new file mode 100644
index 00000000000..c98204f9bb1
--- /dev/null
+++ b/aws_lambda_powertools/logging/constants.py
@@ -0,0 +1,5 @@
+# logger.powertools_handler is set with Powertools Logger handler; useful when there are many handlers
+LOGGER_ATTRIBUTE_POWERTOOLS_HANDLER = "powertools_handler"
+# logger.init attribute is set when Logger has been configured
+LOGGER_ATTRIBUTE_PRECONFIGURED = "init"
+LOGGER_ATTRIBUTE_HANDLER = "logger_handler"
diff --git a/aws_lambda_powertools/logging/exceptions.py b/aws_lambda_powertools/logging/exceptions.py
index 65b30906edf..db2fb0f04ba 100644
--- a/aws_lambda_powertools/logging/exceptions.py
+++ b/aws_lambda_powertools/logging/exceptions.py
@@ -1,2 +1,6 @@
class InvalidLoggerSamplingRateError(Exception):
pass
+
+
+class OrphanedChildLoggerError(Exception):
+ pass
diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py
index dc03e1af8eb..5eadfecc6fa 100644
--- a/aws_lambda_powertools/logging/logger.py
+++ b/aws_lambda_powertools/logging/logger.py
@@ -19,9 +19,15 @@
Optional,
TypeVar,
Union,
+ cast,
overload,
)
+from aws_lambda_powertools.logging.constants import (
+ LOGGER_ATTRIBUTE_HANDLER,
+ LOGGER_ATTRIBUTE_POWERTOOLS_HANDLER,
+ LOGGER_ATTRIBUTE_PRECONFIGURED,
+)
from aws_lambda_powertools.shared import constants
from aws_lambda_powertools.shared.functions import (
extract_event_from_common_models,
@@ -31,7 +37,7 @@
from aws_lambda_powertools.utilities import jmespath_utils
from ..shared.types import AnyCallableT
-from .exceptions import InvalidLoggerSamplingRateError
+from .exceptions import InvalidLoggerSamplingRateError, OrphanedChildLoggerError
from .filters import SuppressFilter
from .formatter import (
RESERVED_FORMATTER_CUSTOM_KEYS,
@@ -233,7 +239,6 @@ def __init__(
self.child = child
self.logger_formatter = logger_formatter
self._stream = stream or sys.stdout
- self.logger_handler = logger_handler or logging.StreamHandler(self._stream)
self.log_uncaught_exceptions = log_uncaught_exceptions
self._is_deduplication_disabled = resolve_truthy_env_var_choice(
@@ -241,6 +246,7 @@ def __init__(
)
self._default_log_keys = {"service": self.service, "sampling_rate": self.sampling_rate}
self._logger = self._get_logger()
+ self.logger_handler = logger_handler or self._get_handler()
# NOTE: This is primarily to improve UX, so IDEs can autocomplete LambdaPowertoolsFormatter options
# previously, we masked all of them as kwargs thus limiting feature discovery
@@ -264,7 +270,7 @@ def __init__(
# Prevent __getattr__ from shielding unknown attribute errors in type checkers
# https://github.com/aws-powertools/powertools-lambda-python/issues/1660
- if not TYPE_CHECKING:
+ if not TYPE_CHECKING: # pragma: no cover
def __getattr__(self, name):
# Proxy attributes not found to actual logger to support backward compatibility
@@ -279,6 +285,18 @@ def _get_logger(self) -> logging.Logger:
return logging.getLogger(logger_name)
+ def _get_handler(self) -> logging.Handler:
+ # is a logger handler already configured?
+ if getattr(self, LOGGER_ATTRIBUTE_HANDLER, None):
+ return self.logger_handler
+
+ # for children, use parent's handler
+ if self.child:
+ return getattr(self._logger.parent, LOGGER_ATTRIBUTE_POWERTOOLS_HANDLER, None) # type: ignore[return-value] # always checked in formatting
+
+ # otherwise, create a new stream handler (first time init)
+ return logging.StreamHandler(self._stream)
+
def _init_logger(
self,
formatter_options: Optional[Dict] = None,
@@ -292,7 +310,7 @@ def _init_logger(
# a) multiple handlers being attached
# b) different sampling mechanisms
# c) multiple messages from being logged as handlers can be duplicated
- is_logger_preconfigured = getattr(self._logger, "init", False)
+ is_logger_preconfigured = getattr(self._logger, LOGGER_ATTRIBUTE_PRECONFIGURED, False)
if self.child or is_logger_preconfigured:
return
@@ -317,6 +335,7 @@ def _init_logger(
# std logging will return the same Logger with our attribute if name is reused
logger.debug(f"Marking logger {self.service} as preconfigured")
self._logger.init = True # type: ignore[attr-defined]
+ self._logger.powertools_handler = self.logger_handler # type: ignore[attr-defined]
def _configure_sampling(self) -> None:
"""Dynamically set log level based on sampling rate
@@ -613,7 +632,7 @@ def structure_logs(self, append: bool = False, formatter_options: Optional[Dict]
# Mode 1
log_keys = {**self._default_log_keys, **keys}
- is_logger_preconfigured = getattr(self._logger, "init", False)
+ is_logger_preconfigured = getattr(self._logger, LOGGER_ATTRIBUTE_PRECONFIGURED, False)
if not is_logger_preconfigured:
formatter = self.logger_formatter or LambdaPowertoolsFormatter(**formatter_options, **log_keys)
self.registered_handler.setFormatter(formatter)
@@ -672,15 +691,20 @@ def removeFilter(self, filter: logging._FilterType) -> None: # noqa: A002 # fil
@property
def registered_handler(self) -> logging.Handler:
"""Convenience property to access the first logger handler"""
- # We ignore mypy here because self.child encodes whether or not self._logger.parent is
- # None, mypy can't see this from context but we can
- handlers = self._logger.parent.handlers if self.child else self._logger.handlers # type: ignore[union-attr]
- return handlers[0]
+ return self._get_handler()
@property
def registered_formatter(self) -> BasePowertoolsFormatter:
"""Convenience property to access the first logger formatter"""
- return self.registered_handler.formatter # type: ignore[return-value]
+ handler = self.registered_handler
+ if handler is None:
+ raise OrphanedChildLoggerError(
+ "Orphan child loggers cannot append nor remove keys until a parent is initialized first. "
+ "To solve this issue, you can A) make sure a parent logger is initialized first, or B) move append/remove keys operations to a later stage." # noqa: E501
+ "Reference: https://docs.powertools.aws.dev/lambda/python/latest/core/logger/#reusing-logger-across-your-code",
+ )
+
+ return cast(BasePowertoolsFormatter, handler.formatter)
@property
def log_level(self) -> int:
diff --git a/aws_lambda_powertools/shared/constants.py b/aws_lambda_powertools/shared/constants.py
index bb8164d1d37..9652e09a0b2 100644
--- a/aws_lambda_powertools/shared/constants.py
+++ b/aws_lambda_powertools/shared/constants.py
@@ -9,6 +9,7 @@
INVALID_XRAY_NAME_CHARACTERS = r"[?;*()!$~^<>]"
# Logger constants
+# maintenance: future major version should start having localized `constants.py` to ease future modularization
LOGGER_LOG_SAMPLING_RATE: str = "POWERTOOLS_LOGGER_SAMPLE_RATE"
LOGGER_LOG_EVENT_ENV: str = "POWERTOOLS_LOGGER_LOG_EVENT"
LOGGER_LOG_DEDUPLICATION_ENV: str = "POWERTOOLS_LOG_DEDUPLICATION_DISABLED"
@@ -61,7 +62,7 @@
# JSON constants
PRETTY_INDENT: int = 4
-COMPACT_INDENT = None
+COMPACT_INDENT: None = None
# Idempotency constants
IDEMPOTENCY_DISABLED_ENV: str = "POWERTOOLS_IDEMPOTENCY_DISABLED"
diff --git a/aws_lambda_powertools/utilities/batch/types.py b/aws_lambda_powertools/utilities/batch/types.py
index 40083537e04..d48f768a6b8 100644
--- a/aws_lambda_powertools/utilities/batch/types.py
+++ b/aws_lambda_powertools/utilities/batch/types.py
@@ -7,7 +7,7 @@
# For IntelliSense and Mypy to work, we need to account for possible SQS subclasses
# We need them as subclasses as we must access their message ID or sequence number metadata via dot notation
-if has_pydantic:
+if has_pydantic: # pragma: no cover
from aws_lambda_powertools.utilities.parser.models import DynamoDBStreamRecordModel, SqsRecordModel
from aws_lambda_powertools.utilities.parser.models import (
KinesisDataStreamRecord as KinesisDataStreamRecordModel,
@@ -17,7 +17,7 @@
Union[Type[SqsRecordModel], Type[DynamoDBStreamRecordModel], Type[KinesisDataStreamRecordModel]]
]
BatchSqsTypeModel = Optional[Type[SqsRecordModel]]
-else:
+else: # pragma: no cover
BatchTypeModels = "BatchTypeModels" # type: ignore
BatchSqsTypeModel = "BatchSqsTypeModel" # type: ignore
diff --git a/aws_lambda_powertools/utilities/data_classes/alb_event.py b/aws_lambda_powertools/utilities/data_classes/alb_event.py
index a1ee3424a94..a3fbb24f270 100644
--- a/aws_lambda_powertools/utilities/data_classes/alb_event.py
+++ b/aws_lambda_powertools/utilities/data_classes/alb_event.py
@@ -43,7 +43,7 @@ def resolved_query_string_parameters(self) -> Dict[str, List[str]]:
return super().resolved_query_string_parameters
@property
- def resolved_headers_field(self) -> Optional[Dict[str, Any]]:
+ def resolved_headers_field(self) -> Dict[str, Any]:
headers: Dict[str, Any] = {}
if self.multi_value_headers:
diff --git a/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py b/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py
index b8ef9c08045..48d3c96c84c 100644
--- a/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py
+++ b/aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py
@@ -15,18 +15,18 @@
class APIGatewayEventAuthorizer(DictWrapper):
@property
- def claims(self) -> Optional[Dict[str, Any]]:
- return self.get("claims")
+ def claims(self) -> Dict[str, Any]:
+ return self.get("claims") or {} # key might exist but can be `null`
@property
- def scopes(self) -> Optional[List[str]]:
- return self.get("scopes")
+ def scopes(self) -> List[str]:
+ return self.get("scopes") or [] # key might exist but can be `null`
@property
- def principal_id(self) -> Optional[str]:
+ def principal_id(self) -> str:
"""The principal user identification associated with the token sent by the client and returned from an
API Gateway Lambda authorizer (formerly known as a custom authorizer)"""
- return self.get("principalId")
+ return self.get("principalId") or "" # key might exist but can be `null`
@property
def integration_latency(self) -> Optional[int]:
@@ -91,7 +91,8 @@ def route_key(self) -> Optional[str]:
@property
def authorizer(self) -> APIGatewayEventAuthorizer:
- return APIGatewayEventAuthorizer(self._data["requestContext"]["authorizer"])
+ authz_data = self._data.get("requestContext", {}).get("authorizer", {})
+ return APIGatewayEventAuthorizer(authz_data)
class APIGatewayProxyEvent(BaseProxyEvent):
@@ -112,11 +113,11 @@ def resource(self) -> str:
@property
def multi_value_headers(self) -> Dict[str, List[str]]:
- return self.get("multiValueHeaders") or {}
+ return self.get("multiValueHeaders") or {} # key might exist but can be `null`
@property
def multi_value_query_string_parameters(self) -> Dict[str, List[str]]:
- return self.get("multiValueQueryStringParameters") or {}
+ return self.get("multiValueQueryStringParameters") or {} # key might exist but can be `null`
@property
def resolved_query_string_parameters(self) -> Dict[str, List[str]]:
@@ -126,7 +127,7 @@ def resolved_query_string_parameters(self) -> Dict[str, List[str]]:
return super().resolved_query_string_parameters
@property
- def resolved_headers_field(self) -> Optional[Dict[str, Any]]:
+ def resolved_headers_field(self) -> Dict[str, Any]:
headers: Dict[str, Any] = {}
if self.multi_value_headers:
@@ -154,72 +155,72 @@ def header_serializer(self) -> BaseHeadersSerializer:
class RequestContextV2AuthorizerIam(DictWrapper):
@property
- def access_key(self) -> Optional[str]:
+ def access_key(self) -> str:
"""The IAM user access key associated with the request."""
- return self.get("accessKey")
+ return self.get("accessKey") or "" # key might exist but can be `null`
@property
- def account_id(self) -> Optional[str]:
+ def account_id(self) -> str:
"""The AWS account ID associated with the request."""
- return self.get("accountId")
+ return self.get("accountId") or "" # key might exist but can be `null`
@property
- def caller_id(self) -> Optional[str]:
+ def caller_id(self) -> str:
"""The principal identifier of the caller making the request."""
- return self.get("callerId")
+ return self.get("callerId") or "" # key might exist but can be `null`
def _cognito_identity(self) -> Dict:
- return self.get("cognitoIdentity", {}) or {} # not available in FunctionURL
+ return self.get("cognitoIdentity") or {} # not available in FunctionURL; key might exist but can be `null`
@property
- def cognito_amr(self) -> Optional[List[str]]:
+ def cognito_amr(self) -> List[str]:
"""This represents how the user was authenticated.
AMR stands for Authentication Methods References as per the openid spec"""
- return self._cognito_identity().get("amr")
+ return self._cognito_identity().get("amr", [])
@property
- def cognito_identity_id(self) -> Optional[str]:
+ def cognito_identity_id(self) -> str:
"""The Amazon Cognito identity ID of the caller making the request.
Available only if the request was signed with Amazon Cognito credentials."""
- return self._cognito_identity().get("identityId")
+ return self._cognito_identity().get("identityId", "")
@property
- def cognito_identity_pool_id(self) -> Optional[str]:
+ def cognito_identity_pool_id(self) -> str:
"""The Amazon Cognito identity pool ID of the caller making the request.
Available only if the request was signed with Amazon Cognito credentials."""
- return self._cognito_identity().get("identityPoolId")
+ return self._cognito_identity().get("identityPoolId") or "" # key might exist but can be `null`
@property
- def principal_org_id(self) -> Optional[str]:
+ def principal_org_id(self) -> str:
"""The AWS organization ID."""
- return self.get("principalOrgId")
+ return self.get("principalOrgId") or "" # key might exist but can be `null`
@property
- def user_arn(self) -> Optional[str]:
+ def user_arn(self) -> str:
"""The Amazon Resource Name (ARN) of the effective user identified after authentication."""
- return self.get("userArn")
+ return self.get("userArn") or "" # key might exist but can be `null`
@property
- def user_id(self) -> Optional[str]:
+ def user_id(self) -> str:
"""The IAM user ID of the effective user identified after authentication."""
- return self.get("userId")
+ return self.get("userId") or "" # key might exist but can be `null`
class RequestContextV2Authorizer(DictWrapper):
@property
- def jwt_claim(self) -> Optional[Dict[str, Any]]:
- jwt = self.get("jwt") or {} # not available in FunctionURL
- return jwt.get("claims")
+ def jwt_claim(self) -> Dict[str, Any]:
+ jwt = self.get("jwt") or {} # not available in FunctionURL; key might exist but can be `null`
+ return jwt.get("claims") or {} # key might exist but can be `null`
@property
- def jwt_scopes(self) -> Optional[List[str]]:
- jwt = self.get("jwt") or {} # not available in FunctionURL
- return jwt.get("scopes")
+ def jwt_scopes(self) -> List[str]:
+ jwt = self.get("jwt") or {} # not available in FunctionURL; key might exist but can be `null`
+ return jwt.get("scopes", [])
@property
- def get_lambda(self) -> Optional[Dict[str, Any]]:
+ def get_lambda(self) -> Dict[str, Any]:
"""Lambda authorization context details"""
- return self.get("lambda")
+ return self.get("lambda") or {} # key might exist but can be `null`
def get_context(self) -> Dict[str, Any]:
"""Retrieve the authorization context details injected by a Lambda Authorizer.
@@ -238,20 +239,20 @@ def get_context(self) -> Dict[str, Any]:
Dict[str, Any]
A dictionary containing Lambda authorization context details.
"""
- return self.get("lambda", {}) or {}
+ return self.get_lambda
@property
- def iam(self) -> Optional[RequestContextV2AuthorizerIam]:
+ def iam(self) -> RequestContextV2AuthorizerIam:
"""IAM authorization details used for making the request."""
- iam = self.get("iam")
- return None if iam is None else RequestContextV2AuthorizerIam(iam)
+ iam = self.get("iam") or {} # key might exist but can be `null`
+ return RequestContextV2AuthorizerIam(iam)
class RequestContextV2(BaseRequestContextV2):
@property
- def authorizer(self) -> Optional[RequestContextV2Authorizer]:
- authorizer = self["requestContext"].get("authorizer")
- return None if authorizer is None else RequestContextV2Authorizer(authorizer)
+ def authorizer(self) -> RequestContextV2Authorizer:
+ ctx = self.get("requestContext") or {} # key might exist but can be `null`
+ return RequestContextV2Authorizer(ctx.get("authorizer", {}))
class APIGatewayProxyEventV2(BaseProxyEvent):
@@ -319,7 +320,7 @@ def header_serializer(self):
return HttpApiHeadersSerializer()
@property
- def resolved_headers_field(self) -> Optional[Dict[str, Any]]:
+ def resolved_headers_field(self) -> Dict[str, Any]:
if self.headers is not None:
headers = {key.lower(): value.split(",") if "," in value else value for key, value in self.headers.items()}
return headers
diff --git a/aws_lambda_powertools/utilities/data_classes/bedrock_agent_event.py b/aws_lambda_powertools/utilities/data_classes/bedrock_agent_event.py
index 45f3cd81f1f..4c404c73111 100644
--- a/aws_lambda_powertools/utilities/data_classes/bedrock_agent_event.py
+++ b/aws_lambda_powertools/utilities/data_classes/bedrock_agent_event.py
@@ -111,7 +111,7 @@ def query_string_parameters(self) -> Optional[Dict[str, str]]:
return {x["name"]: x["value"] for x in self["parameters"]} if self.get("parameters") else None
@property
- def resolved_headers_field(self) -> Optional[Dict[str, Any]]:
+ def resolved_headers_field(self) -> Dict[str, Any]:
return {}
@cached_property
diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py
index b78a6e4939c..76726ca5129 100644
--- a/aws_lambda_powertools/utilities/data_classes/common.py
+++ b/aws_lambda_powertools/utilities/data_classes/common.py
@@ -124,7 +124,7 @@ def resolved_query_string_parameters(self) -> Dict[str, List[str]]:
return {}
@property
- def resolved_headers_field(self) -> Optional[Dict[str, Any]]:
+ def resolved_headers_field(self) -> Dict[str, Any]:
"""
This property determines the appropriate header to be used
as a trusted source for validating OpenAPI.
diff --git a/aws_lambda_powertools/utilities/data_classes/s3_event.py b/aws_lambda_powertools/utilities/data_classes/s3_event.py
index 802f1663edb..1a6f9c541a3 100644
--- a/aws_lambda_powertools/utilities/data_classes/s3_event.py
+++ b/aws_lambda_powertools/utilities/data_classes/s3_event.py
@@ -32,14 +32,14 @@ def key(self) -> str:
return unquote_plus(self["key"])
@property
- def size(self) -> str:
- """Object size"""
- return self["size"]
+ def size(self) -> Optional[int]:
+ """Object size. Object deletion event doesn't contain size."""
+ return self.get("size")
@property
def etag(self) -> str:
- """Object etag"""
- return self["etag"]
+ """Object etag. Object deletion event doesn't contain etag; we default to empty string"""
+ return self.get("etag", "") # type: ignore[return-value] # false positive
@property
def version_id(self) -> str:
@@ -178,8 +178,8 @@ def size(self) -> int:
@property
def etag(self) -> str:
- """object eTag"""
- return self["s3"]["object"]["eTag"]
+ """Object eTag. Object deletion event doesn't contain eTag; we default to empty string"""
+ return self["s3"]["object"].get("eTag", "")
@property
def version_id(self) -> Optional[str]:
diff --git a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py
index 3fe9762fcd7..c28977c56ba 100644
--- a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py
+++ b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py
@@ -145,7 +145,7 @@ def query_string_parameters(self) -> Dict[str, str]:
return self["query_string_parameters"]
@property
- def resolved_headers_field(self) -> Optional[Dict[str, Any]]:
+ def resolved_headers_field(self) -> Dict[str, Any]:
if self.headers is not None:
headers = {key.lower(): value.split(",") if "," in value else value for key, value in self.headers.items()}
return headers
@@ -272,7 +272,7 @@ def query_string_parameters(self) -> Optional[Dict[str, str]]:
return None
@property
- def resolved_headers_field(self) -> Optional[Dict[str, str]]:
+ def resolved_headers_field(self) -> Dict[str, str]:
if self.headers is not None:
return {key.lower(): value for key, value in self.headers.items()}
diff --git a/aws_lambda_powertools/utilities/data_masking/__init__.py b/aws_lambda_powertools/utilities/data_masking/__init__.py
index 4d767e83ce1..428cea6635d 100644
--- a/aws_lambda_powertools/utilities/data_masking/__init__.py
+++ b/aws_lambda_powertools/utilities/data_masking/__init__.py
@@ -1,9 +1,3 @@
-"""
- Note: This utility is currently in a Non-General Availability (Non-GA) phase and may have limitations.
- Please DON'T USE THIS utility in production environments.
- Keep in mind that when we transition to General Availability (GA), there might be breaking changes introduced.
-"""
-
from aws_lambda_powertools.utilities.data_masking.base import DataMasking
__all__ = [
diff --git a/aws_lambda_powertools/utilities/data_masking/base.py b/aws_lambda_powertools/utilities/data_masking/base.py
index 5274aac3b8a..bf5842a70fb 100644
--- a/aws_lambda_powertools/utilities/data_masking/base.py
+++ b/aws_lambda_powertools/utilities/data_masking/base.py
@@ -19,10 +19,6 @@
class DataMasking:
"""
- Note: This utility is currently in a Non-General Availability (Non-GA) phase and may have limitations.
- Please DON'T USE THIS utility in production environments.
- Keep in mind that when we transition to General Availability (GA), there might be breaking changes introduced.
-
The DataMasking class orchestrates erasing, encrypting, and decrypting
for the base provider.
diff --git a/aws_lambda_powertools/utilities/parser/compat.py b/aws_lambda_powertools/utilities/parser/compat.py
new file mode 100644
index 00000000000..c76bc6546a5
--- /dev/null
+++ b/aws_lambda_powertools/utilities/parser/compat.py
@@ -0,0 +1,34 @@
+import functools
+
+
+@functools.lru_cache(maxsize=None)
+def disable_pydantic_v2_warning():
+ """
+ Disables the Pydantic version 2 warning by filtering out the related warnings.
+
+ This function checks the version of Pydantic currently installed and if it is version 2,
+ it filters out the PydanticDeprecationWarning and PydanticDeprecatedSince20 warnings
+ to suppress them.
+
+ Since we only need to run the code once, we are using lru_cache to improve performance.
+
+ Note: This function assumes that Pydantic is installed.
+
+ Usage:
+ disable_pydantic_v2_warning()
+ """
+ try:
+ from pydantic import __version__
+
+ version = __version__.split(".")
+
+ if int(version[0]) == 2: # pragma: no cover # dropping in v3
+ import warnings
+
+ from pydantic import PydanticDeprecatedSince20, PydanticDeprecationWarning
+
+ warnings.filterwarnings("ignore", category=PydanticDeprecationWarning)
+ warnings.filterwarnings("ignore", category=PydanticDeprecatedSince20)
+
+ except ImportError: # pragma: no cover # false positive; dropping in v3
+ pass
diff --git a/aws_lambda_powertools/utilities/parser/models/s3.py b/aws_lambda_powertools/utilities/parser/models/s3.py
index 594378155ef..cfba76fb078 100644
--- a/aws_lambda_powertools/utilities/parser/models/s3.py
+++ b/aws_lambda_powertools/utilities/parser/models/s3.py
@@ -61,7 +61,7 @@ class S3Message(BaseModel):
class S3EventNotificationObjectModel(BaseModel):
key: str
size: Optional[NonNegativeFloat] = None
- etag: str
+ etag: str = Field(default="")
version_id: str = Field(None, alias="version-id")
sequencer: Optional[str] = None
diff --git a/docs/Dockerfile b/docs/Dockerfile
index 6a733e6c585..5e5b42ea981 100644
--- a/docs/Dockerfile
+++ b/docs/Dockerfile
@@ -1,5 +1,5 @@
# v9.1.18
-FROM squidfunk/mkdocs-material@sha256:98c9809e64d0b9b3a4cf0c4c77d99e9bf42f2aaa331decb7c4b48ad4df64e6f5
+FROM squidfunk/mkdocs-material@sha256:8ef47d7116605e6b09860263af7278461c8dfca5dd3995f823dc96ea98b3f06c
# pip-compile --generate-hashes --output-file=requirements.txt requirements.in
COPY requirements.txt /tmp/
RUN pip install --require-hashes -r /tmp/requirements.txt
diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md
index aaf9352ebc0..aa667f5f169 100644
--- a/docs/core/event_handler/api_gateway.md
+++ b/docs/core/event_handler/api_gateway.md
@@ -221,7 +221,7 @@ You can use named decorators to specify the HTTP method that should be handled i
--8<-- "examples/event_handler_rest/src/http_methods.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.
+If you need to accept multiple HTTP methods in a single function, or support a HTTP method for which no decorator exists (e.g. [TRACE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE)), you can use the `route` method and pass a list of HTTP methods.
```python hl_lines="15" title="Handling multiple HTTP Methods"
--8<-- "examples/event_handler_rest/src/http_methods_multiple.py"
@@ -524,12 +524,13 @@ Behind the scenes, the [data validation](#data-validation) feature auto-generate
There are some important **caveats** that you should know before enabling it:
-| Caveat | Description |
-| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Swagger UI is **publicly accessible by default** | When using `enable_swagger` method, you can [protect sensitive API endpoints by implementing a custom middleware](#customizing-swagger-ui) using your preferred authorization mechanism. |
-| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. |
-| You need to expose a **new route** | You'll need to expose the following path to Lambda: `/swagger`; ignore if you're routing this path already. |
-| JS and CSS files are **embedded within Swagger HTML** | If you are not using an external CDN to serve Swagger UI assets, we embed JS and CSS directly into the HTML. To enhance performance, please consider enabling the `compress` option to minimize the size of HTTP requests. |
+| Caveat | Description |
+| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Swagger UI is **publicly accessible by default** | When using `enable_swagger` method, you can [protect sensitive API endpoints by implementing a custom middleware](#customizing-swagger-ui) using your preferred authorization mechanism. |
+| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. |
+| You need to expose a **new route** | You'll need to expose the following path to Lambda: `/swagger`; ignore if you're routing this path already. |
+| JS and CSS files are **embedded within Swagger HTML** | If you are not using an external CDN to serve Swagger UI assets, we embed JS and CSS directly into the HTML. To enhance performance, please consider enabling the `compress` option to minimize the size of HTTP requests. |
+| Authorization data is **lost** on browser close/refresh | Use `enable_swagger(persist_authorization=True)` to persist authorization data, like OAuath 2.0 access tokens. |
```python hl_lines="12-13" title="enabling_swagger.py"
--8<-- "examples/event_handler_rest/src/enabling_swagger.py"
@@ -835,8 +836,8 @@ As a practical example, let's refactor our correlation ID middleware so it accep
These are native middlewares that may become native features depending on customer demand.
-| Middleware | Purpose |
-| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
+| Middleware | Purpose |
+| ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| [SchemaValidationMiddleware](/lambda/python/latest/api/event_handler/middlewares/schema_validation.html){target="_blank"} | Validates API request body and response against JSON Schema, using [Validation utility](../../utilities/validation.md){target="_blank"} |
#### Being a good citizen
@@ -1053,7 +1054,7 @@ When you're describing your API, declare security schemes at the top level, and
OpenAPI 3 lets you describe APIs protected using the following security schemes:
| Security Scheme | Type | Description |
-|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [HTTP auth](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml){target="_blank"} | `HTTPBase` | HTTP authentication schemes using the Authorization header (e.g: [Basic auth](https://swagger.io/docs/specification/authentication/basic-authentication/){target="_blank"}, [Bearer](https://swagger.io/docs/specification/authentication/bearer-authentication/){target="_blank"}) |
| [API keys](https://swagger.io/docs/specification/authentication/api-keys/https://swagger.io/docs/specification/authentication/api-keys/){target="_blank"} (e.g: query strings, cookies) | `APIKey` | API keys in headers, query strings or [cookies](https://swagger.io/docs/specification/authentication/cookie-authentication/){target="_blank"}. |
| [OAuth 2](https://swagger.io/docs/specification/authentication/oauth2/){target="_blank"} | `OAuth2` | Authorization protocol that gives an API client limited access to user data on a web server. |
diff --git a/docs/core/logger.md b/docs/core/logger.md
index bf600e285ca..758762b547c 100644
--- a/docs/core/logger.md
+++ b/docs/core/logger.md
@@ -475,9 +475,9 @@ You can use any of the following built-in JMESPath expressions as part of [injec
### Reusing Logger across your code
-Similar to [Tracer](./tracer.md#reusing-tracer-across-your-code){target="_blank"}, a new instance that uses the same `service` name - env var or explicit parameter - will reuse a previous Logger instance. Just like `logging.getLogger("logger_name")` would in the standard library if called with the same logger name.
+Similar to [Tracer](./tracer.md#reusing-tracer-across-your-code){target="_blank"}, a new instance that uses the same `service` name will reuse a previous Logger instance.
-Notice in the CloudWatch Logs output how `payment_id` appeared as expected when logging in `collect.py`.
+Notice in the CloudWatch Logs output how `payment_id` appears as expected when logging in `collect.py`.
=== "logger_reuse.py"
@@ -497,17 +497,6 @@ Notice in the CloudWatch Logs output how `payment_id` appeared as expected when
--8<-- "examples/logger/src/logger_reuse_output.json"
```
-???+ note "Note: About Child Loggers"
- Coming from standard library, you might be used to use `logging.getLogger(__name__)`. This will create a new instance of a Logger with a different name.
-
- In Powertools, you can have the same effect by using `child=True` parameter: `Logger(child=True)`. This creates a new Logger instance named after `service.`. All state changes will be propagated bi-directionally between Child and Parent.
-
- For that reason, there could be side effects depending on the order the Child Logger is instantiated, because Child Loggers don't have a handler.
-
- For example, if you instantiated a Child Logger and immediately used `logger.append_keys/remove_keys/set_correlation_id` to update logging state, this might fail if the Parent Logger wasn't instantiated.
-
- In this scenario, you can either ensure any calls manipulating state are only called when a Parent Logger is instantiated (example above), or refrain from using `child=True` parameter altogether.
-
### Sampling debug logs
Use sampling when you want to dynamically change your log level to **DEBUG** based on a **percentage of your concurrent/cold start invocations**.
@@ -582,7 +571,7 @@ You can use import and use them as any other Logger formatter via `logger_format
### Migrating from other Loggers
-If you're migrating from other Loggers, there are few key points to be aware of: [Service parameter](#the-service-parameter), [Inheriting Loggers](#inheriting-loggers), [Overriding Log records](#overriding-log-records), and [Logging exceptions](#logging-exceptions).
+If you're migrating from other Loggers, there are few key points to be aware of: [Service parameter](#the-service-parameter), [Child Loggers](#child-loggers), [Overriding Log records](#overriding-log-records), and [Logging exceptions](#logging-exceptions).
#### The service parameter
@@ -590,23 +579,29 @@ Service is what defines the Logger name, including what the Lambda function is r
For Logger, the `service` is the logging key customers can use to search log operations for one or more functions - For example, **search for all errors, or messages like X, where service is payment**.
-#### Inheriting Loggers
+#### Child Loggers
-??? tip "Tip: Prefer [Logger Reuse feature](#reusing-logger-across-your-code) over inheritance unless strictly necessary, [see caveats.](#reusing-logger-across-your-code)"
-
-> Python Logging hierarchy happens via the dot notation: `service`, `service.child`, `service.child_2`
-
-For inheritance, Logger uses a `child=True` parameter along with `service` being the same value across Loggers.
+
+```mermaid
+stateDiagram-v2
+ direction LR
+ Parent: Logger()
+ Child: Logger(child=True)
+ Parent --> Child: bi-directional updates
+ Note right of Child
+ Both have the same service
+ end note
+```
+
-For child Loggers, we introspect the name of your module where `Logger(child=True, service="name")` is called, and we name your Logger as **{service}.{filename}**.
+For inheritance, Logger uses `child` parameter to ensure we don't compete with its parents config. We name child Loggers following Python's convention: _`{service}`.`{filename}`_.
-???+ danger
- A common issue when migrating from other Loggers is that `service` might be defined in the parent Logger (no child param), and not defined in the child Logger:
+Changes are bidirectional between parents and loggers. That is, appending a key in a child or parent will ensure both have them. This means, having the same `service` name is important when instantiating them.
-=== "logging_inheritance_bad.py"
+=== "logging_inheritance_good.py"
```python hl_lines="1 9"
- --8<-- "examples/logger/src/logging_inheritance_bad.py"
+ --8<-- "examples/logger/src/logging_inheritance_good.py"
```
=== "logging_inheritance_module.py"
@@ -615,17 +610,17 @@ For child Loggers, we introspect the name of your module where `Logger(child=Tru
--8<-- "examples/logger/src/logging_inheritance_module.py"
```
-In this case, Logger will register a Logger named `payment`, and a Logger named `service_undefined`. The latter isn't inheriting from the parent, and will have no handler, resulting in no message being logged to standard output.
-
-???+ tip
- This can be fixed by either ensuring both has the `service` value as `payment`, or simply use the environment variable `POWERTOOLS_SERVICE_NAME` to ensure service value will be the same across all Loggers when not explicitly set.
+There are two important side effects when using child loggers:
-Do this instead:
+1. **Service name mismatch**. Logging messages will be dropped as child loggers don't have logging handlers.
+ * Solution: use `POWERTOOLS_SERVICE_NAME` env var. Alternatively, use the same service explicit value.
+2. **Changing state before a parent instantiate**. Using `logger.append_keys` or `logger.remove_keys` without a parent Logger will lead to `OrphanedChildLoggerError` exception.
+ * Solution: always initialize parent Loggers first. Alternatively, move calls to `append_keys`/`remove_keys` from the child at a later stage.
-=== "logging_inheritance_good.py"
+=== "logging_inheritance_bad.py"
```python hl_lines="1 9"
- --8<-- "examples/logger/src/logging_inheritance_good.py"
+ --8<-- "examples/logger/src/logging_inheritance_bad.py"
```
=== "logging_inheritance_module.py"
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 9de8e7ee71f..e60fd35b041 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -26,9 +26,9 @@ importlib-metadata==7.0.1 \
# via
# markdown
# mkdocs
-jinja2==3.1.3 \
- --hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \
- --hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90
+jinja2==3.1.4 \
+ --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
+ --hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
# via
# mkdocs
# mkdocs-git-revision-date-plugin
diff --git a/examples/event_handler_bedrock_agents/cdk/bedrock_agent_stack.py b/examples/event_handler_bedrock_agents/cdk/bedrock_agent_stack.py
index ef220209d6d..8397d87b0e2 100644
--- a/examples/event_handler_bedrock_agents/cdk/bedrock_agent_stack.py
+++ b/examples/event_handler_bedrock_agents/cdk/bedrock_agent_stack.py
@@ -31,7 +31,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
foundation_model=BedrockFoundationModel.ANTHROPIC_CLAUDE_INSTANT_V1_2,
instruction="You are a helpful and friendly agent that answers questions about insurance claims.",
)
- agent.add_action_group(
+ agent.add_action_group( # type: ignore[call-arg]
action_group_name="InsureClaimsSupport",
description="Use these functions for insurance claims support",
action_group_executor=action_group_function,
diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod
index 1a32cf3ee24..d4941985aed 100644
--- a/layer/scripts/layer-balancer/go.mod
+++ b/layer/scripts/layer-balancer/go.mod
@@ -4,24 +4,24 @@ go 1.18
require (
github.com/aws/aws-sdk-go-v2 v1.26.1
- github.com/aws/aws-sdk-go-v2/config v1.27.11
- github.com/aws/aws-sdk-go-v2/service/lambda v1.54.0
+ github.com/aws/aws-sdk-go-v2/config v1.27.13
+ github.com/aws/aws-sdk-go-v2/service/lambda v1.54.1
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
golang.org/x/sync v0.7.0
)
require (
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
- github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect
+ github.com/aws/aws-sdk-go-v2/credentials v1.17.13 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 // indirect
github.com/aws/smithy-go v1.20.2 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
)
diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum
index 2655f1ecfc2..fc012835be4 100644
--- a/layer/scripts/layer-balancer/go.sum
+++ b/layer/scripts/layer-balancer/go.sum
@@ -2,10 +2,10 @@ github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
-github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA=
-github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
+github.com/aws/aws-sdk-go-v2/config v1.27.13 h1:WbKW8hOzrWoOA/+35S5okqO/2Ap8hkkFUzoW8Hzq24A=
+github.com/aws/aws-sdk-go-v2/config v1.27.13/go.mod h1:XLiyiTMnguytjRER7u5RIkhIqS8Nyz41SwAWb4xEjxs=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.13 h1:XDCJDzk/u5cN7Aple7D/MiAhx1Rjo/0nueJ0La8mRuE=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.13/go.mod h1:FMNcjQrmuBYvOTZDtOLCIu0esmxjF7RuA/89iSXWzQI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
@@ -18,14 +18,14 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1x
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk=
-github.com/aws/aws-sdk-go-v2/service/lambda v1.54.0 h1:gazALVrZ7RIG6gJXut3c7NKtPgs9eQ8BFCA9uoliayk=
-github.com/aws/aws-sdk-go-v2/service/lambda v1.54.0/go.mod h1:rFAo+jemFgeqYzDbbCbz2QWQs1Fnk1meTUK9fWkED9M=
-github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w=
-github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
-github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU=
-github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.54.1 h1:RzdiCmlbYq/Qmay/CHQychZFu+p0C+e1OfmK49LHSqg=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.54.1/go.mod h1:rFAo+jemFgeqYzDbbCbz2QWQs1Fnk1meTUK9fWkED9M=
+github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 h1:o5cTaeunSpfXiLTIBx5xo2enQmiChtu1IBbzXnfU9Hs=
+github.com/aws/aws-sdk-go-v2/service/sso v1.20.6/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 h1:Qe0r0lVURDDeBQJ4yP+BOrJkvkiCo/3FH/t+wY11dmw=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
+github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 h1:et3Ta53gotFR4ERLXXHIHl/Uuk1qYpP5uU7cvNql8ns=
+github.com/aws/aws-sdk-go-v2/service/sts v1.28.7/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw=
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
diff --git a/mkdocs.yml b/mkdocs.yml
index 17a8f1a73a9..efd18efd5cc 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -11,6 +11,7 @@ nav:
- API reference: api/" target="_blank
- Upgrade guide: upgrade.md
- We Made This (Community): we_made_this.md
+ - Workshop 🆕: https://s12d.com/powertools-for-aws-lambda-workshop" target="_blank
- Roadmap: roadmap.md
- Features:
- core/tracer.md
diff --git a/package-lock.json b/package-lock.json
index 79a911ad3b4..371506cf118 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,13 +11,13 @@
"package-lock.json": "^1.0.0"
},
"devDependencies": {
- "aws-cdk": "^2.140.0"
+ "aws-cdk": "^2.141.0"
}
},
"node_modules/aws-cdk": {
- "version": "2.140.0",
- "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.140.0.tgz",
- "integrity": "sha512-5NzmXFqjGYiTFZ+jgWBQJvrjhMIlYMoNTOwgvzHj2YnP9LhEsr60IdRGiXYD9CZyR79Hr3VQNbjcgO35bvW9/w==",
+ "version": "2.141.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.141.0.tgz",
+ "integrity": "sha512-RM9uDiETBEKCHemItaRGVjOLwoZ5iqXnejpyXY7+YF75c2c0Ui7HSZI8QD0stDg3S/2UbLcKv2RA9dBsjrWUGA==",
"dev": true,
"bin": {
"cdk": "bin/cdk"
diff --git a/package.json b/package.json
index 4c28c38c744..8e41cd62704 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "aws-lambda-powertools-python-e2e",
"version": "1.0.0",
"devDependencies": {
- "aws-cdk": "^2.140.0"
+ "aws-cdk": "^2.141.0"
},
"dependencies": {
"package-lock.json": "^1.0.0"
diff --git a/poetry.lock b/poetry.lock
index 49256bfb386..2ec11e93b56 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]]
name = "annotated-types"
@@ -363,17 +363,17 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "boto3"
-version = "1.34.102"
+version = "1.34.105"
description = "The AWS SDK for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "boto3-1.34.102-py3-none-any.whl", hash = "sha256:1c1fb2884f85c0ec6b62e6e7ed5a2a6635e1188f3ab5d2b700f7db1cf8464484"},
- {file = "boto3-1.34.102.tar.gz", hash = "sha256:65e4b9fb9ceefe19976e8822ac0cd68d28946d4697e538741d2bbdb5b45ae42f"},
+ {file = "boto3-1.34.105-py3-none-any.whl", hash = "sha256:b633e8fbf7145bdb995ce68a27d096bb89fd393185b0e773418d81cd78db5a03"},
+ {file = "boto3-1.34.105.tar.gz", hash = "sha256:f2c11635be0de7b7c06eb606ece1add125e02d6ed521592294a0a21af09af135"},
]
[package.dependencies]
-botocore = ">=1.34.102,<1.35.0"
+botocore = ">=1.34.105,<1.35.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.10.0,<0.11.0"
@@ -382,13 +382,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "botocore"
-version = "1.34.102"
+version = "1.34.105"
description = "Low-level, data-driven core of boto 3."
optional = false
python-versions = ">=3.8"
files = [
- {file = "botocore-1.34.102-py3-none-any.whl", hash = "sha256:79ac7fc2729294395c70eff9c23510f00785ad2acd78d6130cb4379e9f27da86"},
- {file = "botocore-1.34.102.tar.gz", hash = "sha256:e2f8a9f4bac6f7b568e6e981ac2a2500bc992329c85dde8546f0cae8605dd009"},
+ {file = "botocore-1.34.105-py3-none-any.whl", hash = "sha256:a459d060b541beecb50681e6e8a39313cca981e146a59ba7c5229d62f631a016"},
+ {file = "botocore-1.34.105.tar.gz", hash = "sha256:727d5d3e800ac8b705fca6e19b6fefa1e728a81d62a712df9bd32ed0117c740b"},
]
[package.dependencies]
@@ -443,13 +443,13 @@ ujson = ["ujson (>=5.7.0)"]
[[package]]
name = "cdk-nag"
-version = "2.28.113"
+version = "2.28.115"
description = "Check CDK v2 applications for best practices using a combination on available rule packs."
optional = false
python-versions = "~=3.8"
files = [
- {file = "cdk-nag-2.28.113.tar.gz", hash = "sha256:58e0ee75736af1faec1ee90dfc855bab14cb2bccc73b5f35af949eef66e9cec9"},
- {file = "cdk_nag-2.28.113-py3-none-any.whl", hash = "sha256:66e4afb6931e57183502849410d0319b748833f2eccf969d1b7ad7385de89152"},
+ {file = "cdk-nag-2.28.115.tar.gz", hash = "sha256:5336c5d031889412447bb839931e3889ecde6e751c31a264df63c73f67503278"},
+ {file = "cdk_nag-2.28.115-py3-none-any.whl", hash = "sha256:0f7c9cf104ce5b3152b7d7666f8ffa816b1aca8bbcc258fa4034dd28e3094a73"},
]
[package.dependencies]
@@ -461,18 +461,18 @@ typeguard = ">=2.13.3,<2.14.0"
[[package]]
name = "cdklabs-generative-ai-cdk-constructs"
-version = "0.1.143"
+version = "0.1.148"
description = "AWS Generative AI CDK Constructs is a library for well-architected generative AI patterns."
optional = false
python-versions = "~=3.8"
files = [
- {file = "cdklabs.generative-ai-cdk-constructs-0.1.143.tar.gz", hash = "sha256:315c121629aae9722a013694403b375380a8c3628d4fe6a8fd92d5c72df156c3"},
- {file = "cdklabs.generative_ai_cdk_constructs-0.1.143-py3-none-any.whl", hash = "sha256:ca13983eb28905bdf590e00863a30d104f41de1c8cef63cd4478cc978fe26008"},
+ {file = "cdklabs.generative-ai-cdk-constructs-0.1.148.tar.gz", hash = "sha256:5442691bb3c66102873bab2a4fa14be49c43ab956ff21746231711b322407ebe"},
+ {file = "cdklabs.generative_ai_cdk_constructs-0.1.148-py3-none-any.whl", hash = "sha256:728daa0bdfdd5bf1b43cb2ced1c936465edc5b4932aa47cf25cb254277be6f3c"},
]
[package.dependencies]
-aws-cdk-lib = ">=2.122.0,<3.0.0"
-cdk-nag = ">=2.28.111,<3.0.0"
+aws-cdk-lib = ">=2.141.0,<3.0.0"
+cdk-nag = ">=2.28.115,<3.0.0"
constructs = ">=10.3.0,<11.0.0"
jsii = ">=1.98.0,<2.0.0"
publication = ">=0.0.3"
@@ -555,13 +555,13 @@ pycparser = "*"
[[package]]
name = "cfn-lint"
-version = "0.87.0"
+version = "0.87.2"
description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved"
optional = false
python-versions = "!=4.0,<=4.0,>=3.8"
files = [
- {file = "cfn_lint-0.87.0-py3-none-any.whl", hash = "sha256:a374312e906f732141b0fce28c176078f855d3b2ba5d43ef376c86ad14e11d4b"},
- {file = "cfn_lint-0.87.0.tar.gz", hash = "sha256:749b7e52a2d83f1236e87ef9c244910ffff609bcdf357eab0814ed80c076de11"},
+ {file = "cfn_lint-0.87.2-py3-none-any.whl", hash = "sha256:773ba1d2f232ffdbe1197cc6ce61ddbf0da1781925e9f4dde4c91b7fcd54cc80"},
+ {file = "cfn_lint-0.87.2.tar.gz", hash = "sha256:00d47406841899c05ab6a0708df3f4e32bd7462be2097c10371d744c0050775e"},
]
[package.dependencies]
@@ -1377,22 +1377,22 @@ files = [
[[package]]
name = "importlib-metadata"
-version = "7.0.0"
+version = "7.1.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"},
- {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"},
+ {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"},
+ {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"},
]
[package.dependencies]
zipp = ">=0.5"
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
-testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
[[package]]
name = "importlib-resources"
@@ -1610,13 +1610,13 @@ six = "*"
[[package]]
name = "mako"
-version = "1.3.3"
+version = "1.3.5"
description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
optional = false
python-versions = ">=3.8"
files = [
- {file = "Mako-1.3.3-py3-none-any.whl", hash = "sha256:5324b88089a8978bf76d1629774fcc2f1c07b82acdf00f4c5dd8ceadfffc4b40"},
- {file = "Mako-1.3.3.tar.gz", hash = "sha256:e16c01d9ab9c11f7290eef1cfefc093fb5a45ee4a3da09e2fec2e4d1bae54e73"},
+ {file = "Mako-1.3.5-py3-none-any.whl", hash = "sha256:260f1dbc3a519453a9c856dedfe4beb4e50bd5a26d96386cb6c80856556bb91a"},
+ {file = "Mako-1.3.5.tar.gz", hash = "sha256:48dbc20568c1d276a2698b36d968fa76161bf127194907ea6fc594fa81f943bc"},
]
[package.dependencies]
@@ -1867,13 +1867,13 @@ mkdocs = ">=0.17"
[[package]]
name = "mkdocs-material"
-version = "9.5.21"
+version = "9.5.23"
description = "Documentation that simply works"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mkdocs_material-9.5.21-py3-none-any.whl", hash = "sha256:210e1f179682cd4be17d5c641b2f4559574b9dea2f589c3f0e7c17c5bd1959bc"},
- {file = "mkdocs_material-9.5.21.tar.gz", hash = "sha256:049f82770f40559d3c2aa2259c562ea7257dbb4aaa9624323b5ef27b2d95a450"},
+ {file = "mkdocs_material-9.5.23-py3-none-any.whl", hash = "sha256:ffd08a5beaef3cd135aceb58ded8b98bbbbf2b70e5b656f6a14a63c917d9b001"},
+ {file = "mkdocs_material-9.5.23.tar.gz", hash = "sha256:4627fc3f15de2cba2bde9debc2fd59b9888ef494beabfe67eb352e23d14bf288"},
]
[package.dependencies]
@@ -2093,13 +2093,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""}
[[package]]
name = "mypy-boto3-s3"
-version = "1.34.91"
-description = "Type annotations for boto3.S3 1.34.91 service generated with mypy-boto3-builder 7.24.0"
+version = "1.34.105"
+description = "Type annotations for boto3.S3 1.34.105 service generated with mypy-boto3-builder 7.24.0"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mypy_boto3_s3-1.34.91-py3-none-any.whl", hash = "sha256:0d37161fd0cd7ebf194cf9ccadb9101bf5c9b2426c2d00677b7e644d6f2298e4"},
- {file = "mypy_boto3_s3-1.34.91.tar.gz", hash = "sha256:70c8bad00db70704fb7ac0ee1440c7eb0587578ae9a2b00997f29f17f60f45e7"},
+ {file = "mypy_boto3_s3-1.34.105-py3-none-any.whl", hash = "sha256:95fbc6bcba2bb03c20a97cc5cf60ff66c6842c8c4fc4183c49bfa35905d5a1ee"},
+ {file = "mypy_boto3_s3-1.34.105.tar.gz", hash = "sha256:a137bca9bbe86c0fe35bbf36a2d44ab62526f41bb683550dd6cfbb5a10ede832"},
]
[package.dependencies]
@@ -2178,18 +2178,18 @@ test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"]
[[package]]
name = "opentelemetry-api"
-version = "1.24.0"
+version = "1.16.0"
description = "OpenTelemetry Python API"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.7"
files = [
- {file = "opentelemetry_api-1.24.0-py3-none-any.whl", hash = "sha256:0f2c363d98d10d1ce93330015ca7fd3a65f60be64e05e30f557c61de52c80ca2"},
- {file = "opentelemetry_api-1.24.0.tar.gz", hash = "sha256:42719f10ce7b5a9a73b10a4baf620574fb8ad495a9cbe5c18d76b75d8689c67e"},
+ {file = "opentelemetry_api-1.16.0-py3-none-any.whl", hash = "sha256:79e8f0cf88dbdd36b6abf175d2092af1efcaa2e71552d0d2b3b181a9707bf4bc"},
+ {file = "opentelemetry_api-1.16.0.tar.gz", hash = "sha256:4b0e895a3b1f5e1908043ebe492d33e33f9ccdbe6d02d3994c2f8721a63ddddb"},
]
[package.dependencies]
deprecated = ">=1.2.6"
-importlib-metadata = ">=6.0,<=7.0"
+setuptools = ">=16.0"
[[package]]
name = "packaging"
@@ -2262,13 +2262,13 @@ files = [
[[package]]
name = "platformdirs"
-version = "4.2.1"
+version = "4.2.2"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false
python-versions = ">=3.8"
files = [
- {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"},
- {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"},
+ {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"},
+ {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"},
]
[package.extras]
@@ -2815,90 +2815,90 @@ rpds-py = ">=0.7.0"
[[package]]
name = "regex"
-version = "2024.5.10"
+version = "2024.5.15"
description = "Alternative regular expression module, to replace re."
optional = false
python-versions = ">=3.8"
files = [
- {file = "regex-2024.5.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:eda3dd46df535da787ffb9036b5140f941ecb91701717df91c9daf64cabef953"},
- {file = "regex-2024.5.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d5bd666466c8f00a06886ce1397ba8b12371c1f1c6d1bef11013e9e0a1464a8"},
- {file = "regex-2024.5.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:32e5f3b8e32918bfbdd12eca62e49ab3031125c454b507127ad6ecbd86e62fca"},
- {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:534efd2653ebc4f26fc0e47234e53bf0cb4715bb61f98c64d2774a278b58c846"},
- {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:193b7c6834a06f722f0ce1ba685efe80881de7c3de31415513862f601097648c"},
- {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:160ba087232c5c6e2a1e7ad08bd3a3f49b58c815be0504d8c8aacfb064491cd8"},
- {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:951be1eae7b47660412dc4938777a975ebc41936d64e28081bf2e584b47ec246"},
- {file = "regex-2024.5.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8a0f0ab5453e409586b11ebe91c672040bc804ca98d03a656825f7890cbdf88"},
- {file = "regex-2024.5.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9e6d4d6ae1827b2f8c7200aaf7501c37cf3f3896c86a6aaf2566448397c823dd"},
- {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:161a206c8f3511e2f5fafc9142a2cc25d7fe9a1ec5ad9b4ad2496a7c33e1c5d2"},
- {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:44b3267cea873684af022822195298501568ed44d542f9a2d9bebc0212e99069"},
- {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:560278c9975694e1f0bc50da187abf2cdc1e4890739ea33df2bc4a85eeef143e"},
- {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:70364a097437dd0a90b31cd77f09f7387ad9ac60ef57590971f43b7fca3082a5"},
- {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42be5de7cc8c1edac55db92d82b68dc8e683b204d6f5414c5a51997a323d7081"},
- {file = "regex-2024.5.10-cp310-cp310-win32.whl", hash = "sha256:9a8625849387b9d558d528e263ecc9c0fbde86cfa5c2f0eef43fff480ae24d71"},
- {file = "regex-2024.5.10-cp310-cp310-win_amd64.whl", hash = "sha256:903350bf44d7e4116b4d5898b30b15755d61dcd3161e3413a49c7db76f0bee5a"},
- {file = "regex-2024.5.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bf9596cba92ce7b1fd32c7b07c6e3212c7eed0edc271757e48bfcd2b54646452"},
- {file = "regex-2024.5.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:45cc13d398b6359a7708986386f72bd156ae781c3e83a68a6d4cee5af04b1ce9"},
- {file = "regex-2024.5.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ad45f3bccfcb00868f2871dce02a755529838d2b86163ab8a246115e80cfb7d6"},
- {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d19f0cde6838c81acffff25c7708e4adc7dd02896c9ec25c3939b1500a1778"},
- {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0a9f89d7db5ef6bdf53e5cc8e6199a493d0f1374b3171796b464a74ebe8e508a"},
- {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c6c71cf92b09e5faa72ea2c68aa1f61c9ce11cb66fdc5069d712f4392ddfd00"},
- {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7467ad8b0eac0b28e52679e972b9b234b3de0ea5cee12eb50091d2b68145fe36"},
- {file = "regex-2024.5.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc0db93ad039fc2fe32ccd3dd0e0e70c4f3d6e37ae83f0a487e1aba939bd2fbd"},
- {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fa9335674d7c819674467c7b46154196c51efbaf5f5715187fd366814ba3fa39"},
- {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7dda3091838206969c2b286f9832dff41e2da545b99d1cfaea9ebd8584d02708"},
- {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:504b5116e2bd1821efd815941edff7535e93372a098e156bb9dffde30264e798"},
- {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:91b53dea84415e8115506cc62e441a2b54537359c63d856d73cb1abe05af4c9a"},
- {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1a3903128f9e17a500618e80c68165c78c741ebb17dd1a0b44575f92c3c68b02"},
- {file = "regex-2024.5.10-cp311-cp311-win32.whl", hash = "sha256:236cace6c1903effd647ed46ce6dd5d76d54985fc36dafc5256032886736c85d"},
- {file = "regex-2024.5.10-cp311-cp311-win_amd64.whl", hash = "sha256:12446827f43c7881decf2c126762e11425de5eb93b3b0d8b581344c16db7047a"},
- {file = "regex-2024.5.10-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:14905ed75c7a6edf423eb46c213ed3f4507c38115f1ed3c00f4ec9eafba50e58"},
- {file = "regex-2024.5.10-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4fad420b14ae1970a1f322e8ae84a1d9d89375eb71e1b504060ab2d1bfe68f3c"},
- {file = "regex-2024.5.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c46a76a599fcbf95f98755275c5527304cc4f1bb69919434c1e15544d7052910"},
- {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0faecb6d5779753a6066a3c7a0471a8d29fe25d9981ca9e552d6d1b8f8b6a594"},
- {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aab65121229c2ecdf4a31b793d99a6a0501225bd39b616e653c87b219ed34a49"},
- {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50e7e96a527488334379e05755b210b7da4a60fc5d6481938c1fa053e0c92184"},
- {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba034c8db4b264ef1601eb33cd23d87c5013b8fb48b8161debe2e5d3bd9156b0"},
- {file = "regex-2024.5.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:031219782d97550c2098d9a68ce9e9eaefe67d2d81d8ff84c8354f9c009e720c"},
- {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:62b5f7910b639f3c1d122d408421317c351e213ca39c964ad4121f27916631c6"},
- {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cd832bd9b6120d6074f39bdfbb3c80e416848b07ac72910f1c7f03131a6debc3"},
- {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:e91b1976358e17197157b405cab408a5f4e33310cda211c49fc6da7cffd0b2f0"},
- {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:571452362d552de508c37191b6abbbb660028b8b418e2d68c20779e0bc8eaaa8"},
- {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5253dcb0bfda7214523de58b002eb0090cb530d7c55993ce5f6d17faf953ece7"},
- {file = "regex-2024.5.10-cp312-cp312-win32.whl", hash = "sha256:2f30a5ab8902f93930dc6f627c4dd5da2703333287081c85cace0fc6e21c25af"},
- {file = "regex-2024.5.10-cp312-cp312-win_amd64.whl", hash = "sha256:3799e36d60a35162bb35b2246d8bb012192b7437dff807ef79c14e7352706306"},
- {file = "regex-2024.5.10-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bbdc5db2c98ac2bf1971ffa1410c87ca7a15800415f788971e8ba8520fc0fda9"},
- {file = "regex-2024.5.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6ccdeef4584450b6f0bddd5135354908dacad95425fcb629fe36d13e48b60f32"},
- {file = "regex-2024.5.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:29d839829209f3c53f004e1de8c3113efce6d98029f044fa5cfee666253ee7e6"},
- {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0709ba544cf50bd5cb843df4b8bb6701bae2b70a8e88da9add8386cbca5c1385"},
- {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:972b49f2fe1047b9249c958ec4fa1bdd2cf8ce305dc19d27546d5a38e57732d8"},
- {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cdbb1998da94607d5eec02566b9586f0e70d6438abf1b690261aac0edda7ab6"},
- {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7c8ee4861d9ef5b1120abb75846828c811f932d63311596ad25fa168053e00"},
- {file = "regex-2024.5.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d35d4cc9270944e95f9c88af757b0c9fc43f396917e143a5756608462c5223b"},
- {file = "regex-2024.5.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8722f72068b3e1156a4b2e1afde6810f1fc67155a9fa30a4b9d5b4bc46f18fb0"},
- {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:696639a73ca78a380acfaa0a1f6dd8220616a99074c05bba9ba8bb916914b224"},
- {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea057306ab469130167014b662643cfaed84651c792948891d003cf0039223a5"},
- {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b43b78f9386d3d932a6ce5af4b45f393d2e93693ee18dc4800d30a8909df700e"},
- {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c43395a3b7cc9862801a65c6994678484f186ce13c929abab44fb8a9e473a55a"},
- {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0bc94873ba11e34837bffd7e5006703abeffc4514e2f482022f46ce05bd25e67"},
- {file = "regex-2024.5.10-cp38-cp38-win32.whl", hash = "sha256:1118ba9def608250250f4b3e3f48c62f4562ba16ca58ede491b6e7554bfa09ff"},
- {file = "regex-2024.5.10-cp38-cp38-win_amd64.whl", hash = "sha256:458d68d34fb74b906709735c927c029e62f7d06437a98af1b5b6258025223210"},
- {file = "regex-2024.5.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:15e593386ec6331e0ab4ac0795b7593f02ab2f4b30a698beb89fbdc34f92386a"},
- {file = "regex-2024.5.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ca23b41355ba95929e9505ee04e55495726aa2282003ed9b012d86f857d3e49b"},
- {file = "regex-2024.5.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c8982ee19ccecabbaeac1ba687bfef085a6352a8c64f821ce2f43e6d76a9298"},
- {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7117cb7d6ac7f2e985f3d18aa8a1728864097da1a677ffa69e970ca215baebf1"},
- {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66421f8878a0c82fc0c272a43e2121c8d4c67cb37429b764f0d5ad70b82993b"},
- {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:224a9269f133564109ce668213ef3cb32bc72ccf040b0b51c72a50e569e9dc9e"},
- {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab98016541543692a37905871a5ffca59b16e08aacc3d7d10a27297b443f572d"},
- {file = "regex-2024.5.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d27844763c273a122e08a3e86e7aefa54ee09fb672d96a645ece0454d8425e"},
- {file = "regex-2024.5.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:853cc36e756ff673bf984e9044ccc8fad60b95a748915dddeab9488aea974c73"},
- {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e7eaf9df15423d07b6050fb91f86c66307171b95ea53e2d87a7993b6d02c7f7"},
- {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:169fd0acd7a259f58f417e492e93d0e15fc87592cd1e971c8c533ad5703b5830"},
- {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:334b79ce9c08f26b4659a53f42892793948a613c46f1b583e985fd5a6bf1c149"},
- {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f03b1dbd4d9596dd84955bb40f7d885204d6aac0d56a919bb1e0ff2fb7e1735a"},
- {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfa6d61a76c77610ba9274c1a90a453062bdf6887858afbe214d18ad41cf6bde"},
- {file = "regex-2024.5.10-cp39-cp39-win32.whl", hash = "sha256:249fbcee0a277c32a3ce36d8e36d50c27c968fdf969e0fbe342658d4e010fbc8"},
- {file = "regex-2024.5.10-cp39-cp39-win_amd64.whl", hash = "sha256:0ce56a923f4c01d7568811bfdffe156268c0a7aae8a94c902b92fe34c4bde785"},
- {file = "regex-2024.5.10.tar.gz", hash = "sha256:304e7e2418146ae4d0ef0e9ffa28f881f7874b45b4994cc2279b21b6e7ae50c8"},
+ {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"},
+ {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"},
+ {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"},
+ {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"},
+ {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"},
+ {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"},
+ {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"},
+ {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"},
+ {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"},
+ {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"},
+ {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"},
+ {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"},
+ {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"},
+ {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"},
+ {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"},
+ {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"},
+ {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"},
+ {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"},
+ {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"},
+ {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"},
+ {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"},
+ {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"},
+ {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"},
+ {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"},
+ {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"},
+ {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"},
+ {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"},
+ {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"},
+ {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"},
+ {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"},
+ {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"},
+ {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"},
+ {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"},
+ {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"},
+ {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"},
+ {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"},
]
[[package]]
@@ -3064,28 +3064,28 @@ files = [
[[package]]
name = "ruff"
-version = "0.4.2"
+version = "0.4.4"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
- {file = "ruff-0.4.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d14dc8953f8af7e003a485ef560bbefa5f8cc1ad994eebb5b12136049bbccc5"},
- {file = "ruff-0.4.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:24016ed18db3dc9786af103ff49c03bdf408ea253f3cb9e3638f39ac9cf2d483"},
- {file = "ruff-0.4.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2e06459042ac841ed510196c350ba35a9b24a643e23db60d79b2db92af0c2b"},
- {file = "ruff-0.4.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3afabaf7ba8e9c485a14ad8f4122feff6b2b93cc53cd4dad2fd24ae35112d5c5"},
- {file = "ruff-0.4.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:799eb468ea6bc54b95527143a4ceaf970d5aa3613050c6cff54c85fda3fde480"},
- {file = "ruff-0.4.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ec4ba9436a51527fb6931a8839af4c36a5481f8c19e8f5e42c2f7ad3a49f5069"},
- {file = "ruff-0.4.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6a2243f8f434e487c2a010c7252150b1fdf019035130f41b77626f5655c9ca22"},
- {file = "ruff-0.4.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8772130a063f3eebdf7095da00c0b9898bd1774c43b336272c3e98667d4fb8fa"},
- {file = "ruff-0.4.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ab165ef5d72392b4ebb85a8b0fbd321f69832a632e07a74794c0e598e7a8376"},
- {file = "ruff-0.4.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1f32cadf44c2020e75e0c56c3408ed1d32c024766bd41aedef92aa3ca28eef68"},
- {file = "ruff-0.4.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:22e306bf15e09af45ca812bc42fa59b628646fa7c26072555f278994890bc7ac"},
- {file = "ruff-0.4.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:82986bb77ad83a1719c90b9528a9dd663c9206f7c0ab69282af8223566a0c34e"},
- {file = "ruff-0.4.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:652e4ba553e421a6dc2a6d4868bc3b3881311702633eb3672f9f244ded8908cd"},
- {file = "ruff-0.4.2-py3-none-win32.whl", hash = "sha256:7891ee376770ac094da3ad40c116258a381b86c7352552788377c6eb16d784fe"},
- {file = "ruff-0.4.2-py3-none-win_amd64.whl", hash = "sha256:5ec481661fb2fd88a5d6cf1f83403d388ec90f9daaa36e40e2c003de66751798"},
- {file = "ruff-0.4.2-py3-none-win_arm64.whl", hash = "sha256:cbd1e87c71bca14792948c4ccb51ee61c3296e164019d2d484f3eaa2d360dfaf"},
- {file = "ruff-0.4.2.tar.gz", hash = "sha256:33bcc160aee2520664bc0859cfeaebc84bb7323becff3f303b8f1f2d81cb4edc"},
+ {file = "ruff-0.4.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:29d44ef5bb6a08e235c8249294fa8d431adc1426bfda99ed493119e6f9ea1bf6"},
+ {file = "ruff-0.4.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c4efe62b5bbb24178c950732ddd40712b878a9b96b1d02b0ff0b08a090cbd891"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c8e2f1e8fc12d07ab521a9005d68a969e167b589cbcaee354cb61e9d9de9c15"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:60ed88b636a463214905c002fa3eaab19795679ed55529f91e488db3fe8976ab"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b90fc5e170fc71c712cc4d9ab0e24ea505c6a9e4ebf346787a67e691dfb72e85"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8e7e6ebc10ef16dcdc77fd5557ee60647512b400e4a60bdc4849468f076f6eef"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9ddb2c494fb79fc208cd15ffe08f32b7682519e067413dbaf5f4b01a6087bcd"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c51c928a14f9f0a871082603e25a1588059b7e08a920f2f9fa7157b5bf08cfe9"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5eb0a4bfd6400b7d07c09a7725e1a98c3b838be557fee229ac0f84d9aa49c36"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b1867ee9bf3acc21778dcb293db504692eda5f7a11a6e6cc40890182a9f9e595"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1aecced1269481ef2894cc495647392a34b0bf3e28ff53ed95a385b13aa45768"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9da73eb616b3241a307b837f32756dc20a0b07e2bcb694fec73699c93d04a69e"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:958b4ea5589706a81065e2a776237de2ecc3e763342e5cc8e02a4a4d8a5e6f95"},
+ {file = "ruff-0.4.4-py3-none-win32.whl", hash = "sha256:cb53473849f011bca6e754f2cdf47cafc9c4f4ff4570003a0dad0b9b6890e876"},
+ {file = "ruff-0.4.4-py3-none-win_amd64.whl", hash = "sha256:424e5b72597482543b684c11def82669cc6b395aa8cc69acc1858b5ef3e5daae"},
+ {file = "ruff-0.4.4-py3-none-win_arm64.whl", hash = "sha256:39df0537b47d3b597293edbb95baf54ff5b49589eb7ff41926d8243caa995ea6"},
+ {file = "ruff-0.4.4.tar.gz", hash = "sha256:f87ea42d5cdebdc6a69761a9d0bc83ae9b3b30d0ad78952005ba6568d6c022af"},
]
[[package]]
@@ -3407,13 +3407,13 @@ urllib3 = ">=2"
[[package]]
name = "types-setuptools"
-version = "69.5.0.20240423"
+version = "69.5.0.20240513"
description = "Typing stubs for setuptools"
optional = false
python-versions = ">=3.8"
files = [
- {file = "types-setuptools-69.5.0.20240423.tar.gz", hash = "sha256:a7ba908f1746c4337d13f027fa0f4a5bcad6d1d92048219ba792b3295c58586d"},
- {file = "types_setuptools-69.5.0.20240423-py3-none-any.whl", hash = "sha256:a4381e041510755a6c9210e26ad55b1629bc10237aeb9cb8b6bd24996b73db48"},
+ {file = "types-setuptools-69.5.0.20240513.tar.gz", hash = "sha256:3a8ccea3e3f1f639856a1dd622be282f74e94e00fdc364630240f999cc9594fc"},
+ {file = "types_setuptools-69.5.0.20240513-py3-none-any.whl", hash = "sha256:bd3964c08cffd5a057d9cabe61641c86a41a1b5dd2b652b8d371eed64d89d726"},
]
[[package]]
@@ -3440,76 +3440,89 @@ files = [
[[package]]
name = "ujson"
-version = "5.9.0"
+version = "5.10.0"
description = "Ultra fast JSON encoder and decoder for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "ujson-5.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab71bf27b002eaf7d047c54a68e60230fbd5cd9da60de7ca0aa87d0bccead8fa"},
- {file = "ujson-5.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a365eac66f5aa7a7fdf57e5066ada6226700884fc7dce2ba5483538bc16c8c5"},
- {file = "ujson-5.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e015122b337858dba5a3dc3533af2a8fc0410ee9e2374092f6a5b88b182e9fcc"},
- {file = "ujson-5.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:779a2a88c53039bebfbccca934430dabb5c62cc179e09a9c27a322023f363e0d"},
- {file = "ujson-5.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10ca3c41e80509fd9805f7c149068fa8dbee18872bbdc03d7cca928926a358d5"},
- {file = "ujson-5.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a566e465cb2fcfdf040c2447b7dd9718799d0d90134b37a20dff1e27c0e9096"},
- {file = "ujson-5.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f833c529e922577226a05bc25b6a8b3eb6c4fb155b72dd88d33de99d53113124"},
- {file = "ujson-5.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b68a0caab33f359b4cbbc10065c88e3758c9f73a11a65a91f024b2e7a1257106"},
- {file = "ujson-5.9.0-cp310-cp310-win32.whl", hash = "sha256:7cc7e605d2aa6ae6b7321c3ae250d2e050f06082e71ab1a4200b4ae64d25863c"},
- {file = "ujson-5.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:a6d3f10eb8ccba4316a6b5465b705ed70a06011c6f82418b59278fbc919bef6f"},
- {file = "ujson-5.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b23bbb46334ce51ddb5dded60c662fbf7bb74a37b8f87221c5b0fec1ec6454b"},
- {file = "ujson-5.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6974b3a7c17bbf829e6c3bfdc5823c67922e44ff169851a755eab79a3dd31ec0"},
- {file = "ujson-5.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5964ea916edfe24af1f4cc68488448fbb1ec27a3ddcddc2b236da575c12c8ae"},
- {file = "ujson-5.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ba7cac47dd65ff88571eceeff48bf30ed5eb9c67b34b88cb22869b7aa19600d"},
- {file = "ujson-5.9.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bbd91a151a8f3358c29355a491e915eb203f607267a25e6ab10531b3b157c5e"},
- {file = "ujson-5.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:829a69d451a49c0de14a9fecb2a2d544a9b2c884c2b542adb243b683a6f15908"},
- {file = "ujson-5.9.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a807ae73c46ad5db161a7e883eec0fbe1bebc6a54890152ccc63072c4884823b"},
- {file = "ujson-5.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8fc2aa18b13d97b3c8ccecdf1a3c405f411a6e96adeee94233058c44ff92617d"},
- {file = "ujson-5.9.0-cp311-cp311-win32.whl", hash = "sha256:70e06849dfeb2548be48fdd3ceb53300640bc8100c379d6e19d78045e9c26120"},
- {file = "ujson-5.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:7309d063cd392811acc49b5016728a5e1b46ab9907d321ebbe1c2156bc3c0b99"},
- {file = "ujson-5.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:20509a8c9f775b3a511e308bbe0b72897ba6b800767a7c90c5cca59d20d7c42c"},
- {file = "ujson-5.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b28407cfe315bd1b34f1ebe65d3bd735d6b36d409b334100be8cdffae2177b2f"},
- {file = "ujson-5.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d302bd17989b6bd90d49bade66943c78f9e3670407dbc53ebcf61271cadc399"},
- {file = "ujson-5.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f21315f51e0db8ee245e33a649dd2d9dce0594522de6f278d62f15f998e050e"},
- {file = "ujson-5.9.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5635b78b636a54a86fdbf6f027e461aa6c6b948363bdf8d4fbb56a42b7388320"},
- {file = "ujson-5.9.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:82b5a56609f1235d72835ee109163c7041b30920d70fe7dac9176c64df87c164"},
- {file = "ujson-5.9.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5ca35f484622fd208f55041b042d9d94f3b2c9c5add4e9af5ee9946d2d30db01"},
- {file = "ujson-5.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:829b824953ebad76d46e4ae709e940bb229e8999e40881338b3cc94c771b876c"},
- {file = "ujson-5.9.0-cp312-cp312-win32.whl", hash = "sha256:25fa46e4ff0a2deecbcf7100af3a5d70090b461906f2299506485ff31d9ec437"},
- {file = "ujson-5.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:60718f1720a61560618eff3b56fd517d107518d3c0160ca7a5a66ac949c6cf1c"},
- {file = "ujson-5.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d581db9db9e41d8ea0b2705c90518ba623cbdc74f8d644d7eb0d107be0d85d9c"},
- {file = "ujson-5.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ff741a5b4be2d08fceaab681c9d4bc89abf3c9db600ab435e20b9b6d4dfef12e"},
- {file = "ujson-5.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdcb02cabcb1e44381221840a7af04433c1dc3297af76fde924a50c3054c708c"},
- {file = "ujson-5.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e208d3bf02c6963e6ef7324dadf1d73239fb7008491fdf523208f60be6437402"},
- {file = "ujson-5.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4b3917296630a075e04d3d07601ce2a176479c23af838b6cf90a2d6b39b0d95"},
- {file = "ujson-5.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0c4d6adb2c7bb9eb7c71ad6f6f612e13b264942e841f8cc3314a21a289a76c4e"},
- {file = "ujson-5.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0b159efece9ab5c01f70b9d10bbb77241ce111a45bc8d21a44c219a2aec8ddfd"},
- {file = "ujson-5.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0cb4a7814940ddd6619bdce6be637a4b37a8c4760de9373bac54bb7b229698b"},
- {file = "ujson-5.9.0-cp38-cp38-win32.whl", hash = "sha256:dc80f0f5abf33bd7099f7ac94ab1206730a3c0a2d17549911ed2cb6b7aa36d2d"},
- {file = "ujson-5.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:506a45e5fcbb2d46f1a51fead991c39529fc3737c0f5d47c9b4a1d762578fc30"},
- {file = "ujson-5.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0fd2eba664a22447102062814bd13e63c6130540222c0aa620701dd01f4be81"},
- {file = "ujson-5.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bdf7fc21a03bafe4ba208dafa84ae38e04e5d36c0e1c746726edf5392e9f9f36"},
- {file = "ujson-5.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2f909bc08ce01f122fd9c24bc6f9876aa087188dfaf3c4116fe6e4daf7e194f"},
- {file = "ujson-5.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd4ea86c2afd41429751d22a3ccd03311c067bd6aeee2d054f83f97e41e11d8f"},
- {file = "ujson-5.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:63fb2e6599d96fdffdb553af0ed3f76b85fda63281063f1cb5b1141a6fcd0617"},
- {file = "ujson-5.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:32bba5870c8fa2a97f4a68f6401038d3f1922e66c34280d710af00b14a3ca562"},
- {file = "ujson-5.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:37ef92e42535a81bf72179d0e252c9af42a4ed966dc6be6967ebfb929a87bc60"},
- {file = "ujson-5.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f69f16b8f1c69da00e38dc5f2d08a86b0e781d0ad3e4cc6a13ea033a439c4844"},
- {file = "ujson-5.9.0-cp39-cp39-win32.whl", hash = "sha256:3382a3ce0ccc0558b1c1668950008cece9bf463ebb17463ebf6a8bfc060dae34"},
- {file = "ujson-5.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:6adef377ed583477cf005b58c3025051b5faa6b8cc25876e594afbb772578f21"},
- {file = "ujson-5.9.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ffdfebd819f492e48e4f31c97cb593b9c1a8251933d8f8972e81697f00326ff1"},
- {file = "ujson-5.9.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4eec2ddc046360d087cf35659c7ba0cbd101f32035e19047013162274e71fcf"},
- {file = "ujson-5.9.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbb90aa5c23cb3d4b803c12aa220d26778c31b6e4b7a13a1f49971f6c7d088e"},
- {file = "ujson-5.9.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba0823cb70866f0d6a4ad48d998dd338dce7314598721bc1b7986d054d782dfd"},
- {file = "ujson-5.9.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4e35d7885ed612feb6b3dd1b7de28e89baaba4011ecdf995e88be9ac614765e9"},
- {file = "ujson-5.9.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b048aa93eace8571eedbd67b3766623e7f0acbf08ee291bef7d8106210432427"},
- {file = "ujson-5.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:323279e68c195110ef85cbe5edce885219e3d4a48705448720ad925d88c9f851"},
- {file = "ujson-5.9.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ac92d86ff34296f881e12aa955f7014d276895e0e4e868ba7fddebbde38e378"},
- {file = "ujson-5.9.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6eecbd09b316cea1fd929b1e25f70382917542ab11b692cb46ec9b0a26c7427f"},
- {file = "ujson-5.9.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:473fb8dff1d58f49912323d7cb0859df5585cfc932e4b9c053bf8cf7f2d7c5c4"},
- {file = "ujson-5.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f91719c6abafe429c1a144cfe27883eace9fb1c09a9c5ef1bcb3ae80a3076a4e"},
- {file = "ujson-5.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1c0991c4fe256f5fdb19758f7eac7f47caac29a6c57d0de16a19048eb86bad"},
- {file = "ujson-5.9.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a8ea0f55a1396708e564595aaa6696c0d8af532340f477162ff6927ecc46e21"},
- {file = "ujson-5.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:07e0cfdde5fd91f54cd2d7ffb3482c8ff1bf558abf32a8b953a5d169575ae1cd"},
- {file = "ujson-5.9.0.tar.gz", hash = "sha256:89cc92e73d5501b8a7f48575eeb14ad27156ad092c2e9fc7e3cf949f07e75532"},
+ {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"},
+ {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"},
+ {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"},
+ {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"},
+ {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"},
+ {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"},
+ {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"},
+ {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"},
+ {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"},
+ {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"},
+ {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"},
+ {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"},
+ {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"},
+ {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"},
+ {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"},
+ {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"},
+ {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"},
+ {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"},
+ {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"},
+ {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"},
+ {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"},
+ {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"},
+ {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"},
+ {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"},
+ {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"},
+ {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"},
+ {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"},
+ {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"},
+ {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"},
+ {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"},
+ {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"},
+ {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"},
+ {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"},
+ {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"},
+ {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"},
+ {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"},
+ {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"},
+ {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"},
+ {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"},
+ {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"},
+ {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"},
+ {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"},
+ {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"},
+ {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"},
+ {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"},
+ {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"},
+ {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"},
+ {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"},
+ {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"},
+ {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"},
+ {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"},
+ {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"},
+ {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"},
+ {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"},
+ {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"},
+ {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"},
+ {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"},
+ {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"},
+ {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"},
+ {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"},
+ {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"},
+ {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"},
+ {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"},
+ {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"},
]
[[package]]
@@ -3734,4 +3747,4 @@ validation = ["fastjsonschema"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.8,<4.0.0"
-content-hash = "dc26b0353ea42f5f579393d41512d0fcbbfc781b729f397963a6b9ab41a93a73"
+content-hash = "2c9a768a679f3ec1e76d83d1c8760b862ee6b49844691fb7d20ba60aaa529e68"
diff --git a/pyproject.toml b/pyproject.toml
index 45764b3d415..c5b39d42a41 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -63,14 +63,14 @@ bandit = "^1.7.8"
radon = "^6.0.1"
xenon = "^0.9.1"
mkdocs-git-revision-date-plugin = "^0.3.2"
-mike = "^2.1.0"
+mike = "^2.1.1"
pytest-xdist = "^3.6.1"
-aws-cdk-lib = "^2.140.0"
+aws-cdk-lib = "^2.141.0"
"aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0"
"aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0"
"aws-cdk.aws-apigatewayv2-authorizers-alpha" = "^2.38.1-alpha.0"
-"aws-cdk.aws-lambda-python-alpha" = "^2.139.1a0"
-"cdklabs.generative-ai-cdk-constructs" = "^0.1.134"
+"aws-cdk.aws-lambda-python-alpha" = "^2.141.0a0"
+"cdklabs.generative-ai-cdk-constructs" = "^0.1.148"
pytest-benchmark = "^4.0.0"
mypy-boto3-appconfig = "^1.34.58"
mypy-boto3-cloudformation = "^1.34.84"
@@ -80,11 +80,11 @@ mypy-boto3-lambda = "^1.34.77"
mypy-boto3-logs = "^1.34.66"
mypy-boto3-secretsmanager = "^1.34.72"
mypy-boto3-ssm = "^1.34.91"
-mypy-boto3-s3 = "^1.34.91"
+mypy-boto3-s3 = "^1.34.105"
mypy-boto3-xray = "^1.34.0"
types-requests = "^2.31.0"
typing-extensions = "^4.6.2"
-mkdocs-material = "^9.5.20"
+mkdocs-material = "^9.5.22"
filelock = "^3.14.0"
checksumdir = "^1.2.0"
mypy-boto3-appconfigdata = "^1.34.24"
@@ -110,12 +110,12 @@ datadog = ["datadog-lambda"]
datamasking = ["aws-encryption-sdk", "jsonpath-ng"]
[tool.poetry.group.dev.dependencies]
-cfn-lint = "0.87.0"
+cfn-lint = "0.87.2"
mypy = "^1.1.1"
types-python-dateutil = "^2.8.19.6"
httpx = ">=0.23.3,<0.28.0"
sentry-sdk = ">=1.22.2,<3.0.0"
-ruff = ">=0.0.272,<0.4.3"
+ruff = ">=0.0.272,<0.4.5"
retry2 = "^0.9.5"
pytest-socket = ">=0.6,<0.8"
types-redis = "^4.6.0.7"
@@ -129,6 +129,7 @@ omit = [
"aws_lambda_powertools/exceptions/*",
"aws_lambda_powertools/utilities/parser/types.py",
"aws_lambda_powertools/utilities/jmespath_utils/envelopes.py",
+ "aws_lambda_powertools/metrics/metric.py" # barrel import (export-only)
]
branch = true
diff --git a/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json b/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json
index af52ee2fef0..7c0995338a8 100644
--- a/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json
+++ b/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json
@@ -16,8 +16,6 @@
},
"object": {
"key": "IMG_m7fzo3.jpg",
- "size": 184662,
- "etag": "4e68adba0abe2dc8653dc3354e14c01d",
"sequencer": "006408CAD69598B05E"
},
"request-id": "0BH729840619AG5K",
@@ -26,4 +24,4 @@
"reason": "DeleteObject",
"deletion-type": "Delete Marker Created"
}
-}
\ No newline at end of file
+}
diff --git a/tests/functional/event_handler/test_api_gateway.py b/tests/functional/event_handler/test_api_gateway.py
index f2d48d925f4..039c469d031 100644
--- a/tests/functional/event_handler/test_api_gateway.py
+++ b/tests/functional/event_handler/test_api_gateway.py
@@ -292,12 +292,16 @@ def delete_func():
def patch_func():
raise RuntimeError()
+ @app.head("/no_matching_head")
+ def head_func():
+ raise RuntimeError()
+
def handler(event, context):
return app.resolve(event, context)
# Also check the route configurations
routes = app._static_routes
- assert len(routes) == 5
+ assert len(routes) == 6
for route in routes:
if route.func == get_func:
assert route.method == "GET"
@@ -309,6 +313,8 @@ def handler(event, context):
assert route.method == "DELETE"
elif route.func == patch_func:
assert route.method == "PATCH"
+ elif route.func == head_func:
+ assert route.method == "HEAD"
# WHEN calling the handler
# THEN return a 404
diff --git a/tests/functional/event_handler/test_openapi_swagger.py b/tests/functional/event_handler/test_openapi_swagger.py
index 11ec0cf24da..a8d9326efcf 100644
--- a/tests/functional/event_handler/test_openapi_swagger.py
+++ b/tests/functional/event_handler/test_openapi_swagger.py
@@ -118,6 +118,18 @@ def test_openapi_swagger_with_rest_api_stage():
assert "ui.specActions.updateUrl('/prod/swagger?format=json')" in result["body"]
+def test_openapi_swagger_with_persist_authorization():
+ app = APIGatewayRestResolver(enable_validation=True)
+ app.enable_swagger(persist_authorization=True)
+
+ event = load_event("apiGatewayProxyEvent.json")
+ event["path"] = "/swagger"
+
+ result = app(event, {})
+ assert result["statusCode"] == 200
+ assert "persistAuthorization: true" in result["body"]
+
+
def test_openapi_swagger_oauth2_without_powertools_dev():
with pytest.raises(ValueError) as exc:
OAuth2Config(app_name="OAuth2 app", client_id="client_id", client_secret="verysecret")
diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py
index 7aa4037cb9c..b59ce604d98 100644
--- a/tests/functional/test_logger.py
+++ b/tests/functional/test_logger.py
@@ -17,7 +17,7 @@
from aws_lambda_powertools import Logger, Tracer, set_package_logger_handler
from aws_lambda_powertools.logging import correlation_paths
-from aws_lambda_powertools.logging.exceptions import InvalidLoggerSamplingRateError
+from aws_lambda_powertools.logging.exceptions import InvalidLoggerSamplingRateError, OrphanedChildLoggerError
from aws_lambda_powertools.logging.formatter import (
BasePowertoolsFormatter,
LambdaPowertoolsFormatter,
@@ -1176,3 +1176,63 @@ def test_logger_json_unicode(stdout, service_name):
assert log["message"] == non_ascii_chars
assert log[japanese_field] == japanese_string
+
+
+def test_logger_registered_handler_is_custom_handler(service_name):
+ # GIVEN a library or environment pre-setup a logger for us using the same name (see #4277)
+ class ForeignHandler(logging.StreamHandler): ...
+
+ foreign_handler = ForeignHandler()
+ logging.getLogger(service_name).addHandler(foreign_handler)
+
+ # WHEN Logger init with a custom handler
+ custom_handler = logging.StreamHandler()
+ logger = Logger(service=service_name, logger_handler=custom_handler)
+
+ # THEN registered handler should always return what we provided
+ assert logger.registered_handler is not foreign_handler
+ assert logger.registered_handler is custom_handler
+ assert logger.logger_handler is custom_handler
+ assert logger.handlers == [foreign_handler, custom_handler]
+
+
+def test_child_logger_registered_handler_is_custom_handler(service_name):
+ # GIVEN
+ class ForeignHandler(logging.StreamHandler): ...
+
+ foreign_handler = ForeignHandler()
+ logging.getLogger(service_name).addHandler(foreign_handler)
+
+ custom_handler = logging.StreamHandler()
+ custom_handler.name = "CUSTOM HANDLER"
+ parent = Logger(service=service_name, logger_handler=custom_handler)
+
+ # WHEN a child Logger init
+ child = Logger(service=service_name, child=True)
+
+ # THEN child registered handler should always return what we provided in the parent
+ assert child.registered_handler is not foreign_handler
+ assert child.registered_handler is custom_handler
+ assert child.registered_handler is parent.registered_handler
+
+
+def test_logger_handler_is_created_despite_env_pre_setup(service_name):
+ # GIVEN a library or environment pre-setup a logger for us using the same name
+ environment_handler = logging.StreamHandler()
+ logging.getLogger(service_name).addHandler(environment_handler)
+
+ # WHEN Logger init without a custom handler
+ logger = Logger(service=service_name)
+
+ # THEN registered handler should be Powertools default handler, not env
+ assert logger.registered_handler is not environment_handler
+
+
+def test_child_logger_append_keys_before_parent(stdout, service_name):
+ # GIVEN a child Logger is initialized before its/without parent
+ child = Logger(stream=stdout, service=service_name, child=True)
+
+ # WHEN a child Logger appends a key
+ # THEN it will raise an AttributeError
+ with pytest.raises(OrphanedChildLoggerError):
+ child.append_keys(customer_id="value")
diff --git a/tests/unit/data_classes/test_api_gateway_proxy_event.py b/tests/unit/data_classes/test_api_gateway_proxy_event.py
index 7d464372135..d86e4b5e19b 100644
--- a/tests/unit/data_classes/test_api_gateway_proxy_event.py
+++ b/tests/unit/data_classes/test_api_gateway_proxy_event.py
@@ -89,8 +89,8 @@ def test_api_gateway_proxy_event():
assert request_context.api_id == request_context_raw["apiId"]
authorizer = request_context.authorizer
- assert authorizer.claims is None
- assert authorizer.scopes is None
+ assert authorizer.claims == {}
+ assert authorizer.scopes == []
assert request_context.domain_name == request_context_raw["domainName"]
assert request_context.domain_prefix == request_context_raw["domainPrefix"]
@@ -144,8 +144,8 @@ def test_api_gateway_proxy_event_with_principal_id():
request_context = parsed_event.request_context
authorizer = request_context.authorizer
- assert authorizer.claims is None
- assert authorizer.scopes is None
+ assert authorizer.claims == {}
+ assert authorizer.scopes == []
assert authorizer.principal_id == raw_event["requestContext"]["authorizer"]["principalId"]
assert authorizer.integration_latency == raw_event["requestContext"]["authorizer"]["integrationLatency"]
assert authorizer.get("integrationStatus", "failed") == "failed"
diff --git a/tests/unit/data_classes/test_lambda_function_url.py b/tests/unit/data_classes/test_lambda_function_url.py
index b7e8003d6c7..f8ce71b1543 100644
--- a/tests/unit/data_classes/test_lambda_function_url.py
+++ b/tests/unit/data_classes/test_lambda_function_url.py
@@ -1,4 +1,5 @@
from aws_lambda_powertools.utilities.data_classes import LambdaFunctionUrlEvent
+from aws_lambda_powertools.utilities.data_classes.api_gateway_proxy_event import RequestContextV2Authorizer
from tests.functional.utils import load_event
@@ -47,7 +48,7 @@ def test_lambda_function_url_event():
assert http.source_ip == http_raw["sourceIp"]
assert http.user_agent == http_raw["userAgent"]
- assert request_context.authorizer is None
+ assert isinstance(request_context.authorizer, RequestContextV2Authorizer)
def test_lambda_function_url_event_iam():
@@ -102,9 +103,9 @@ def test_lambda_function_url_event_iam():
authorizer = request_context.authorizer
assert authorizer is not None
- assert authorizer.jwt_claim is None
- assert authorizer.jwt_scopes is None
- assert authorizer.get_lambda is None
+ assert authorizer.jwt_claim == {}
+ assert authorizer.jwt_scopes == []
+ assert authorizer.get_lambda == {}
iam = authorizer.iam
iam_raw = raw_event["requestContext"]["authorizer"]["iam"]
@@ -112,9 +113,9 @@ def test_lambda_function_url_event_iam():
assert iam.access_key == iam_raw["accessKey"]
assert iam.account_id == iam_raw["accountId"]
assert iam.caller_id == iam_raw["callerId"]
- assert iam.cognito_amr is None
- assert iam.cognito_identity_id is None
- assert iam.cognito_identity_pool_id is None
- assert iam.principal_org_id is None
+ assert iam.cognito_amr == []
+ assert iam.cognito_identity_id == ""
+ assert iam.cognito_identity_pool_id == ""
+ assert iam.principal_org_id == ""
assert iam.user_id == iam_raw["userId"]
assert iam.user_arn == iam_raw["userArn"]
diff --git a/tests/unit/data_classes/test_s3_eventbridge_notification.py b/tests/unit/data_classes/test_s3_eventbridge_notification.py
index 391c3fa1788..ae27ad2965f 100644
--- a/tests/unit/data_classes/test_s3_eventbridge_notification.py
+++ b/tests/unit/data_classes/test_s3_eventbridge_notification.py
@@ -26,10 +26,10 @@ def test_s3_eventbridge_notification_detail_parsed(raw_event: Dict):
assert parsed_event.detail.deletion_type == raw_event["detail"].get("deletion-type")
assert parsed_event.detail.destination_access_tier == raw_event["detail"].get("destination-access-tier")
assert parsed_event.detail.destination_storage_class == raw_event["detail"].get("destination-storage-class")
- assert parsed_event.detail.object.etag == raw_event["detail"]["object"]["etag"]
+ assert parsed_event.detail.object.etag == raw_event["detail"]["object"].get("etag", "")
assert parsed_event.detail.object.key == raw_event["detail"]["object"]["key"]
assert parsed_event.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"]
- assert parsed_event.detail.object.size == raw_event["detail"]["object"]["size"]
+ assert parsed_event.detail.object.size == raw_event["detail"]["object"].get("size")
assert parsed_event.detail.reason == raw_event["detail"].get("reason")
assert parsed_event.detail.version == raw_event["detail"].get("version")
assert parsed_event.detail.request_id == raw_event["detail"]["request-id"]
diff --git a/tests/unit/parser/test_s3_notification.py b/tests/unit/parser/test_s3_notification.py
index c77c70095a3..ca83851d06c 100644
--- a/tests/unit/parser/test_s3_notification.py
+++ b/tests/unit/parser/test_s3_notification.py
@@ -52,8 +52,8 @@ def test_s3_eventbridge_notification_object_deleted_event():
assert model.detail.version == raw_event["detail"]["version"]
assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"]
assert model.detail.object.key == raw_event["detail"]["object"]["key"]
- assert model.detail.object.size == raw_event["detail"]["object"]["size"]
- assert model.detail.object.etag == raw_event["detail"]["object"]["etag"]
+ assert model.detail.object.size == raw_event["detail"]["object"].get("size")
+ assert model.detail.object.etag == raw_event["detail"]["object"].get("etag", "")
assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"]
assert model.detail.request_id == raw_event["detail"]["request-id"]
assert model.detail.requester == raw_event["detail"]["requester"]