? Which setting do you want to update? Lambda layers configuration
? Do you want to enable Lambda layers for this function? Yes
-? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33
+? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37
? Do you want to edit the local lambda function now? No
diff --git a/examples/homepage/install/x86_64/cdk_x86.py b/examples/homepage/install/x86_64/cdk_x86.py
index 30d82a497dd..1b09ee48ce4 100644
--- a/examples/homepage/install/x86_64/cdk_x86.py
+++ b/examples/homepage/install/x86_64/cdk_x86.py
@@ -9,7 +9,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn(
self,
id="lambda-powertools",
- layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33",
+ layer_version_arn=f"arn:aws:lambda:{Aws.REGION}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37",
)
aws_lambda.Function(
self,
diff --git a/examples/homepage/install/x86_64/pulumi_x86.py b/examples/homepage/install/x86_64/pulumi_x86.py
index 1130c67b644..b74df328c0d 100644
--- a/examples/homepage/install/x86_64/pulumi_x86.py
+++ b/examples/homepage/install/x86_64/pulumi_x86.py
@@ -22,7 +22,7 @@
pulumi.Output.concat(
"arn:aws:lambda:",
aws.get_region_output().name,
- ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33",
+ ":017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37",
),
],
tracing_config={"mode": "Active"},
diff --git a/examples/homepage/install/x86_64/sam.yaml b/examples/homepage/install/x86_64/sam.yaml
index d6beb66ea52..85cb40ad532 100644
--- a/examples/homepage/install/x86_64/sam.yaml
+++ b/examples/homepage/install/x86_64/sam.yaml
@@ -8,4 +8,4 @@ Resources:
Runtime: python3.12
Handler: app.lambda_handler
Layers:
- - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33
+ - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37
diff --git a/examples/homepage/install/x86_64/serverless.yml b/examples/homepage/install/x86_64/serverless.yml
index 56deaf1b0fa..2183bda869c 100644
--- a/examples/homepage/install/x86_64/serverless.yml
+++ b/examples/homepage/install/x86_64/serverless.yml
@@ -10,4 +10,4 @@ functions:
handler: lambda_function.lambda_handler
architecture: arm64
layers:
- - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33
+ - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37
diff --git a/examples/homepage/install/x86_64/terraform.tf b/examples/homepage/install/x86_64/terraform.tf
index 56e73fe45b6..2b9703883bb 100644
--- a/examples/homepage/install/x86_64/terraform.tf
+++ b/examples/homepage/install/x86_64/terraform.tf
@@ -34,7 +34,7 @@ resource "aws_lambda_function" "test_lambda" {
role = aws_iam_role.iam_for_lambda.arn
handler = "index.test"
runtime = "python3.12"
- layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33"]
+ layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37"]
source_code_hash = filebase64sha256("lambda_function_payload.zip")
}
diff --git a/examples/idempotency/src/bring_your_own_persistent_store.py b/examples/idempotency/src/bring_your_own_persistent_store.py
index 83ab27b8c4e..50e3595e94f 100644
--- a/examples/idempotency/src/bring_your_own_persistent_store.py
+++ b/examples/idempotency/src/bring_your_own_persistent_store.py
@@ -1,6 +1,6 @@
import datetime
import logging
-from typing import Any, Dict, Optional
+from typing import Any, Dict
import boto3
from botocore.config import Config
@@ -24,8 +24,8 @@ def __init__(
status_attr: str = "status",
data_attr: str = "data",
validation_key_attr: str = "validation",
- boto_config: Optional[Config] = None,
- boto3_session: Optional[boto3.session.Session] = None,
+ boto_config: Config | None = None,
+ boto3_session: boto3.session.Session | None = None,
):
boto3_session = boto3_session or boto3.session.Session()
self._ddb_resource = boto3_session.resource("dynamodb", config=boto_config)
diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml
index 092fb4166d3..a4c3125c76b 100644
--- a/examples/logger/sam/template.yaml
+++ b/examples/logger/sam/template.yaml
@@ -14,7 +14,7 @@ Globals:
Layers:
# Find the latest Layer version in the official documentation
# https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer
- - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33
+ - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37
Resources:
LoggerLambdaHandlerExample:
diff --git a/examples/logger/src/bring_your_own_formatter_from_scratch.py b/examples/logger/src/bring_your_own_formatter_from_scratch.py
index 425f00b0d28..7bcffa1d0af 100644
--- a/examples/logger/src/bring_your_own_formatter_from_scratch.py
+++ b/examples/logger/src/bring_your_own_formatter_from_scratch.py
@@ -1,13 +1,13 @@
import json
import logging
-from typing import Any, Dict, Iterable, List, Optional
+from typing import Any, Dict, Iterable, List
from aws_lambda_powertools import Logger
from aws_lambda_powertools.logging.formatter import BasePowertoolsFormatter
class CustomFormatter(BasePowertoolsFormatter):
- def __init__(self, log_record_order: Optional[List[str]] = None, *args, **kwargs):
+ def __init__(self, log_record_order: List[str] | None = None, *args, **kwargs):
self.log_record_order = log_record_order or ["level", "location", "message", "timestamp"]
self.log_format = dict.fromkeys(self.log_record_order)
super().__init__(*args, **kwargs)
diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml
index dc7d0258fee..a90e5e0fc1d 100644
--- a/examples/metrics/sam/template.yaml
+++ b/examples/metrics/sam/template.yaml
@@ -16,7 +16,7 @@ Globals:
Layers:
# Find the latest Layer version in the official documentation
# https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer
- - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33
+ - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37
Resources:
CaptureLambdaHandlerExample:
diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml
index d43669484f8..38870c8c88e 100644
--- a/examples/metrics_datadog/sam/template.yaml
+++ b/examples/metrics_datadog/sam/template.yaml
@@ -20,7 +20,7 @@ Globals:
Layers:
# Find the latest Layer version in the official documentation
# https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer
- - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33
+ - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37
# Find the latest Layer version in the Datadog official documentation
# Datadog SDK
diff --git a/examples/streaming/src/assert_transformation_module.py b/examples/streaming/src/assert_transformation_module.py
index eac11abd4af..cc9b1dc4984 100644
--- a/examples/streaming/src/assert_transformation_module.py
+++ b/examples/streaming/src/assert_transformation_module.py
@@ -1,5 +1,5 @@
import io
-from typing import IO, Optional
+from typing import IO
from aws_lambda_powertools.utilities.streaming.transformations import BaseTransform
@@ -9,7 +9,7 @@ def __init__(self, input_stream: IO[bytes], encoding: str):
self.encoding = encoding
self.input_stream = io.TextIOWrapper(input_stream, encoding=encoding)
- def read(self, size: int = -1) -> Optional[bytes]:
+ def read(self, size: int = -1) -> bytes | None:
data = self.input_stream.read(size)
return data.upper().encode(self.encoding)
diff --git a/examples/streaming/src/s3_json_transform.py b/examples/streaming/src/s3_json_transform.py
index 30c31b0f32c..8588498e38b 100644
--- a/examples/streaming/src/s3_json_transform.py
+++ b/examples/streaming/src/s3_json_transform.py
@@ -1,5 +1,5 @@
import io
-from typing import IO, Optional
+from typing import IO
import ijson
@@ -11,10 +11,10 @@ class JsonDeserializer(io.RawIOBase):
def __init__(self, input_stream: IO[bytes]):
self.input = ijson.items(input_stream, "", multiple_values=True)
- def read(self, size: int = -1) -> Optional[bytes]:
+ def read(self, size: int = -1) -> bytes | None:
raise NotImplementedError(f"{__name__} does not implement read")
- def readline(self, size: Optional[int] = None) -> bytes:
+ def readline(self, size: int | None = None) -> bytes:
raise NotImplementedError(f"{__name__} does not implement readline")
def read_object(self) -> dict:
diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml
index 465ac3e2507..82fcc82b2ff 100644
--- a/examples/tracer/sam/template.yaml
+++ b/examples/tracer/sam/template.yaml
@@ -13,7 +13,7 @@ Globals:
Layers:
# Find the latest Layer version in the official documentation
# https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer
- - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:33
+ - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV3-python312-x86_64:37
Resources:
CaptureLambdaHandlerExample:
diff --git a/layer_v3/poetry.lock b/layer_v3/poetry.lock
index 79d0e9ccd06..7c33f06a244 100644
--- a/layer_v3/poetry.lock
+++ b/layer_v3/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand.
[[package]]
name = "attrs"
@@ -14,75 +14,75 @@ files = [
[[package]]
name = "aws-cdk-asset-awscli-v1"
-version = "2.2.242"
+version = "2.2.273"
description = "A library that contains the AWS CLI for use in Lambda Layers"
optional = false
python-versions = "~=3.9"
groups = ["main"]
files = [
- {file = "aws_cdk_asset_awscli_v1-2.2.242-py3-none-any.whl", hash = "sha256:d1001bf56a12f7d1162d4211003d1e8f72a213159465e2d0e1c598cc0ea44aad"},
- {file = "aws_cdk_asset_awscli_v1-2.2.242.tar.gz", hash = "sha256:a957d679a118f4375307ed90b9aed7127c5c1402989438060eae4ab29ab0d13f"},
+ {file = "aws_cdk_asset_awscli_v1-2.2.273-py3-none-any.whl", hash = "sha256:1a0994afa7b48f63b580603be64c7a99d19ed6777bdf81d3c2435d8b43cf0d71"},
+ {file = "aws_cdk_asset_awscli_v1-2.2.273.tar.gz", hash = "sha256:6580dad3416e53712db434f81add6fb4a314e1a80f9c57cc42606df1f64c8e0f"},
]
[package.dependencies]
-jsii = ">=1.112.0,<2.0.0"
+jsii = ">=1.127.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = ">=2.13.3,<4.3.0"
+typeguard = "2.13.3"
[[package]]
name = "aws-cdk-asset-node-proxy-agent-v6"
-version = "2.1.0"
+version = "2.1.2"
description = "@aws-cdk/asset-node-proxy-agent-v6"
optional = false
-python-versions = "~=3.8"
+python-versions = "~=3.9"
groups = ["main"]
files = [
- {file = "aws_cdk.asset_node_proxy_agent_v6-2.1.0-py3-none-any.whl", hash = "sha256:24a388b69a44d03bae6dbf864c4e25ba650d4b61c008b4568b94ffbb9a69e40e"},
- {file = "aws_cdk_asset_node_proxy_agent_v6-2.1.0.tar.gz", hash = "sha256:1f292c0631f86708ba4ee328b3a2b229f7e46ea1c79fbde567ee9eb119c2b0e2"},
+ {file = "aws_cdk_asset_node_proxy_agent_v6-2.1.2-py3-none-any.whl", hash = "sha256:1028bff16fdb87b8c82404e9b48f32ed383429dece84067f47379c4049da5da4"},
+ {file = "aws_cdk_asset_node_proxy_agent_v6-2.1.2.tar.gz", hash = "sha256:1340588dd351dcae37e07188f39075364f73ccde6ed9468c1184b06ada4af665"},
]
[package.dependencies]
-jsii = ">=1.103.1,<2.0.0"
+jsii = ">=1.129.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = ">=2.13.3,<5.0.0"
+typeguard = "2.13.3"
[[package]]
name = "aws-cdk-cloud-assembly-schema"
-version = "48.18.0"
+version = "53.28.0"
description = "Schema for the protocol between CDK framework and CDK CLI"
optional = false
-python-versions = "~=3.9"
+python-versions = "~=3.10"
groups = ["main"]
files = [
- {file = "aws_cdk_cloud_assembly_schema-48.18.0-py3-none-any.whl", hash = "sha256:12b193fde580828d8c4909cfa62e1f83977fe20d0aa448c7e7e353f8e21e1b68"},
- {file = "aws_cdk_cloud_assembly_schema-48.18.0.tar.gz", hash = "sha256:dc8d1bbe09bca45d675fa7d5c59fd7c073ed86865fc97dc985c6a4caf1016b42"},
+ {file = "aws_cdk_cloud_assembly_schema-53.28.0-py3-none-any.whl", hash = "sha256:c5de34f4a0d61eb48574a0264a9567175f601c27b4d053fb24ad1157c4ea0d99"},
+ {file = "aws_cdk_cloud_assembly_schema-53.28.0.tar.gz", hash = "sha256:12e28dc44026e5f062041ba1450a510b1acddcfbe8358f73cfda8df993712d42"},
]
[package.dependencies]
-jsii = ">=1.118.0,<2.0.0"
+jsii = ">=1.131.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = ">=2.13.3,<4.3.0"
+typeguard = "2.13.3"
[[package]]
name = "aws-cdk-lib"
-version = "2.223.0"
+version = "2.253.0"
description = "Version 2 of the AWS Cloud Development Kit library"
optional = false
python-versions = "~=3.9"
groups = ["main"]
files = [
- {file = "aws_cdk_lib-2.223.0-py3-none-any.whl", hash = "sha256:c6070a9449b2ce48987855ce273e65b9b18a134d98110ac86f23a393e1bf0b84"},
- {file = "aws_cdk_lib-2.223.0.tar.gz", hash = "sha256:8d2ea3c2754d1022db19f59e0558a9b23b26317a95b1327c502ca8afd94c5830"},
+ {file = "aws_cdk_lib-2.253.0-py3-none-any.whl", hash = "sha256:58997c8a5af49d5328f5106468581a14235a1356dfe7574bb14656799594a2b5"},
+ {file = "aws_cdk_lib-2.253.0.tar.gz", hash = "sha256:6db33e164f9afd6207698d382579bf62f762f14325f4b6d77643865e92448f20"},
]
[package.dependencies]
-"aws-cdk.asset-awscli-v1" = "2.2.242"
-"aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.0,<3.0.0"
-"aws-cdk.cloud-assembly-schema" = ">=48.6.0,<49.0.0"
-constructs = ">=10.0.0,<11.0.0"
-jsii = ">=1.118.0,<2.0.0"
+"aws-cdk.asset-awscli-v1" = "2.2.273"
+"aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.1,<3.0.0"
+"aws-cdk.cloud-assembly-schema" = ">=53.18.0,<54.0.0"
+constructs = ">=10.5.0,<11.0.0"
+jsii = ">=1.128.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = ">=2.13.3,<4.3.0"
+typeguard = "2.13.3"
[[package]]
name = "boto3"
@@ -166,20 +166,19 @@ files = [
[[package]]
name = "constructs"
-version = "10.4.3"
+version = "10.8.1"
description = "A programming model for software-defined state"
optional = false
-python-versions = "~=3.9"
+python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "constructs-10.4.3-py3-none-any.whl", hash = "sha256:43bbefa1ac1c044577d0b1a30648fe5b49557b8b95de2648186f6b909febf7f9"},
- {file = "constructs-10.4.3.tar.gz", hash = "sha256:bfe3657b0acb62af7aa1fda9a7e338ae5cae84ddf8f84f71125a2a3800d52ea0"},
+ {file = "constructs-10.8.1-py3-none-any.whl", hash = "sha256:f71297db64723889147c82de46dcacaa76b120f856d5b5ac5f65abb22ea88355"},
+ {file = "constructs-10.8.1.tar.gz", hash = "sha256:9f6e4eb1f6b8b1ac8dcbc85457dcbb1e3f9bd93bbeef03154f6cc7fbbba74b06"},
]
[package.dependencies]
-jsii = ">=1.118.0,<2.0.0"
+jsii = ">=1.139.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = ">=2.13.3,<4.3.0"
[[package]]
name = "exceptiongroup"
@@ -200,26 +199,6 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""}
[package.extras]
test = ["pytest (>=6)"]
-[[package]]
-name = "importlib-resources"
-version = "6.5.2"
-description = "Read resources from Python packages"
-optional = false
-python-versions = ">=3.9"
-groups = ["main"]
-files = [
- {file = "importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec"},
- {file = "importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c"},
-]
-
-[package.extras]
-check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""]
-cover = ["pytest-cov"]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-enabler = ["pytest-enabler (>=2.2)"]
-test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "zipp (>=3.17)"]
-type = ["pytest-mypy"]
-
[[package]]
name = "iniconfig"
version = "2.3.0"
@@ -246,23 +225,22 @@ files = [
[[package]]
name = "jsii"
-version = "1.119.0"
+version = "1.139.0"
description = "Python client for jsii runtime"
optional = false
-python-versions = "~=3.9"
+python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "jsii-1.119.0-py3-none-any.whl", hash = "sha256:9203200ed5289ecc6198783513cbd7abef53d4f6eac0046181d647fa56eda6ab"},
- {file = "jsii-1.119.0.tar.gz", hash = "sha256:9f87508908bfa51dd9aac59fdbbeff347ae76377758ea5e5f83f149052211514"},
+ {file = "jsii-1.139.0-py3-none-any.whl", hash = "sha256:11468f767c6da698ed9888a04352850af33ccccfec7656475626caf36fca8bbb"},
+ {file = "jsii-1.139.0.tar.gz", hash = "sha256:163c5d3ec00fd4ec89a33b9097f20a6f27626dd69d6875a8f7cc7577b8021ad0"},
]
[package.dependencies]
-attrs = ">=21.2,<26.0"
-cattrs = ">=1.8,<25.4"
-importlib_resources = ">=5.2.0"
+attrs = ">=21.2,<27.0"
+cattrs = ">=1.8,<27.0"
publication = ">=0.0.3"
python-dateutil = "*"
-typeguard = ">=2.13.3,<4.5.0"
+typeguard = "2.13.3"
typing_extensions = ">=3.8,<5.0"
[[package]]
@@ -372,10 +350,10 @@ files = [
]
[package.dependencies]
-botocore = ">=1.37.4,<2.0a.0"
+botocore = ">=1.37.4,<2.0a0"
[package.extras]
-crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
+crt = ["botocore[crt] (>=1.37.4,<2.0a0)"]
[[package]]
name = "six"
@@ -444,22 +422,19 @@ files = [
[[package]]
name = "typeguard"
-version = "4.2.1"
+version = "2.13.3"
description = "Run-time type checker for Python"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.5.3"
groups = ["main"]
files = [
- {file = "typeguard-4.2.1-py3-none-any.whl", hash = "sha256:7da3bd46e61f03e0852f8d251dcbdc2a336aa495d7daff01e092b55327796eb8"},
- {file = "typeguard-4.2.1.tar.gz", hash = "sha256:c556a1b95948230510070ca53fa0341fb0964611bd05d598d87fb52115d65fee"},
+ {file = "typeguard-2.13.3-py3-none-any.whl", hash = "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1"},
+ {file = "typeguard-2.13.3.tar.gz", hash = "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4"},
]
-[package.dependencies]
-typing-extensions = {version = ">=4.10.0", markers = "python_version < \"3.13\""}
-
[package.extras]
-doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"]
-test = ["coverage[toml] (>=7)", "mypy (>=1.2.0) ; platform_python_implementation != \"PyPy\"", "pytest (>=7)"]
+doc = ["sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
+test = ["mypy ; platform_python_implementation != \"PyPy\"", "pytest", "typing-extensions"]
[[package]]
name = "typing-extensions"
diff --git a/mkdocs.yml b/mkdocs.yml
index 6bea356bac6..265560a55d5 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -33,6 +33,7 @@ nav:
- utilities/data_classes.md
- utilities/parser.md
- utilities/idempotency.md
+ - utilities/circuit_breaker.md
- utilities/data_masking.md
- utilities/feature_flags.md
- utilities/metadata.md
@@ -105,6 +106,12 @@ nav:
- Exceptions: api_doc/feature_flags/exceptions.md
- Feature flags: api_doc/feature_flags/feature_flags.md
- Schema: api_doc/feature_flags/schema.md
+ - Circuit Breaker (alpha):
+ - Circuit Breaker: api_doc/circuit_breaker_alpha/circuit_breaker.md
+ - Config: api_doc/circuit_breaker_alpha/config.md
+ - States: api_doc/circuit_breaker_alpha/states.md
+ - Exceptions: api_doc/circuit_breaker_alpha/exceptions.md
+ - Persistence: api_doc/circuit_breaker_alpha/persistence.md
- Idempotency:
- Base: api_doc/idempotency/base.md
- Config: api_doc/idempotency/config.md
@@ -248,6 +255,7 @@ plugins:
- utilities/data_classes.md
- utilities/parser.md
- utilities/idempotency.md
+ - utilities/circuit_breaker.md
- utilities/data_masking.md
- utilities/feature_flags.md
- utilities/metadata.md
diff --git a/package-lock.json b/package-lock.json
index f0b022384df..cda2d626edd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,13 +8,13 @@
"name": "aws-lambda-powertools-python-e2e",
"version": "1.0.0",
"devDependencies": {
- "aws-cdk": "^2.1126.0"
+ "aws-cdk": "^2.1136.0"
}
},
"node_modules/aws-cdk": {
- "version": "2.1126.0",
- "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1126.0.tgz",
- "integrity": "sha512-uNoocb3vCPiAT3j9+SwL6pn/VVggHWBsgC2XpxyhNvYQYt6cE9BM/149GWwtdcwnLrPjnwW1+CV/5nSSh5dV+w==",
+ "version": "2.1136.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1136.0.tgz",
+ "integrity": "sha512-n6kCL9R9uuvb7WXEwiSs3rYGwnTy9AHHmxOT5Pj5/++E4PYz2bLDXIxzoiOMIj5maoyC52PTe/0GezFV+O0ILQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
diff --git a/package.json b/package.json
index 42de5c30465..d429b6b453c 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,6 @@
"name": "aws-lambda-powertools-python-e2e",
"version": "1.0.0",
"devDependencies": {
- "aws-cdk": "^2.1126.0"
+ "aws-cdk": "^2.1136.0"
}
}
diff --git a/poetry.lock b/poetry.lock
index 1bafb91820d..6234daec8f2 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -29,6 +29,7 @@ markers = {main = "extra == \"valkey\""}
[package.dependencies]
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
idna = ">=2.8"
+trio = {version = ">=0.32.0", optional = true, markers = "python_version >= \"3.10\" and extra == \"trio\""}
typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
[package.extras]
@@ -51,45 +52,69 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"]
[[package]]
name = "ast-serialize"
-version = "0.5.0"
+version = "0.8.0"
description = "Python bindings for mypy AST serialization"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
- {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash = "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c"},
- {file = "ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb"},
- {file = "ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101"},
- {file = "ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a"},
- {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211"},
- {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf"},
- {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9"},
- {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee"},
- {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809"},
- {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43"},
- {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934"},
- {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759"},
- {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887"},
- {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27"},
- {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d"},
- {file = "ast_serialize-0.5.0-cp39-abi3-win32.whl", hash = "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a"},
- {file = "ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash = "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590"},
- {file = "ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642"},
- {file = "ast_serialize-0.5.0.tar.gz", hash = "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6"},
+ {file = "ast_serialize-0.8.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:3d822605fa7bb326ef868d25fafced7fc660fa46d9b90c02ea86d5e2f5d325f7"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:2efa40b068197d5efb62655b43baadb842ed71c4958cccd3e8b86a35726f0119"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:db1b957291bca08c7e72f43a12357b2948e20775d970e3fc3dac0aa3160ab725"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdc0d5b18ff8fb364e87923e47c0a91d0d69dbcaeaa274591f7fd26892cc3a3a"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9da7330f3e235bf7da89b8d39205c6350fc0c08a85379743f2df9fff87d6d980"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3186969ee66a9863b00acc6523ace44c56974eecb348a7ea4b228d9f0b80e19"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40a57b73731be45da4fa41430c4d5dc94a24b3a4faba7b9e069978c0402064ea"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5075b9da3ef807eda752502446dfecea3b381c4900b7e27a5d5f4f899eb39951"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:293cc1c5bfa741f8e3fbe8175b9c07beee487c9a6fdbb25a5acad9f1df2d30a9"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0910c3442a75216dde0f102d854ba2aaa71d2482e0ee213630b9bf29584fba3"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43dd6d596879bb1cb8a12cc9dae7bb10090a39a35883026c24f82488a195619a"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8c9d537f59e936392cfd3597789d1390304dd659efc3c486ce7f40fb6b8a9f53"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f0190a33d7f97c65e9069f7a7f40499eea6b5cbe260c558378109caf20ce934b"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:77308ae6c5cf5264cc0f01a7c556ec77a9e68eb1f61b093534d698139fdc3b14"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8d53a23f27e1ed3a36b2d26fd2a1a6228c8e85a1ed62ff7cdb44bd610769f20a"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa5e7cb08f96fed9121f77b224151e41caf88feab9d652bb46c78202b6fbeda"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-win32.whl", hash = "sha256:fa70ed4dea0bb18b30a1789c77baa701d0ef30c474f2ccabdea61e25623a8827"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d8b3c8eee4c1baef9d4e84d2a59a805501617127be42615cb48970b15b0892b6"},
+ {file = "ast_serialize-0.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:ac4f0a83c55a9b782f79ad55a5247b7db123c1db405959791c2ef886e9710c9f"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:86b8a1e6d90467345356098b040150e82fbc26d24a7a202224b13dc1f6264ca0"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:39e92ff8e8cb45947fe9007174b2950e1fb098e6abd00266a13cd3bcf6675068"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85d8d18db5b2dfcb3b7e38a4d600ca35504c0ed8a6f75cd1c811e4ffe248a15"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9830ff7e764f74d9eefb01170c61a9f0fd2c027dac5fcb72e064decd57d56371"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6479d9722a4cd21b578f5478074c41e6169f04811996ec881655560f703a5bba"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a63bed264e818cd83eec11feed0f50aa162542b91132ef58afebc857182763a5"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d187197d234aa45d6cfa2b096be5f666e8cc2e7eb3722d0ab8926293cf5720c"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:2d39a56282cfcc0d8eeea37267c754be59c98d48505c23b1dae5c6011f3813dd"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7cc5f10386994c0f4844f1e6d6a97127e9b478660eb6dec2b257644f0acab64"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6102f2f985c2e542be85cd857678ec9356fefa792b93cadfadd31139f5696f27"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:3a8660fe66667b76a6e9dccd1d33e66b229fde3b308db991c041609226c005b6"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:e7266307e5fba39836edb79def8608887af48820508bff3c5f2941e1e04d1534"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca7e6fd1ad845d1cc649dc2ecd499db2f8f46af5bf8da7b70dd858774cc038b"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:2880350b13d3eae69a0d70bc1fb6c9bfaca4dbd0e20ba8cd1aa483080b56ff06"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:ab0f9a59f7d63d0d441b56b9a818b273705264352d5115cfee12e940e816d958"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:0485a25ef519c62e749ee3c1ad8070e591b380d67226349eb5a70b228dc1ac4a"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:bd84d60bca7079e741be4ac5dbe237751a59d7f6f9f0126b11880d63822cbe16"},
+ {file = "ast_serialize-0.8.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:057769b5921336eb2d9124f2a731b42ed05ffdac559b840dbdf6f3937cf153dc"},
+ {file = "ast_serialize-0.8.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:a02cbed7d8bfdcdee88edaac12bd50d53d9953aaa2e1852ef078625be5f1c0b5"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e1bd223df0f6c96b396975fa604cb33bce53d9b4a0185490be4c4a289f7c9c87"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ddd3b61f45c132da66c5476b281891e08c1fd87fbdabe8a6973e1622efc85f06"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f9caa63fad8241257ae401b5ff0a64026c6adb36b8e86cbe8782d9ea505daf6"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3926fa117b5e65019853a2969966d11c7175af377a3425991f3fe73784412405"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:485f1113af805e9e170b95ef993ca3fbd4f89c04bab25c58b4fc632d854801ab"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccebbed24f1281062d5852353c72c47502955926cfcb8345ffb3a44d87ff3d3"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:252f883290d1cdb728eb7fe1d9a7221b88af5a329aae0bc91ddee4dafb820331"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:96abc072ad29db8d02194afd47d68987322622787daceae82398d7b69f3ba2e6"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9118ad3e369727060b2696fc4078f250ecffca4248ba87f537f55cea9f9dce06"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f359df4bd921918af8bebd142a376c77511d7151cc8ba852760b587b5a4a54f3"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:e94f9121d13fa36cbf21314783c77d05ae3a0868decd18cf5233fdcc6de49ac8"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:54f95b486018d262bcb387a9afd96f0da74508b442762b80c769454a6fbb3ee3"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c38b915511e32bc718c49dbce98ff9af36bac0ad6a604f58000cd5e3aecdba7"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:9a2ef9cf12f2de4f1028c42c1dd7d775255e0fb3e5bb48896c97e35ef52366fe"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f18048fe9f6dd266bd577cdec48bdcecb74faaa01fe941324435483b013ed2a"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-win32.whl", hash = "sha256:31883542dd6c94d178f5db3d32fbd69c5eb88b3a7c018e7ac8cc0c45195ddbed"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:861794565b06337005c1447ef23103a3d5a627d08bdc827870d00d0b28ef5f51"},
+ {file = "ast_serialize-0.8.0-cp39-abi3-win_arm64.whl", hash = "sha256:b2a5978662fd4db463dfb4b974d2b10ac6430b98f5333aabc7051909df3561d0"},
+ {file = "ast_serialize-0.8.0.tar.gz", hash = "sha256:6c37c43e4004dfb42d321ddedc569dc17ff4259296f3af577c9ea46a809bc010"},
]
[[package]]
@@ -116,7 +141,7 @@ files = [
{file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"},
{file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"},
]
-markers = {main = "extra == \"all\" or extra == \"datamasking\""}
+markers = {main = "extra == \"valkey\" or extra == \"all\" or extra == \"datamasking\""}
[[package]]
name = "avro"
@@ -137,20 +162,19 @@ zstandard = ["zstandard"]
[[package]]
name = "aws-cdk-asset-awscli-v1"
-version = "2.2.282"
+version = "2.2.292"
description = "A library that contains the AWS CLI for use in Lambda Layers"
optional = false
-python-versions = "~=3.10"
+python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "aws_cdk_asset_awscli_v1-2.2.282-py3-none-any.whl", hash = "sha256:24139da0eb1be59f8cfda22c6343d51e8d50bb89b5052b049cfab92683de7790"},
- {file = "aws_cdk_asset_awscli_v1-2.2.282.tar.gz", hash = "sha256:f86e61653927f77fb235b5ec148c955c610117430c869d182c8b20f7e07e2df2"},
+ {file = "aws_cdk_asset_awscli_v1-2.2.292-py3-none-any.whl", hash = "sha256:01cfb33e2913df2d63448b0954ea4ed1bcb1d064514b4b7aa266eda915e8ebfc"},
+ {file = "aws_cdk_asset_awscli_v1-2.2.292.tar.gz", hash = "sha256:06da203eeaecbbbf5f1ecd3b12140104e6a59b6a7f6182cfbda5c5deda4b6344"},
]
[package.dependencies]
-jsii = ">=1.130.0,<2.0.0"
+jsii = ">=1.139.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = "2.13.3"
[[package]]
name = "aws-cdk-asset-node-proxy-agent-v6"
@@ -249,72 +273,69 @@ typeguard = ">=2.13.3,<2.14.0"
[[package]]
name = "aws-cdk-aws-lambda-python-alpha"
-version = "2.259.0a0"
+version = "2.266.0a0"
description = "The CDK Construct Library for AWS Lambda in Python"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "aws_cdk_aws_lambda_python_alpha-2.259.0a0-py3-none-any.whl", hash = "sha256:6ab839026a26fd9e9c7d0df04e08dbbfe32e9a22d89726175e165e2b5da268f2"},
- {file = "aws_cdk_aws_lambda_python_alpha-2.259.0a0.tar.gz", hash = "sha256:5d061cb7ba7a76e5699e7a0cc1aaa2ba329d5242ddf945a79eda717c287d2e09"},
+ {file = "aws_cdk_aws_lambda_python_alpha-2.266.0a0-py3-none-any.whl", hash = "sha256:be7c34c7296d9e6c478df9065510b2013a52d27629be6d90b4c9221043e71077"},
+ {file = "aws_cdk_aws_lambda_python_alpha-2.266.0a0.tar.gz", hash = "sha256:eb7bb2890c722dc7d49851c61f8df8f7dd339a9135216e8f007c5c5be1b05cdb"},
]
[package.dependencies]
-aws-cdk-lib = ">=2.259.0,<3.0.0"
+aws-cdk-lib = ">=2.266.0,<3.0.0"
constructs = ">=10.5.0,<11.0.0"
-jsii = ">=1.133.0,<2.0.0"
+jsii = ">=1.139.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = "2.13.3"
[[package]]
name = "aws-cdk-cloud-assembly-schema"
-version = "54.2.0"
+version = "54.21.0"
description = "Schema for the protocol between CDK framework and CDK CLI"
optional = false
-python-versions = "~=3.10"
+python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "aws_cdk_cloud_assembly_schema-54.2.0-py3-none-any.whl", hash = "sha256:a7038bffa1aaf3365b72147987396bcf0b9951c3b53b2eebfc181b7cb4227067"},
- {file = "aws_cdk_cloud_assembly_schema-54.2.0.tar.gz", hash = "sha256:2e3a05fca6a28f49811b7b011fce12b03dd0adb15c37a0ad2d1b16d8d66fe95a"},
+ {file = "aws_cdk_cloud_assembly_schema-54.21.0-py3-none-any.whl", hash = "sha256:e5951260bb7ca20956240a96f90aa423c33467a5a37b40e338dd4e2c9c02fb0c"},
+ {file = "aws_cdk_cloud_assembly_schema-54.21.0.tar.gz", hash = "sha256:bd66b07ab1a1570801219a3ad3e438a6853db284771cff7aa5e18935b2b3dd0c"},
]
[package.dependencies]
-jsii = ">=1.132.0,<2.0.0"
+jsii = ">=1.139.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = "2.13.3"
[[package]]
name = "aws-cdk-lib"
-version = "2.259.0"
+version = "2.267.0"
description = "Version 2 of the AWS Cloud Development Kit library"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "aws_cdk_lib-2.259.0-py3-none-any.whl", hash = "sha256:4ea916f3673bd372d5e5a7bf84eb5bfb20c171b74a02c14ec8af2620441457a3"},
- {file = "aws_cdk_lib-2.259.0.tar.gz", hash = "sha256:5481f23b51dd771146c747d54e5d442f25a346a78c60077bd21b7d968af898e7"},
+ {file = "aws_cdk_lib-2.267.0-py3-none-any.whl", hash = "sha256:83e269742e10069b5df80b2b99ec55ffb097f31cbf62317b6cf44eb63d4a9430"},
+ {file = "aws_cdk_lib-2.267.0.tar.gz", hash = "sha256:2778f1befdda7401ad064d60f5442858c2dad2a1a87591264ca6f17da6ebd4a2"},
]
[package.dependencies]
-"aws-cdk.asset-awscli-v1" = "2.2.282"
+"aws-cdk.asset-awscli-v1" = "2.2.292"
"aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.2,<3.0.0"
-"aws-cdk.cloud-assembly-schema" = ">=54.0.0,<55.0.0"
+"aws-cdk.cloud-assembly-schema" = ">=54.11.0,<55.0.0"
constructs = ">=10.5.0,<11.0.0"
-jsii = ">=1.133.0,<2.0.0"
+jsii = ">=1.139.0,<2.0.0"
publication = ">=0.0.3"
-typeguard = "2.13.3"
[[package]]
name = "aws-encryption-sdk"
-version = "4.0.5"
+version = "4.0.6"
description = "AWS Encryption SDK implementation for Python"
optional = true
python-versions = "*"
groups = ["main"]
markers = "extra == \"all\" or extra == \"datamasking\""
files = [
- {file = "aws_encryption_sdk-4.0.5-py2.py3-none-any.whl", hash = "sha256:3e6b76afb94c28730487dee71fa1bfc217fcdbab061733c220ff87b88630e40e"},
- {file = "aws_encryption_sdk-4.0.5.tar.gz", hash = "sha256:a36136181a4d63cbf0d7347d29786c80a4d74a07c79c88a8799e27b27a9c3fc1"},
+ {file = "aws_encryption_sdk-4.0.6-py2.py3-none-any.whl", hash = "sha256:35f62f775a8d4a6cb677a4a8927bb19acb3da35308405213f668396ee6298ad4"},
+ {file = "aws_encryption_sdk-4.0.6.tar.gz", hash = "sha256:ec03bfa2df64ef21417bd6ff749bb63e84149586a4f7fbe528ec6b443326ea9e"},
]
[package.dependencies]
@@ -498,14 +519,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "boto3-stubs"
-version = "1.43.24"
-description = "Type annotations for boto3 1.43.24 generated with mypy-boto3-builder 8.12.0"
+version = "1.43.36"
+description = "Type annotations for boto3 1.43.36 generated with mypy-boto3-builder 8.12.0"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
- {file = "boto3_stubs-1.43.24-py3-none-any.whl", hash = "sha256:d5d8c00769d46970efedbbe24fb99c26568dfa4cc12a9acb2ddba8667160dcc1"},
- {file = "boto3_stubs-1.43.24.tar.gz", hash = "sha256:1b60837a40179f668a6b2f5206fd67acb4bf636aff2cd401f84fcf651cb4c988"},
+ {file = "boto3_stubs-1.43.36-py3-none-any.whl", hash = "sha256:e89e48f937710919ef2d36623a8a98c3768568ca6fb9726f7b2369f681ec5745"},
+ {file = "boto3_stubs-1.43.36.tar.gz", hash = "sha256:35bdcef0f3e5b6bb1f1f6e61ab813fdde0d739508512450b6ea12509b516cdcb"},
]
[package.dependencies]
@@ -530,7 +551,7 @@ account = ["mypy-boto3-account (>=1.43.0,<1.44.0)"]
acm = ["mypy-boto3-acm (>=1.43.0,<1.44.0)"]
acm-pca = ["mypy-boto3-acm-pca (>=1.43.0,<1.44.0)"]
aiops = ["mypy-boto3-aiops (>=1.43.0,<1.44.0)"]
-all = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)", "mypy-boto3-account (>=1.43.0,<1.44.0)", "mypy-boto3-acm (>=1.43.0,<1.44.0)", "mypy-boto3-acm-pca (>=1.43.0,<1.44.0)", "mypy-boto3-aiops (>=1.43.0,<1.44.0)", "mypy-boto3-amp (>=1.43.0,<1.44.0)", "mypy-boto3-amplify (>=1.43.0,<1.44.0)", "mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)", "mypy-boto3-amplifyuibuilder (>=1.43.0,<1.44.0)", "mypy-boto3-apigateway (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewaymanagementapi (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewayv2 (>=1.43.0,<1.44.0)", "mypy-boto3-appconfig (>=1.43.0,<1.44.0)", "mypy-boto3-appconfigdata (>=1.43.0,<1.44.0)", "mypy-boto3-appfabric (>=1.43.0,<1.44.0)", "mypy-boto3-appflow (>=1.43.0,<1.44.0)", "mypy-boto3-appintegrations (>=1.43.0,<1.44.0)", "mypy-boto3-application-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-application-insights (>=1.43.0,<1.44.0)", "mypy-boto3-application-signals (>=1.43.0,<1.44.0)", "mypy-boto3-applicationcostprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-appmesh (>=1.43.0,<1.44.0)", "mypy-boto3-apprunner (>=1.43.0,<1.44.0)", "mypy-boto3-appstream (>=1.43.0,<1.44.0)", "mypy-boto3-appsync (>=1.43.0,<1.44.0)", "mypy-boto3-arc-region-switch (>=1.43.0,<1.44.0)", "mypy-boto3-arc-zonal-shift (>=1.43.0,<1.44.0)", "mypy-boto3-artifact (>=1.43.0,<1.44.0)", "mypy-boto3-athena (>=1.43.0,<1.44.0)", "mypy-boto3-auditmanager (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling-plans (>=1.43.0,<1.44.0)", "mypy-boto3-b2bi (>=1.43.0,<1.44.0)", "mypy-boto3-backup (>=1.43.0,<1.44.0)", "mypy-boto3-backup-gateway (>=1.43.0,<1.44.0)", "mypy-boto3-backupsearch (>=1.43.0,<1.44.0)", "mypy-boto3-batch (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-dashboards (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-data-exports (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-pricing-calculator (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-recommended-actions (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore-control (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-billing (>=1.43.0,<1.44.0)", "mypy-boto3-billingconductor (>=1.43.0,<1.44.0)", "mypy-boto3-braket (>=1.43.0,<1.44.0)", "mypy-boto3-budgets (>=1.43.0,<1.44.0)", "mypy-boto3-ce (>=1.43.0,<1.44.0)", "mypy-boto3-chatbot (>=1.43.0,<1.44.0)", "mypy-boto3-chime (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-identity (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-meetings (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-messaging (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-voice (>=1.43.0,<1.44.0)", "mypy-boto3-cleanrooms (>=1.43.0,<1.44.0)", "mypy-boto3-cleanroomsml (>=1.43.0,<1.44.0)", "mypy-boto3-cloud9 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudcontrol (>=1.43.0,<1.44.0)", "mypy-boto3-clouddirectory (>=1.43.0,<1.44.0)", "mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsm (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsmv2 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearch (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)", "mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)", "mypy-boto3-codeartifact (>=1.43.0,<1.44.0)", "mypy-boto3-codebuild (>=1.43.0,<1.44.0)", "mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)", "mypy-boto3-codecommit (>=1.43.0,<1.44.0)", "mypy-boto3-codeconnections (>=1.43.0,<1.44.0)", "mypy-boto3-codedeploy (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-reviewer (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-security (>=1.43.0,<1.44.0)", "mypy-boto3-codeguruprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-codepipeline (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-connections (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-identity (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-idp (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-sync (>=1.43.0,<1.44.0)", "mypy-boto3-comprehend (>=1.43.0,<1.44.0)", "mypy-boto3-comprehendmedical (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer-automation (>=1.43.0,<1.44.0)", "mypy-boto3-config (>=1.43.0,<1.44.0)", "mypy-boto3-connect (>=1.43.0,<1.44.0)", "mypy-boto3-connect-contact-lens (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaigns (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaignsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-connectcases (>=1.43.0,<1.44.0)", "mypy-boto3-connecthealth (>=1.43.0,<1.44.0)", "mypy-boto3-connectparticipant (>=1.43.0,<1.44.0)", "mypy-boto3-controlcatalog (>=1.43.0,<1.44.0)", "mypy-boto3-controltower (>=1.43.0,<1.44.0)", "mypy-boto3-cost-optimization-hub (>=1.43.0,<1.44.0)", "mypy-boto3-cur (>=1.43.0,<1.44.0)", "mypy-boto3-customer-profiles (>=1.43.0,<1.44.0)", "mypy-boto3-databrew (>=1.43.0,<1.44.0)", "mypy-boto3-dataexchange (>=1.43.0,<1.44.0)", "mypy-boto3-datapipeline (>=1.43.0,<1.44.0)", "mypy-boto3-datasync (>=1.43.0,<1.44.0)", "mypy-boto3-datazone (>=1.43.0,<1.44.0)", "mypy-boto3-dax (>=1.43.0,<1.44.0)", "mypy-boto3-deadline (>=1.43.0,<1.44.0)", "mypy-boto3-detective (>=1.43.0,<1.44.0)", "mypy-boto3-devicefarm (>=1.43.0,<1.44.0)", "mypy-boto3-devops-agent (>=1.43.0,<1.44.0)", "mypy-boto3-devops-guru (>=1.43.0,<1.44.0)", "mypy-boto3-directconnect (>=1.43.0,<1.44.0)", "mypy-boto3-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-dlm (>=1.43.0,<1.44.0)", "mypy-boto3-dms (>=1.43.0,<1.44.0)", "mypy-boto3-docdb (>=1.43.0,<1.44.0)", "mypy-boto3-docdb-elastic (>=1.43.0,<1.44.0)", "mypy-boto3-drs (>=1.43.0,<1.44.0)", "mypy-boto3-ds (>=1.43.0,<1.44.0)", "mypy-boto3-ds-data (>=1.43.0,<1.44.0)", "mypy-boto3-dsql (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodbstreams (>=1.43.0,<1.44.0)", "mypy-boto3-ebs (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-ec2-instance-connect (>=1.43.0,<1.44.0)", "mypy-boto3-ecr (>=1.43.0,<1.44.0)", "mypy-boto3-ecr-public (>=1.43.0,<1.44.0)", "mypy-boto3-ecs (>=1.43.0,<1.44.0)", "mypy-boto3-efs (>=1.43.0,<1.44.0)", "mypy-boto3-eks (>=1.43.0,<1.44.0)", "mypy-boto3-eks-auth (>=1.43.0,<1.44.0)", "mypy-boto3-elasticache (>=1.43.0,<1.44.0)", "mypy-boto3-elasticbeanstalk (>=1.43.0,<1.44.0)", "mypy-boto3-elb (>=1.43.0,<1.44.0)", "mypy-boto3-elbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-elementalinference (>=1.43.0,<1.44.0)", "mypy-boto3-emr (>=1.43.0,<1.44.0)", "mypy-boto3-emr-containers (>=1.43.0,<1.44.0)", "mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-entityresolution (>=1.43.0,<1.44.0)", "mypy-boto3-es (>=1.43.0,<1.44.0)", "mypy-boto3-events (>=1.43.0,<1.44.0)", "mypy-boto3-evs (>=1.43.0,<1.44.0)", "mypy-boto3-finspace (>=1.43.0,<1.44.0)", "mypy-boto3-finspace-data (>=1.43.0,<1.44.0)", "mypy-boto3-firehose (>=1.43.0,<1.44.0)", "mypy-boto3-fis (>=1.43.0,<1.44.0)", "mypy-boto3-fms (>=1.43.0,<1.44.0)", "mypy-boto3-forecast (>=1.43.0,<1.44.0)", "mypy-boto3-forecastquery (>=1.43.0,<1.44.0)", "mypy-boto3-frauddetector (>=1.43.0,<1.44.0)", "mypy-boto3-freetier (>=1.43.0,<1.44.0)", "mypy-boto3-fsx (>=1.43.0,<1.44.0)", "mypy-boto3-gamelift (>=1.43.0,<1.44.0)", "mypy-boto3-gameliftstreams (>=1.43.0,<1.44.0)", "mypy-boto3-geo-maps (>=1.43.0,<1.44.0)", "mypy-boto3-geo-places (>=1.43.0,<1.44.0)", "mypy-boto3-geo-routes (>=1.43.0,<1.44.0)", "mypy-boto3-glacier (>=1.43.0,<1.44.0)", "mypy-boto3-globalaccelerator (>=1.43.0,<1.44.0)", "mypy-boto3-glue (>=1.43.0,<1.44.0)", "mypy-boto3-grafana (>=1.43.0,<1.44.0)", "mypy-boto3-greengrass (>=1.43.0,<1.44.0)", "mypy-boto3-greengrassv2 (>=1.43.0,<1.44.0)", "mypy-boto3-groundstation (>=1.43.0,<1.44.0)", "mypy-boto3-guardduty (>=1.43.0,<1.44.0)", "mypy-boto3-health (>=1.43.0,<1.44.0)", "mypy-boto3-healthlake (>=1.43.0,<1.44.0)", "mypy-boto3-iam (>=1.43.0,<1.44.0)", "mypy-boto3-identitystore (>=1.43.0,<1.44.0)", "mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)", "mypy-boto3-importexport (>=1.43.0,<1.44.0)", "mypy-boto3-inspector (>=1.43.0,<1.44.0)", "mypy-boto3-inspector-scan (>=1.43.0,<1.44.0)", "mypy-boto3-inspector2 (>=1.43.0,<1.44.0)", "mypy-boto3-interconnect (>=1.43.0,<1.44.0)", "mypy-boto3-internetmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-invoicing (>=1.43.0,<1.44.0)", "mypy-boto3-iot (>=1.43.0,<1.44.0)", "mypy-boto3-iot-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)", "mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents-data (>=1.43.0,<1.44.0)", "mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)", "mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)", "mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)", "mypy-boto3-iotthingsgraph (>=1.43.0,<1.44.0)", "mypy-boto3-iottwinmaker (>=1.43.0,<1.44.0)", "mypy-boto3-iotwireless (>=1.43.0,<1.44.0)", "mypy-boto3-ivs (>=1.43.0,<1.44.0)", "mypy-boto3-ivs-realtime (>=1.43.0,<1.44.0)", "mypy-boto3-ivschat (>=1.43.0,<1.44.0)", "mypy-boto3-kafka (>=1.43.0,<1.44.0)", "mypy-boto3-kafkaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-kendra (>=1.43.0,<1.44.0)", "mypy-boto3-kendra-ranking (>=1.43.0,<1.44.0)", "mypy-boto3-keyspaces (>=1.43.0,<1.44.0)", "mypy-boto3-keyspacesstreams (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-archived-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-signaling (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)", "mypy-boto3-kms (>=1.43.0,<1.44.0)", "mypy-boto3-lakeformation (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)", "mypy-boto3-lex-models (>=1.43.0,<1.44.0)", "mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-models (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-lightsail (>=1.43.0,<1.44.0)", "mypy-boto3-location (>=1.43.0,<1.44.0)", "mypy-boto3-logs (>=1.43.0,<1.44.0)", "mypy-boto3-lookoutequipment (>=1.43.0,<1.44.0)", "mypy-boto3-m2 (>=1.43.0,<1.44.0)", "mypy-boto3-machinelearning (>=1.43.0,<1.44.0)", "mypy-boto3-macie2 (>=1.43.0,<1.44.0)", "mypy-boto3-mailmanager (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain-query (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-agreement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-catalog (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-deployment (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-entitlement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-reporting (>=1.43.0,<1.44.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconvert (>=1.43.0,<1.44.0)", "mypy-boto3-medialive (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage-vod (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackagev2 (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore-data (>=1.43.0,<1.44.0)", "mypy-boto3-mediatailor (>=1.43.0,<1.44.0)", "mypy-boto3-medical-imaging (>=1.43.0,<1.44.0)", "mypy-boto3-memorydb (>=1.43.0,<1.44.0)", "mypy-boto3-meteringmarketplace (>=1.43.0,<1.44.0)", "mypy-boto3-mgh (>=1.43.0,<1.44.0)", "mypy-boto3-mgn (>=1.43.0,<1.44.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhub-config (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhuborchestrator (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhubstrategy (>=1.43.0,<1.44.0)", "mypy-boto3-mpa (>=1.43.0,<1.44.0)", "mypy-boto3-mq (>=1.43.0,<1.44.0)", "mypy-boto3-mturk (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-neptune (>=1.43.0,<1.44.0)", "mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)", "mypy-boto3-neptunedata (>=1.43.0,<1.44.0)", "mypy-boto3-network-firewall (>=1.43.0,<1.44.0)", "mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-networkmanager (>=1.43.0,<1.44.0)", "mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-notificationscontacts (>=1.43.0,<1.44.0)", "mypy-boto3-nova-act (>=1.43.0,<1.44.0)", "mypy-boto3-oam (>=1.43.0,<1.44.0)", "mypy-boto3-observabilityadmin (>=1.43.0,<1.44.0)", "mypy-boto3-odb (>=1.43.0,<1.44.0)", "mypy-boto3-omics (>=1.43.0,<1.44.0)", "mypy-boto3-opensearch (>=1.43.0,<1.44.0)", "mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)", "mypy-boto3-organizations (>=1.43.0,<1.44.0)", "mypy-boto3-osis (>=1.43.0,<1.44.0)", "mypy-boto3-outposts (>=1.43.0,<1.44.0)", "mypy-boto3-panorama (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-ad (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-scep (>=1.43.0,<1.44.0)", "mypy-boto3-pcs (>=1.43.0,<1.44.0)", "mypy-boto3-personalize (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-events (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-pi (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-email (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)", "mypy-boto3-pipes (>=1.43.0,<1.44.0)", "mypy-boto3-polly (>=1.43.0,<1.44.0)", "mypy-boto3-pricing (>=1.43.0,<1.44.0)", "mypy-boto3-proton (>=1.43.0,<1.44.0)", "mypy-boto3-qapps (>=1.43.0,<1.44.0)", "mypy-boto3-qbusiness (>=1.43.0,<1.44.0)", "mypy-boto3-qconnect (>=1.43.0,<1.44.0)", "mypy-boto3-quicksight (>=1.43.0,<1.44.0)", "mypy-boto3-ram (>=1.43.0,<1.44.0)", "mypy-boto3-rbin (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-rds-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-rekognition (>=1.43.0,<1.44.0)", "mypy-boto3-repostspace (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehub (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehubv2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-explorer-2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-groups (>=1.43.0,<1.44.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.43.0,<1.44.0)", "mypy-boto3-rolesanywhere (>=1.43.0,<1.44.0)", "mypy-boto3-route53 (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-cluster (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-control-config (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-readiness (>=1.43.0,<1.44.0)", "mypy-boto3-route53domains (>=1.43.0,<1.44.0)", "mypy-boto3-route53globalresolver (>=1.43.0,<1.44.0)", "mypy-boto3-route53profiles (>=1.43.0,<1.44.0)", "mypy-boto3-route53resolver (>=1.43.0,<1.44.0)", "mypy-boto3-rtbfabric (>=1.43.0,<1.44.0)", "mypy-boto3-rum (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-s3control (>=1.43.0,<1.44.0)", "mypy-boto3-s3files (>=1.43.0,<1.44.0)", "mypy-boto3-s3outposts (>=1.43.0,<1.44.0)", "mypy-boto3-s3tables (>=1.43.0,<1.44.0)", "mypy-boto3-s3vectors (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-edge (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-geospatial (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-metrics (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemakerjobruntime (>=1.43.0,<1.44.0)", "mypy-boto3-savingsplans (>=1.43.0,<1.44.0)", "mypy-boto3-scheduler (>=1.43.0,<1.44.0)", "mypy-boto3-schemas (>=1.43.0,<1.44.0)", "mypy-boto3-sdb (>=1.43.0,<1.44.0)", "mypy-boto3-secretsmanager (>=1.43.0,<1.44.0)", "mypy-boto3-security-ir (>=1.43.0,<1.44.0)", "mypy-boto3-securityagent (>=1.43.0,<1.44.0)", "mypy-boto3-securityhub (>=1.43.0,<1.44.0)", "mypy-boto3-securitylake (>=1.43.0,<1.44.0)", "mypy-boto3-serverlessrepo (>=1.43.0,<1.44.0)", "mypy-boto3-service-quotas (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog-appregistry (>=1.43.0,<1.44.0)", "mypy-boto3-servicediscovery (>=1.43.0,<1.44.0)", "mypy-boto3-ses (>=1.43.0,<1.44.0)", "mypy-boto3-sesv2 (>=1.43.0,<1.44.0)", "mypy-boto3-shield (>=1.43.0,<1.44.0)", "mypy-boto3-signer (>=1.43.0,<1.44.0)", "mypy-boto3-signer-data (>=1.43.0,<1.44.0)", "mypy-boto3-signin (>=1.43.0,<1.44.0)", "mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-simspaceweaver (>=1.43.0,<1.44.0)", "mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)", "mypy-boto3-snowball (>=1.43.0,<1.44.0)", "mypy-boto3-sns (>=1.43.0,<1.44.0)", "mypy-boto3-socialmessaging (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)", "mypy-boto3-ssm (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-contacts (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-guiconnect (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-incidents (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-quicksetup (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-sap (>=1.43.0,<1.44.0)", "mypy-boto3-sso (>=1.43.0,<1.44.0)", "mypy-boto3-sso-admin (>=1.43.0,<1.44.0)", "mypy-boto3-sso-oidc (>=1.43.0,<1.44.0)", "mypy-boto3-stepfunctions (>=1.43.0,<1.44.0)", "mypy-boto3-storagegateway (>=1.43.0,<1.44.0)", "mypy-boto3-sts (>=1.43.0,<1.44.0)", "mypy-boto3-supplychain (>=1.43.0,<1.44.0)", "mypy-boto3-support (>=1.43.0,<1.44.0)", "mypy-boto3-support-app (>=1.43.0,<1.44.0)", "mypy-boto3-sustainability (>=1.43.0,<1.44.0)", "mypy-boto3-swf (>=1.43.0,<1.44.0)", "mypy-boto3-synthetics (>=1.43.0,<1.44.0)", "mypy-boto3-taxsettings (>=1.43.0,<1.44.0)", "mypy-boto3-textract (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-influxdb (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-query (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-write (>=1.43.0,<1.44.0)", "mypy-boto3-tnb (>=1.43.0,<1.44.0)", "mypy-boto3-transcribe (>=1.43.0,<1.44.0)", "mypy-boto3-transfer (>=1.43.0,<1.44.0)", "mypy-boto3-translate (>=1.43.0,<1.44.0)", "mypy-boto3-trustedadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-uxc (>=1.43.0,<1.44.0)", "mypy-boto3-verifiedpermissions (>=1.43.0,<1.44.0)", "mypy-boto3-voice-id (>=1.43.0,<1.44.0)", "mypy-boto3-vpc-lattice (>=1.43.0,<1.44.0)", "mypy-boto3-waf (>=1.43.0,<1.44.0)", "mypy-boto3-waf-regional (>=1.43.0,<1.44.0)", "mypy-boto3-wafv2 (>=1.43.0,<1.44.0)", "mypy-boto3-wellarchitected (>=1.43.0,<1.44.0)", "mypy-boto3-wickr (>=1.43.0,<1.44.0)", "mypy-boto3-wisdom (>=1.43.0,<1.44.0)", "mypy-boto3-workdocs (>=1.43.0,<1.44.0)", "mypy-boto3-workmail (>=1.43.0,<1.44.0)", "mypy-boto3-workmailmessageflow (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-instances (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-thin-client (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-web (>=1.43.0,<1.44.0)", "mypy-boto3-xray (>=1.43.0,<1.44.0)"]
+all = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)", "mypy-boto3-account (>=1.43.0,<1.44.0)", "mypy-boto3-acm (>=1.43.0,<1.44.0)", "mypy-boto3-acm-pca (>=1.43.0,<1.44.0)", "mypy-boto3-aiops (>=1.43.0,<1.44.0)", "mypy-boto3-amp (>=1.43.0,<1.44.0)", "mypy-boto3-amplify (>=1.43.0,<1.44.0)", "mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)", "mypy-boto3-amplifyuibuilder (>=1.43.0,<1.44.0)", "mypy-boto3-apigateway (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewaymanagementapi (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewayv2 (>=1.43.0,<1.44.0)", "mypy-boto3-appconfig (>=1.43.0,<1.44.0)", "mypy-boto3-appconfigdata (>=1.43.0,<1.44.0)", "mypy-boto3-appfabric (>=1.43.0,<1.44.0)", "mypy-boto3-appflow (>=1.43.0,<1.44.0)", "mypy-boto3-appintegrations (>=1.43.0,<1.44.0)", "mypy-boto3-application-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-application-insights (>=1.43.0,<1.44.0)", "mypy-boto3-application-signals (>=1.43.0,<1.44.0)", "mypy-boto3-applicationcostprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-appmesh (>=1.43.0,<1.44.0)", "mypy-boto3-apprunner (>=1.43.0,<1.44.0)", "mypy-boto3-appstream (>=1.43.0,<1.44.0)", "mypy-boto3-appsync (>=1.43.0,<1.44.0)", "mypy-boto3-arc-region-switch (>=1.43.0,<1.44.0)", "mypy-boto3-arc-zonal-shift (>=1.43.0,<1.44.0)", "mypy-boto3-artifact (>=1.43.0,<1.44.0)", "mypy-boto3-athena (>=1.43.0,<1.44.0)", "mypy-boto3-auditmanager (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling-plans (>=1.43.0,<1.44.0)", "mypy-boto3-b2bi (>=1.43.0,<1.44.0)", "mypy-boto3-backup (>=1.43.0,<1.44.0)", "mypy-boto3-backup-gateway (>=1.43.0,<1.44.0)", "mypy-boto3-backupsearch (>=1.43.0,<1.44.0)", "mypy-boto3-batch (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-dashboards (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-data-exports (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-pricing-calculator (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-recommended-actions (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore-control (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-billing (>=1.43.0,<1.44.0)", "mypy-boto3-billingconductor (>=1.43.0,<1.44.0)", "mypy-boto3-braket (>=1.43.0,<1.44.0)", "mypy-boto3-budgets (>=1.43.0,<1.44.0)", "mypy-boto3-ce (>=1.43.0,<1.44.0)", "mypy-boto3-chatbot (>=1.43.0,<1.44.0)", "mypy-boto3-chime (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-identity (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-meetings (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-messaging (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-voice (>=1.43.0,<1.44.0)", "mypy-boto3-cleanrooms (>=1.43.0,<1.44.0)", "mypy-boto3-cleanroomsml (>=1.43.0,<1.44.0)", "mypy-boto3-cloud9 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudcontrol (>=1.43.0,<1.44.0)", "mypy-boto3-clouddirectory (>=1.43.0,<1.44.0)", "mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsm (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsmv2 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearch (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)", "mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)", "mypy-boto3-codeartifact (>=1.43.0,<1.44.0)", "mypy-boto3-codebuild (>=1.43.0,<1.44.0)", "mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)", "mypy-boto3-codecommit (>=1.43.0,<1.44.0)", "mypy-boto3-codeconnections (>=1.43.0,<1.44.0)", "mypy-boto3-codedeploy (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-reviewer (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-security (>=1.43.0,<1.44.0)", "mypy-boto3-codeguruprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-codepipeline (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-connections (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-identity (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-idp (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-sync (>=1.43.0,<1.44.0)", "mypy-boto3-comprehend (>=1.43.0,<1.44.0)", "mypy-boto3-comprehendmedical (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer-automation (>=1.43.0,<1.44.0)", "mypy-boto3-config (>=1.43.0,<1.44.0)", "mypy-boto3-connect (>=1.43.0,<1.44.0)", "mypy-boto3-connect-contact-lens (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaigns (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaignsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-connectcases (>=1.43.0,<1.44.0)", "mypy-boto3-connecthealth (>=1.43.0,<1.44.0)", "mypy-boto3-connectparticipant (>=1.43.0,<1.44.0)", "mypy-boto3-controlcatalog (>=1.43.0,<1.44.0)", "mypy-boto3-controltower (>=1.43.0,<1.44.0)", "mypy-boto3-cost-optimization-hub (>=1.43.0,<1.44.0)", "mypy-boto3-cur (>=1.43.0,<1.44.0)", "mypy-boto3-customer-profiles (>=1.43.0,<1.44.0)", "mypy-boto3-databrew (>=1.43.0,<1.44.0)", "mypy-boto3-dataexchange (>=1.43.0,<1.44.0)", "mypy-boto3-datapipeline (>=1.43.0,<1.44.0)", "mypy-boto3-datasync (>=1.43.0,<1.44.0)", "mypy-boto3-datazone (>=1.43.0,<1.44.0)", "mypy-boto3-dax (>=1.43.0,<1.44.0)", "mypy-boto3-deadline (>=1.43.0,<1.44.0)", "mypy-boto3-detective (>=1.43.0,<1.44.0)", "mypy-boto3-devicefarm (>=1.43.0,<1.44.0)", "mypy-boto3-devops-agent (>=1.43.0,<1.44.0)", "mypy-boto3-devops-guru (>=1.43.0,<1.44.0)", "mypy-boto3-directconnect (>=1.43.0,<1.44.0)", "mypy-boto3-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-dlm (>=1.43.0,<1.44.0)", "mypy-boto3-dms (>=1.43.0,<1.44.0)", "mypy-boto3-docdb (>=1.43.0,<1.44.0)", "mypy-boto3-docdb-elastic (>=1.43.0,<1.44.0)", "mypy-boto3-drs (>=1.43.0,<1.44.0)", "mypy-boto3-ds (>=1.43.0,<1.44.0)", "mypy-boto3-ds-data (>=1.43.0,<1.44.0)", "mypy-boto3-dsql (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodbstreams (>=1.43.0,<1.44.0)", "mypy-boto3-ebs (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-ec2-instance-connect (>=1.43.0,<1.44.0)", "mypy-boto3-ecr (>=1.43.0,<1.44.0)", "mypy-boto3-ecr-public (>=1.43.0,<1.44.0)", "mypy-boto3-ecs (>=1.43.0,<1.44.0)", "mypy-boto3-efs (>=1.43.0,<1.44.0)", "mypy-boto3-eks (>=1.43.0,<1.44.0)", "mypy-boto3-eks-auth (>=1.43.0,<1.44.0)", "mypy-boto3-elasticache (>=1.43.0,<1.44.0)", "mypy-boto3-elasticbeanstalk (>=1.43.0,<1.44.0)", "mypy-boto3-elb (>=1.43.0,<1.44.0)", "mypy-boto3-elbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-elementalinference (>=1.43.0,<1.44.0)", "mypy-boto3-emr (>=1.43.0,<1.44.0)", "mypy-boto3-emr-containers (>=1.43.0,<1.44.0)", "mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-entityresolution (>=1.43.0,<1.44.0)", "mypy-boto3-es (>=1.43.0,<1.44.0)", "mypy-boto3-events (>=1.43.0,<1.44.0)", "mypy-boto3-evs (>=1.43.0,<1.44.0)", "mypy-boto3-finspace (>=1.43.0,<1.44.0)", "mypy-boto3-finspace-data (>=1.43.0,<1.44.0)", "mypy-boto3-firehose (>=1.43.0,<1.44.0)", "mypy-boto3-fis (>=1.43.0,<1.44.0)", "mypy-boto3-fms (>=1.43.0,<1.44.0)", "mypy-boto3-forecast (>=1.43.0,<1.44.0)", "mypy-boto3-forecastquery (>=1.43.0,<1.44.0)", "mypy-boto3-frauddetector (>=1.43.0,<1.44.0)", "mypy-boto3-freetier (>=1.43.0,<1.44.0)", "mypy-boto3-fsx (>=1.43.0,<1.44.0)", "mypy-boto3-gamelift (>=1.43.0,<1.44.0)", "mypy-boto3-gameliftstreams (>=1.43.0,<1.44.0)", "mypy-boto3-geo-maps (>=1.43.0,<1.44.0)", "mypy-boto3-geo-places (>=1.43.0,<1.44.0)", "mypy-boto3-geo-routes (>=1.43.0,<1.44.0)", "mypy-boto3-glacier (>=1.43.0,<1.44.0)", "mypy-boto3-globalaccelerator (>=1.43.0,<1.44.0)", "mypy-boto3-glue (>=1.43.0,<1.44.0)", "mypy-boto3-grafana (>=1.43.0,<1.44.0)", "mypy-boto3-greengrass (>=1.43.0,<1.44.0)", "mypy-boto3-greengrassv2 (>=1.43.0,<1.44.0)", "mypy-boto3-groundstation (>=1.43.0,<1.44.0)", "mypy-boto3-guardduty (>=1.43.0,<1.44.0)", "mypy-boto3-health (>=1.43.0,<1.44.0)", "mypy-boto3-healthlake (>=1.43.0,<1.44.0)", "mypy-boto3-iam (>=1.43.0,<1.44.0)", "mypy-boto3-identitystore (>=1.43.0,<1.44.0)", "mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)", "mypy-boto3-importexport (>=1.43.0,<1.44.0)", "mypy-boto3-inspector (>=1.43.0,<1.44.0)", "mypy-boto3-inspector-scan (>=1.43.0,<1.44.0)", "mypy-boto3-inspector2 (>=1.43.0,<1.44.0)", "mypy-boto3-interconnect (>=1.43.0,<1.44.0)", "mypy-boto3-internetmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-invoicing (>=1.43.0,<1.44.0)", "mypy-boto3-iot (>=1.43.0,<1.44.0)", "mypy-boto3-iot-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)", "mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents-data (>=1.43.0,<1.44.0)", "mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)", "mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)", "mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)", "mypy-boto3-iotthingsgraph (>=1.43.0,<1.44.0)", "mypy-boto3-iottwinmaker (>=1.43.0,<1.44.0)", "mypy-boto3-iotwireless (>=1.43.0,<1.44.0)", "mypy-boto3-ivs (>=1.43.0,<1.44.0)", "mypy-boto3-ivs-realtime (>=1.43.0,<1.44.0)", "mypy-boto3-ivschat (>=1.43.0,<1.44.0)", "mypy-boto3-kafka (>=1.43.0,<1.44.0)", "mypy-boto3-kafkaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-kendra (>=1.43.0,<1.44.0)", "mypy-boto3-kendra-ranking (>=1.43.0,<1.44.0)", "mypy-boto3-keyspaces (>=1.43.0,<1.44.0)", "mypy-boto3-keyspacesstreams (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-archived-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-signaling (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)", "mypy-boto3-kms (>=1.43.0,<1.44.0)", "mypy-boto3-lakeformation (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-lambda-core (>=1.43.0,<1.44.0)", "mypy-boto3-lambda-microvms (>=1.43.0,<1.44.0)", "mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)", "mypy-boto3-lex-models (>=1.43.0,<1.44.0)", "mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-models (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-lightsail (>=1.43.0,<1.44.0)", "mypy-boto3-location (>=1.43.0,<1.44.0)", "mypy-boto3-logs (>=1.43.0,<1.44.0)", "mypy-boto3-lookoutequipment (>=1.43.0,<1.44.0)", "mypy-boto3-m2 (>=1.43.0,<1.44.0)", "mypy-boto3-machinelearning (>=1.43.0,<1.44.0)", "mypy-boto3-macie2 (>=1.43.0,<1.44.0)", "mypy-boto3-mailmanager (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain-query (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-agreement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-catalog (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-deployment (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-entitlement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-reporting (>=1.43.0,<1.44.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconvert (>=1.43.0,<1.44.0)", "mypy-boto3-medialive (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage-vod (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackagev2 (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore-data (>=1.43.0,<1.44.0)", "mypy-boto3-mediatailor (>=1.43.0,<1.44.0)", "mypy-boto3-medical-imaging (>=1.43.0,<1.44.0)", "mypy-boto3-memorydb (>=1.43.0,<1.44.0)", "mypy-boto3-meteringmarketplace (>=1.43.0,<1.44.0)", "mypy-boto3-mgh (>=1.43.0,<1.44.0)", "mypy-boto3-mgn (>=1.43.0,<1.44.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhub-config (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhuborchestrator (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhubstrategy (>=1.43.0,<1.44.0)", "mypy-boto3-mpa (>=1.43.0,<1.44.0)", "mypy-boto3-mq (>=1.43.0,<1.44.0)", "mypy-boto3-mturk (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-neptune (>=1.43.0,<1.44.0)", "mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)", "mypy-boto3-neptunedata (>=1.43.0,<1.44.0)", "mypy-boto3-network-firewall (>=1.43.0,<1.44.0)", "mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-networkmanager (>=1.43.0,<1.44.0)", "mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-notificationscontacts (>=1.43.0,<1.44.0)", "mypy-boto3-nova-act (>=1.43.0,<1.44.0)", "mypy-boto3-oam (>=1.43.0,<1.44.0)", "mypy-boto3-observabilityadmin (>=1.43.0,<1.44.0)", "mypy-boto3-odb (>=1.43.0,<1.44.0)", "mypy-boto3-omics (>=1.43.0,<1.44.0)", "mypy-boto3-opensearch (>=1.43.0,<1.44.0)", "mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)", "mypy-boto3-organizations (>=1.43.0,<1.44.0)", "mypy-boto3-osis (>=1.43.0,<1.44.0)", "mypy-boto3-outposts (>=1.43.0,<1.44.0)", "mypy-boto3-panorama (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-ad (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-scep (>=1.43.0,<1.44.0)", "mypy-boto3-pcs (>=1.43.0,<1.44.0)", "mypy-boto3-personalize (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-events (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-pi (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-email (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)", "mypy-boto3-pipes (>=1.43.0,<1.44.0)", "mypy-boto3-polly (>=1.43.0,<1.44.0)", "mypy-boto3-pricing (>=1.43.0,<1.44.0)", "mypy-boto3-proton (>=1.43.0,<1.44.0)", "mypy-boto3-qapps (>=1.43.0,<1.44.0)", "mypy-boto3-qbusiness (>=1.43.0,<1.44.0)", "mypy-boto3-qconnect (>=1.43.0,<1.44.0)", "mypy-boto3-quicksight (>=1.43.0,<1.44.0)", "mypy-boto3-ram (>=1.43.0,<1.44.0)", "mypy-boto3-rbin (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-rds-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-rekognition (>=1.43.0,<1.44.0)", "mypy-boto3-repostspace (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehub (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehubv2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-explorer-2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-groups (>=1.43.0,<1.44.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.43.0,<1.44.0)", "mypy-boto3-rolesanywhere (>=1.43.0,<1.44.0)", "mypy-boto3-route53 (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-cluster (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-control-config (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-readiness (>=1.43.0,<1.44.0)", "mypy-boto3-route53domains (>=1.43.0,<1.44.0)", "mypy-boto3-route53globalresolver (>=1.43.0,<1.44.0)", "mypy-boto3-route53profiles (>=1.43.0,<1.44.0)", "mypy-boto3-route53resolver (>=1.43.0,<1.44.0)", "mypy-boto3-rtbfabric (>=1.43.0,<1.44.0)", "mypy-boto3-rum (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-s3control (>=1.43.0,<1.44.0)", "mypy-boto3-s3files (>=1.43.0,<1.44.0)", "mypy-boto3-s3outposts (>=1.43.0,<1.44.0)", "mypy-boto3-s3tables (>=1.43.0,<1.44.0)", "mypy-boto3-s3vectors (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-edge (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-geospatial (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-metrics (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemakerjobruntime (>=1.43.0,<1.44.0)", "mypy-boto3-savingsplans (>=1.43.0,<1.44.0)", "mypy-boto3-scheduler (>=1.43.0,<1.44.0)", "mypy-boto3-schemas (>=1.43.0,<1.44.0)", "mypy-boto3-sdb (>=1.43.0,<1.44.0)", "mypy-boto3-secretsmanager (>=1.43.0,<1.44.0)", "mypy-boto3-security-ir (>=1.43.0,<1.44.0)", "mypy-boto3-securityagent (>=1.43.0,<1.44.0)", "mypy-boto3-securityhub (>=1.43.0,<1.44.0)", "mypy-boto3-securitylake (>=1.43.0,<1.44.0)", "mypy-boto3-serverlessrepo (>=1.43.0,<1.44.0)", "mypy-boto3-service-quotas (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog-appregistry (>=1.43.0,<1.44.0)", "mypy-boto3-servicediscovery (>=1.43.0,<1.44.0)", "mypy-boto3-ses (>=1.43.0,<1.44.0)", "mypy-boto3-sesv2 (>=1.43.0,<1.44.0)", "mypy-boto3-shield (>=1.43.0,<1.44.0)", "mypy-boto3-signer (>=1.43.0,<1.44.0)", "mypy-boto3-signer-data (>=1.43.0,<1.44.0)", "mypy-boto3-signin (>=1.43.0,<1.44.0)", "mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-simspaceweaver (>=1.43.0,<1.44.0)", "mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)", "mypy-boto3-snowball (>=1.43.0,<1.44.0)", "mypy-boto3-sns (>=1.43.0,<1.44.0)", "mypy-boto3-socialmessaging (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)", "mypy-boto3-ssm (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-contacts (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-guiconnect (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-incidents (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-quicksetup (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-sap (>=1.43.0,<1.44.0)", "mypy-boto3-sso (>=1.43.0,<1.44.0)", "mypy-boto3-sso-admin (>=1.43.0,<1.44.0)", "mypy-boto3-sso-oidc (>=1.43.0,<1.44.0)", "mypy-boto3-stepfunctions (>=1.43.0,<1.44.0)", "mypy-boto3-storagegateway (>=1.43.0,<1.44.0)", "mypy-boto3-sts (>=1.43.0,<1.44.0)", "mypy-boto3-supplychain (>=1.43.0,<1.44.0)", "mypy-boto3-support (>=1.43.0,<1.44.0)", "mypy-boto3-support-app (>=1.43.0,<1.44.0)", "mypy-boto3-sustainability (>=1.43.0,<1.44.0)", "mypy-boto3-swf (>=1.43.0,<1.44.0)", "mypy-boto3-synthetics (>=1.43.0,<1.44.0)", "mypy-boto3-taxsettings (>=1.43.0,<1.44.0)", "mypy-boto3-textract (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-influxdb (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-query (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-write (>=1.43.0,<1.44.0)", "mypy-boto3-tnb (>=1.43.0,<1.44.0)", "mypy-boto3-transcribe (>=1.43.0,<1.44.0)", "mypy-boto3-transfer (>=1.43.0,<1.44.0)", "mypy-boto3-translate (>=1.43.0,<1.44.0)", "mypy-boto3-trustedadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-uxc (>=1.43.0,<1.44.0)", "mypy-boto3-verifiedpermissions (>=1.43.0,<1.44.0)", "mypy-boto3-voice-id (>=1.43.0,<1.44.0)", "mypy-boto3-vpc-lattice (>=1.43.0,<1.44.0)", "mypy-boto3-waf (>=1.43.0,<1.44.0)", "mypy-boto3-waf-regional (>=1.43.0,<1.44.0)", "mypy-boto3-wafv2 (>=1.43.0,<1.44.0)", "mypy-boto3-wellarchitected (>=1.43.0,<1.44.0)", "mypy-boto3-wickr (>=1.43.0,<1.44.0)", "mypy-boto3-wisdom (>=1.43.0,<1.44.0)", "mypy-boto3-workdocs (>=1.43.0,<1.44.0)", "mypy-boto3-workmail (>=1.43.0,<1.44.0)", "mypy-boto3-workmailmessageflow (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-instances (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-thin-client (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-web (>=1.43.0,<1.44.0)", "mypy-boto3-xray (>=1.43.0,<1.44.0)"]
amp = ["mypy-boto3-amp (>=1.43.0,<1.44.0)"]
amplify = ["mypy-boto3-amplify (>=1.43.0,<1.44.0)"]
amplifybackend = ["mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)"]
@@ -577,7 +598,7 @@ bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime (
bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)"]
billing = ["mypy-boto3-billing (>=1.43.0,<1.44.0)"]
billingconductor = ["mypy-boto3-billingconductor (>=1.43.0,<1.44.0)"]
-boto3 = ["boto3 (==1.43.24)"]
+boto3 = ["boto3 (==1.43.36)"]
braket = ["mypy-boto3-braket (>=1.43.0,<1.44.0)"]
budgets = ["mypy-boto3-budgets (>=1.43.0,<1.44.0)"]
ce = ["mypy-boto3-ce (>=1.43.0,<1.44.0)"]
@@ -749,6 +770,8 @@ kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)"]
kms = ["mypy-boto3-kms (>=1.43.0,<1.44.0)"]
lakeformation = ["mypy-boto3-lakeformation (>=1.43.0,<1.44.0)"]
lambda = ["mypy-boto3-lambda (>=1.43.0,<1.44.0)"]
+lambda-core = ["mypy-boto3-lambda-core (>=1.43.0,<1.44.0)"]
+lambda-microvms = ["mypy-boto3-lambda-microvms (>=1.43.0,<1.44.0)"]
launch-wizard = ["mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)"]
lex-models = ["mypy-boto3-lex-models (>=1.43.0,<1.44.0)"]
lex-runtime = ["mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)"]
@@ -1055,14 +1078,14 @@ typeguard = "2.13.3"
[[package]]
name = "cdklabs-generative-ai-cdk-constructs"
-version = "0.1.317"
+version = "0.1.318"
description = "AWS Generative AI CDK Constructs is a library for well-architected generative AI patterns."
optional = false
python-versions = "~=3.10"
groups = ["dev"]
files = [
- {file = "cdklabs_generative_ai_cdk_constructs-0.1.317-py3-none-any.whl", hash = "sha256:86359377bbb56c946a460b0b7244ad5f9b8be3ab290201ad2e197fc7a6628dfb"},
- {file = "cdklabs_generative_ai_cdk_constructs-0.1.317.tar.gz", hash = "sha256:e04ed66168736f65cc4d13449a719dbb8d84c7ffb054d22a034865918315d157"},
+ {file = "cdklabs_generative_ai_cdk_constructs-0.1.318-py3-none-any.whl", hash = "sha256:1a6717eeaf2b86cf1a60965eba52cf875355427c4de5ebded0b6d34c83182753"},
+ {file = "cdklabs_generative_ai_cdk_constructs-0.1.318.tar.gz", hash = "sha256:bc685eeb633142abb7ffed4a90f029aec8e10ada8e63b99398b13f21b4d81f6f"},
]
[package.dependencies]
@@ -1179,7 +1202,7 @@ files = [
{file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"},
{file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"},
]
-markers = {main = "platform_python_implementation != \"PyPy\" and (extra == \"all\" or extra == \"datamasking\")", dev = "platform_python_implementation != \"PyPy\""}
+markers = {main = "(extra == \"all\" or extra == \"datamasking\" or extra == \"valkey\") and (platform_python_implementation != \"PyPy\" or extra == \"valkey\")", dev = "platform_python_implementation != \"PyPy\""}
[package.dependencies]
pycparser = {version = "*", markers = "implementation_name != \"PyPy\""}
@@ -1399,118 +1422,133 @@ typeguard = "2.13.3"
[[package]]
name = "coverage"
-version = "7.14.1"
+version = "7.15.4"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "coverage-7.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3e3680291c4a1d0dadfa84a2c459576a4af5133abb617905714339a0c73138cf"},
- {file = "coverage-7.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5274669f37f2343635a347b91a60777621341ab3378e9c6ac9335eee704bddf"},
- {file = "coverage-7.14.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cfe5a5fec635799ef33428f1e5e61bafa45a92a96190ba731561ba558ccc214d"},
- {file = "coverage-7.14.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62a9f70b52e0b5a95cfef4a5c5641b06983cadc5e538a3feeb5c00211f523ac2"},
- {file = "coverage-7.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c18ebc343e15be53049b3a2dce38fe82d58f37e20ab9094b3a39c0aa4f6bb47"},
- {file = "coverage-7.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b84ffdf877644e7096aa936991efeed873f7f3df57b9cd001312b7668ab08550"},
- {file = "coverage-7.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e854312c4103f2ad4c0dc023b69b77ebfd2c89db5f86c4c94dc2353f9a92167e"},
- {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c643734307300234fafa36bf2a040a7235f8f177ea1fd6ec1423aea6fb7b929f"},
- {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:84ac9499e48700399a5dd0ea7085b5091961fec52c68d66b4ec0d3cf7f4441b1"},
- {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7f02d09f70776579b926d889a4c9c235070a1f47c40458aeaca563fae5acfdb5"},
- {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ce66d8e46da2bb5ee313a745cbd2e391d319176c1f7a9451bfcd3a2fb920859b"},
- {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c912c259304cfb5ee584481cfb7ce1ff932b4d61e6c9140b8f19cb7b5ed82332"},
- {file = "coverage-7.14.1-cp310-cp310-win32.whl", hash = "sha256:1238cb94638e610e972c60dac68e813f868dc7d6e982535270558443058d9d59"},
- {file = "coverage-7.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:fc459e5d73be2d6332fcfe8dbf3d8994671fe33c700f4565988ecfa511547253"},
- {file = "coverage-7.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:478b5bcd63c2e1357c5c7e16c070690df7b07f676b1c114d7b93e533c664309f"},
- {file = "coverage-7.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a24a81f9715ee42ef59a316cc11611c98fe23920f7c81861315c9f3ff4a230f4"},
- {file = "coverage-7.14.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:196a13319ad88d6d8ef5ab489ec4f44ddde2143c0c7d5b27786f6c3ffd56a7e1"},
- {file = "coverage-7.14.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d452fd08b5c72c5167c93e6867b5c08500bd40f2a21e1e854a500550b6cc36f"},
- {file = "coverage-7.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23bf7fa51ac02e07fc7c96849b82946da47ae862dc8f86d183b2a4864fc38129"},
- {file = "coverage-7.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcaa50684dcaadfa599ac48f81103c756d791cfd85c97203d2217c593d48b860"},
- {file = "coverage-7.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4ea1c034f95c9b056e856b794630b17f9fa3d57e4800ff1e503d3be0f9c9078c"},
- {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c7e057326434e441306226fbeb5d1aaf14a2637efe97ba668306635835f32ad7"},
- {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59baf88468dbc8d63b1887afd92bda52e40bb1561696e5819670601403810cec"},
- {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d75f892b3ab73ba11cab5442cce7b3e168fd64162b16f0e1e0d09c508edef"},
- {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3a56abc20a472baf0304c455721bc601477440d28ecfde8a03dde79ede07e0df"},
- {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a3cb83d1552c0cd1b4906655b6a33fd4a8473229633a901c6b73bf86914dee9"},
- {file = "coverage-7.14.1-cp311-cp311-win32.whl", hash = "sha256:10274a1fbeb8ec5d72966e17bb198a3104257aca4ac09d98667c5f8aca8c8548"},
- {file = "coverage-7.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:87ebdf787d4888e3f3f2d523eadc6e18c6d18c6d0eb173801a189641627fb37e"},
- {file = "coverage-7.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:dd34767fa19848d35659ffc0a75314f58c7af3f1cd87ec521e8292a1238398a3"},
- {file = "coverage-7.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a06c76364a9360e33d6d23769aefdf7f66f38e2ffb60ceb1baaa4989d83b695c"},
- {file = "coverage-7.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fad54e871165f6ec2f536063ac74c3104508a12963e64072ba44bd822de52b0c"},
- {file = "coverage-7.14.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:84b535f00655ecafe1d929d1fb00ed5d6fa3051ea643ab2c161a3887b86f294b"},
- {file = "coverage-7.14.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b6b0853b895fe0e98cbfc580d1ec3393d9302b4b1e96a77b3f5c91fdab899e6"},
- {file = "coverage-7.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:442cc9c952b2df400cda54bb04ab87330cf2cd08a8692cbbea36773531eb6f37"},
- {file = "coverage-7.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8270544c361ed405a27a060dbc9ed2c124b084d96dfdc2d9a2510482aef981ad"},
- {file = "coverage-7.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:48b283b1dd6372e8de2a7a9a4c4d5dc06f4d4fd209b876f3c88a7a205a0c8f84"},
- {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5b0c99ba93a07d56f6df340bb79be53202a082b2fdb81bfe6190b741a3470d54"},
- {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e471bc5769ff073b058cfadb0d736b56ce067c8560eabeb0da88462df98c23e7"},
- {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f497a1ea81d4cd7c10ddcaa685135b9aabd291af3d55775a9ddf3cb7a364cdd9"},
- {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2222be86d0b54f5dd5a38f45f17f315f737245e857bf0bdedc70734f84a13c02"},
- {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:85e85586565842f6932abebd4c18bcb1074223dc0b3576e7d173ca710622813a"},
- {file = "coverage-7.14.1-cp312-cp312-win32.whl", hash = "sha256:4a28fd227808366b196a75476dced2eb35b351d6766ba9c858dc93319e87f4f1"},
- {file = "coverage-7.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:54acdb6674a4661768d7bf7db32dfb9f46ab1d764f8aba6df75ce1a6a088724e"},
- {file = "coverage-7.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:99cd41ff91afd94896fea3bc002706b6ae4ce95727d06e4a0f39c0a8d8bd8b1a"},
- {file = "coverage-7.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:be9f2c802dcfce3f71298303aa5dad0dce440a76c52f2f60dacd8656dab78793"},
- {file = "coverage-7.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6223a72fd0e4c7156353ec0f08a5f93623e1d3034d0e2683b9bb8ea674131b1d"},
- {file = "coverage-7.14.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7279d2110a28cebc738b6459ecda2771735a4c18465fbbd36b3288fe5ed92247"},
- {file = "coverage-7.14.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9eeb3fcbc13ba40dfbdb22d01d196a28e9cef9ed4c29b60061a1e0e823a9929d"},
- {file = "coverage-7.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f0cfc27c539f07cf5c0a4cfe211d0b6cae039f8f40526dbaa71944e64b50a7b"},
- {file = "coverage-7.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:221c70f316241a78e77e607c227cefc8808d4e08f28d99c04f35694690e940be"},
- {file = "coverage-7.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da028256b04ec30e5e0114b6f76172938c313991f0a2d3d894271315cf5d5e43"},
- {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76a085d7005236a767e3426148b2c407e53ad61695c562f8a81da2d373324901"},
- {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b553d04b5e778a8e56d57eb134aff42a92718ecba45e79c4764ecfa40efd92ff"},
- {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:46f714d2fb8ae2f4f29f23ada7f1e79b759fff5a70f94a1dac23af204c3ec9e4"},
- {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1896f5e19ff3f0431c7ce2172adc54890fd97f86b59ced8ca1649145d9ffe35d"},
- {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:62fd185ef9df3c33d1c8178c5af105f762afbad96038de9a4ae100aa6297ca33"},
- {file = "coverage-7.14.1-cp313-cp313-win32.whl", hash = "sha256:ab4af6352741a604c431c6072fce5bee33bf0f20dc7a56618d6bf6bb89e9810c"},
- {file = "coverage-7.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:7af486dabe8954d03b087f0021540897afe084f04e16ff5579e08cc46f871416"},
- {file = "coverage-7.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:2224f89ffd0c5605ccce1ed7a584da162bc7c55f601ab1c946bc9de31a486b42"},
- {file = "coverage-7.14.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de286598cc65d2b489411174b1faec2f5a7775fb3201fd925db2a76b4030f37d"},
- {file = "coverage-7.14.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:042c46ded7c288aeb07cf14a28b6c1e10b78fcba40171c3fa1e939377eeef0b5"},
- {file = "coverage-7.14.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f4ddbe407477f04c45115d1a4e5bc480f753553b534d338d4c3358b1cdd0ea52"},
- {file = "coverage-7.14.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d13e6725992e2d2fd7d81d4f5241952d13740121dfd501da09201be39b2c003a"},
- {file = "coverage-7.14.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f747dc8edcfe740130f28f32f3995e955494285717e86ee25af51db2219df08a"},
- {file = "coverage-7.14.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced2f09ef276fd58611a1ef502164ad266d2b75174e5a40cabbdb4033f9f6cf2"},
- {file = "coverage-7.14.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b84800013769a78ccb9ef4659402e26d06867e337b61ec365f77ad008adea80e"},
- {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ea8cd6ca0ee9f616aaef3afc6882e32c2cbf18b00d96313ffd76af650574034d"},
- {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:aa5e304a873fabddc11e484e9b6b738bd38bd7bed17b09aa84eecf5332e8b8bb"},
- {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5a1c5215be81035e629d5bc756650634d0bf31991038db7a0eccb90f025ce16d"},
- {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:79058c47dae6788504b5effb319961bcd72d7240551464b91d474bc0ed186d69"},
- {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:370c5afae3fa0658e11694a32b24c2778f6bc2d17718121f94ee185e69f26b54"},
- {file = "coverage-7.14.1-cp313-cp313t-win32.whl", hash = "sha256:3758dd0a7f1fa57365ef2e781df0f0731d38b6e3772259d13dae4bd8a958d4b1"},
- {file = "coverage-7.14.1-cp313-cp313t-win_amd64.whl", hash = "sha256:6ff665fb023a77386fe11685190cee1f60a7d635994a30d9b0a061533d470fce"},
- {file = "coverage-7.14.1-cp313-cp313t-win_arm64.whl", hash = "sha256:17a5a241e5997621a956a7f402a7433ef4221e5152809b785bec79e2323799f1"},
- {file = "coverage-7.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d5ed429d0b8edaac649e889b4ffcedb6c80b06629a3f93050e3dddfb99235bee"},
- {file = "coverage-7.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8011224a62280e50dab346960c03cf47aca1a1e09e608c0fb33fd6e0cc8e9500"},
- {file = "coverage-7.14.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:12c42ec1e14f553c4f817e989365982e646e27211f10a0f717855b94a79c8906"},
- {file = "coverage-7.14.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06144cd511cf2624873a035c5069cf297144f6e77a73ee3d7a55b605ec5efb42"},
- {file = "coverage-7.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a311d8e1da24be5c1ccf85cbfb06315dbaa1703d5a1eab3f6432c72b837917c8"},
- {file = "coverage-7.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c79cead5b5bc584d9c71451cb984d0e3a84e0c0937379c8efcbf27c8d661b851"},
- {file = "coverage-7.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dcbf65f1f66a26cdd88c35cf68fb4729c5d1cd2e88added72420541dfb212034"},
- {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fd86572566fb40189a8260446158235159bc7a82dfbc87a3b39cf4fb57fcec1c"},
- {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:7771b601718fdde84832c3a434ca9bbf4ae9adbc49d84198b4110700c3c77c36"},
- {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:39b21e212c55af06fa375e3dbf90a8a8e38792f3a910c580066d23563830ddd5"},
- {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f2302660e32562a532b442480121aef8aa61a5bdb20b30bf0adab29f10a5a4b4"},
- {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:03a6f93c1ec3b7f2e77b5dbcc5573a2c21f12529a5c6bbe0f16f72303cc2fa4d"},
- {file = "coverage-7.14.1-cp314-cp314-win32.whl", hash = "sha256:8a3ce026d73290f42f08dafecbd82c193a74df280461fbf97300fec51fd133ee"},
- {file = "coverage-7.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:114c95ef29302423b87d159075805f4ab973254a2638a5d7d046c94887cc87d7"},
- {file = "coverage-7.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:a07891c3f4805442b31b71e84ba3cf29ed1aa9a428284e06deeb4b23e5b46343"},
- {file = "coverage-7.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1101a5ebb083aecb625ebb6209d4105b58f647b093cb2dc8122d7b33f743cfe1"},
- {file = "coverage-7.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:851b9e1e4e8a4608e77c79714b2e77c0970d2ed7202a05e92ae407817481887b"},
- {file = "coverage-7.14.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d5b89cdfb2ee051b71e8c3c70bd81a9eff81100f736a269136fe1a68efe00474"},
- {file = "coverage-7.14.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0177614a0370f227888b4e436a7c55686d6a9f90eb1ade2b624ba685a1686e86"},
- {file = "coverage-7.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d69af5dea2de76fc485a83032a630523f985198b7e25be901ec60181587b01e"},
- {file = "coverage-7.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:35ab22d91de736e8966b980dc355cbcdd2c6dbbcfe275f9a2991bc8a91b3df65"},
- {file = "coverage-7.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:357d4e32935c36588aaba057d734fa32428c360c9fc2e4442afbf1b646beee6e"},
- {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:51bd64741cc6fa065abd300ede1afe5a5291ece9c31da8b24884deda48bcc3f8"},
- {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9132cd363a68a4c3daa7c8704a654b1e39d3360f6f5b8ddd470608a945236c07"},
- {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07c6290b1697b862c0478eab545eec949a0d0e4d6d03497f446d706da3b4f2de"},
- {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5ea0c297e27133853b4d8a3eb799bff5a2dbd9f2f41537a240d337ac9b4df890"},
- {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:01b7733daad0237daa01ef80fe2dfceffc911e6a17fa7b55d14aa8214eaaaecd"},
- {file = "coverage-7.14.1-cp314-cp314t-win32.whl", hash = "sha256:6adc5a36984624a70bf11d7184e20fa0a49aa7c47ffab43804106a1a695ea22e"},
- {file = "coverage-7.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ddf799247318f34dbcd2efa8c95a8d0642674e926bb1774cf9b63dfd2a389d1c"},
- {file = "coverage-7.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:145986fe66647eb489f18d9a997567a3fd358584c4b5a808769113abc07466af"},
- {file = "coverage-7.14.1-py3-none-any.whl", hash = "sha256:a252f21c27e38347e60111a3266b03827422a7d5525951aceee313aa68bab1d2"},
- {file = "coverage-7.14.1.tar.gz", hash = "sha256:30c08f7d90415aa98b3c990385dea2939b0da55f38515e5b369b83655f8523be"},
+ {file = "coverage-7.15.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0be6daac4cce6b8c8dc65886bae1b082ddbca4da8e5cbb5e15166acf253e264"},
+ {file = "coverage-7.15.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b24e078eabcd6a9caa8b0713f9bc1eeb310bcc960a29d45a3b4fcd4b16d5b11d"},
+ {file = "coverage-7.15.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cfe20cc8cf8821d4fe54f89106cbf06aa27f37b5bbe3535568065a81539b4150"},
+ {file = "coverage-7.15.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:83cf06cdd687677742caff1a9134833b7a8b75f111519d2cb0e0ba1b9a851e15"},
+ {file = "coverage-7.15.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8fa4de68e2a752468ff14b4e15db7def689a71be759e826a31ccecbef69c5fd0"},
+ {file = "coverage-7.15.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4dff9daa47d83120c3ec38ce921214242944a832aa04e903e50b5b7ebac8972d"},
+ {file = "coverage-7.15.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a093fd37229918976f602aa07aa59e0973cde82186f220c8e197f721f5be0ce4"},
+ {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:317db01a2cb02552fd67e2b1cca77a4b528a2a277176c5e0bf2cecbb639d3f54"},
+ {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8ee3838dcb656602c3b51e16aed9bfb0822f8d8d6d1c5966d32ec8c104be8e20"},
+ {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:425920379052ff1fe465268f3361d35804a241bbdd5a1b592c8cb60df4c52325"},
+ {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:69bb2400abef928e365ea7d4d9925169ada78ed2295546780002d4b65de3df88"},
+ {file = "coverage-7.15.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:81661f82d302484e3119e7c80c519c02fa9bcc2a6b339baf67d67bc89c580f04"},
+ {file = "coverage-7.15.4-cp310-cp310-win32.whl", hash = "sha256:cb476b2e828ecb71cb6b6a928d23fd20a7ddb501188022dae1c37499149cc338"},
+ {file = "coverage-7.15.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fc2130bf37df31852a8384f12601563a45a0024bccc6624f38355cba7a8d360"},
+ {file = "coverage-7.15.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bbac5abad70df71019988f83f26ac7092ff2642975def4429e98dc7585ef3490"},
+ {file = "coverage-7.15.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:357a173465c7ce028d07a95cc2b63b5bf59f50ecdd5ad75c5cbb78ada984048e"},
+ {file = "coverage-7.15.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:21b803935e2efc3acebe9697197a294fccf5dc4e5382bd6369542ff7a7d2a1d7"},
+ {file = "coverage-7.15.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7a2b580774a4786c1053157c0165e04476e03ff293993d7c148eee784a94bae6"},
+ {file = "coverage-7.15.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9464451c4efffe8d47ace5a540b10b0dc10e879066290f8600872b7f54a419d"},
+ {file = "coverage-7.15.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de602f34123c2f4af1c1869c6dbbbd60da6d5983bf01937367295d135cccbfce"},
+ {file = "coverage-7.15.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6879ded16a27f3eeca19b900c147e81616e7054db451471a611b2755ee5249f7"},
+ {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:986be58c3ab54aae8d3496a6225eea74f760fdbe739b38bd442c7e8d133aa53b"},
+ {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c6103639613fe6c1e989082948419bc77a2d26b6c825c99d7fad25f7d3d87afc"},
+ {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d3af93dddb5659276c63bc16ac6466ac2033a70ca816097bbc06345b8ccdf571"},
+ {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:b10075e5421d04265766a6d1dac809bbeb8a946fbb23c8f82c227409b2190719"},
+ {file = "coverage-7.15.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a67a9f78b2942d87ba8ce3059c642164d2aedd65337377fb52fe9803656bc5c7"},
+ {file = "coverage-7.15.4-cp311-cp311-win32.whl", hash = "sha256:69484d1aca26e322e1c3ce03f09341e84524ababad2d7202161738d83cc9f82e"},
+ {file = "coverage-7.15.4-cp311-cp311-win_amd64.whl", hash = "sha256:63fd6fcd1dd6e158f7eb78606e72933b3f6d01e7b747f99c6c12d764307a0fdc"},
+ {file = "coverage-7.15.4-cp311-cp311-win_arm64.whl", hash = "sha256:ea82116c9893fa89e929b7f197ee5a1950a76e91cc5c85ba503fc02379d04890"},
+ {file = "coverage-7.15.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d4fedd1f7f428f9fe83b1ead5e7cc87a43427be31aadafbac3ac0636dc7abb22"},
+ {file = "coverage-7.15.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:37e2f0cdf58e2e1fed4e4d5a8f8786ae2f7eb80b478016876667dc4a01d60a97"},
+ {file = "coverage-7.15.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fb55d0e70bb15f2e81477613627286581414693d74ac7963c93a790dd453ca9d"},
+ {file = "coverage-7.15.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:899b9da30f3c6c336566e3707495bb23e8302d39d862f01fa78c48b99b9437e2"},
+ {file = "coverage-7.15.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d15715e8c46552827e5e4f30a35575a2dbcad14454cf3284c54483946bd16931"},
+ {file = "coverage-7.15.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:002a438859f7b430bc99afeaf01a6d187dad1d0dc907b64cdeffc632a5db8fd8"},
+ {file = "coverage-7.15.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e4193a04b518f7968f3099755f5509ee7cccc6dc2b92a6b14841934d22e222c9"},
+ {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e98dcc55d572b38e69d117da7e8e8efb8500f1f5eaf81ecd460a63220790b839"},
+ {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:af6c538498ce66c10d3fd541c2a8d5b03da5850355add34e6cba564210cb9e72"},
+ {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1d10025d96ea89fc2f73714dbc4cbd433fe012c1ac9e23f895d7728b238b6e52"},
+ {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d802e1947603162ded419bff83ac7489820355d2b856dfb09206574e3a37ac0c"},
+ {file = "coverage-7.15.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2de40895718f91951b86712b4c5b694acaf9a0a49be13874896f599a1eed3f4"},
+ {file = "coverage-7.15.4-cp312-cp312-win32.whl", hash = "sha256:5c3431b2161279b7db5c2a1aa58ae02e5cb8c3c42d93a5094be3f5537bd5b11b"},
+ {file = "coverage-7.15.4-cp312-cp312-win_amd64.whl", hash = "sha256:6befeab5fb2b51c958ca4ac6c5d141a1e8240f4f76e46350f1911963deda49cd"},
+ {file = "coverage-7.15.4-cp312-cp312-win_arm64.whl", hash = "sha256:67bc345491ab55b837277d76f5775d057e8c7f1ac44d890d8c2c82adde258c6f"},
+ {file = "coverage-7.15.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c705b28feb2775dc82a25f1d473a370bc37ff93f5177f4e29ce2425f560f6921"},
+ {file = "coverage-7.15.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3ff205ab5e3ecc670f6a4dd19d9cbf12ede53dd41cfc1e15716ec961ea6d314e"},
+ {file = "coverage-7.15.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5172326e861a38b48b48befca15e0f477a26b283337a33a739c8fed229934e36"},
+ {file = "coverage-7.15.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:12b59c90084e3234fb11184886bf4a40f4f16a8c8f867be2e087b81f8e8868d4"},
+ {file = "coverage-7.15.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349062d66f00b40fa2c1c222438bad25fabf755631b5d82937fe985c8008615c"},
+ {file = "coverage-7.15.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4256ced708e598e05209bc1a8ab4074e04a51dba4c62fb45926a229af675ace7"},
+ {file = "coverage-7.15.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d80f974b20782d9612c8b4c9beeca867074c7cf4079d1419843fa25a26428b25"},
+ {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2e179f19bfe1d31f8eeeaa12990194d761c4f62f0759661000bca6cd8729f40b"},
+ {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8bc16bb47b7679670eceff71d78bfb7d6e5b143f6c2cd117487ec7c75e0d4b78"},
+ {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1cd685005cd2c4200adfc14cf39a603b9320efab3f18a8f7f156d20c9cc3345f"},
+ {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:337399ad2c93b3acd2a937627dae8b3e86b66707cd3d3e856347999aadf1ef8d"},
+ {file = "coverage-7.15.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:96e257121228ec5cd2bb919276e94ac11074471bc37d68dbae0e8308cce15fff"},
+ {file = "coverage-7.15.4-cp313-cp313-win32.whl", hash = "sha256:c65a9e0dfc6143491879da4e13b5e30f8be192055de508d737fb14601edbd22c"},
+ {file = "coverage-7.15.4-cp313-cp313-win_amd64.whl", hash = "sha256:2ff8f5e9b8f7a94f0c11c45631eee103dbcb7d63274edd12c56efe1be690b3b4"},
+ {file = "coverage-7.15.4-cp313-cp313-win_arm64.whl", hash = "sha256:6e0a8a5083b096487d6cfced94cdd514d8f5db6f113610fb36c0620edb1028cf"},
+ {file = "coverage-7.15.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:770e9325ab5ea6d56f77e59b29ecfe0ac20b57a82a601876f90494a4dda0386f"},
+ {file = "coverage-7.15.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d12b33a3a50a1676b7784dc8d00a0c6d66a9f2add4b85a041c19b6a7e53ef23c"},
+ {file = "coverage-7.15.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5669c8378ebde86f5def7a25d29586631b58acc27ffde04399f678f3dfc6e082"},
+ {file = "coverage-7.15.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ff97a14362eef486483ed44042ca2027ea257df6ff768e62358ee0c9776925ac"},
+ {file = "coverage-7.15.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a325e815318638aed1655d9c06e6d7c2d3d46c09231ce988070428a8762d734"},
+ {file = "coverage-7.15.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:474223409d88eb20d2d6a0d37ea60e8647a65a90cc008dc1f0410af5f64f1e0d"},
+ {file = "coverage-7.15.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7f2f62ae3cd189dd2e13aece758c57b3eecbd27be070dbd4cbd10936049e5dbf"},
+ {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:39ece820e29e0a2ba34b3ecb3be83c27e997eed8926f2ba6fe7ce7a0bda5843b"},
+ {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f21b56dcace11dfe013014201f577dcd592b2a9b72182d930361b47cf6f73f25"},
+ {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:93a3a0b662abcc10c73a47cbc72cd60f63618d6989fb2d1286e50eacd974f303"},
+ {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:141fae2cabf5569b782c10afc4c850ce10f618c13f8db54765cba99cc839da1f"},
+ {file = "coverage-7.15.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:81294c7e6ab30c5f74c0353b11b2fd6320e72d9bee6ac73b357caa8b916323a5"},
+ {file = "coverage-7.15.4-cp314-cp314-win32.whl", hash = "sha256:7bbd7d6418e0dab31a206af5203bd43ae36edb8e7fba1940b055d3e9249290d7"},
+ {file = "coverage-7.15.4-cp314-cp314-win_amd64.whl", hash = "sha256:f0204ed122758782970526057093f448051a39db9d810d4e344bb87a3546f425"},
+ {file = "coverage-7.15.4-cp314-cp314-win_arm64.whl", hash = "sha256:9e71e7bc71c686a123347ae47a0de33a175e797a85bb57b791492adf4eec8ed8"},
+ {file = "coverage-7.15.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7c922735321eef3f87c280a3d39afff6b646723a2880b862cda4ac7a093b8aa8"},
+ {file = "coverage-7.15.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f41c17c4668a655ce96d090d8d5ffdc24ef64b5a02f9753884d08483e8a4a41a"},
+ {file = "coverage-7.15.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:46822e9b6ff1c6a72b518c162c44a8f45a61a1d609c51084bf5b16c023c5037b"},
+ {file = "coverage-7.15.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d6f4955b73b5445271379a59e3792b0d978f42d4a01e0cf7a67d9c33a3bb0a5"},
+ {file = "coverage-7.15.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3fc9e047706fb4a9abb54f719d3aa643e80e5bb3818182c40aee01ac0f0247ba"},
+ {file = "coverage-7.15.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05e491d4f3165d62d4f5c8fd48dfeabf2ae8f42cbbd484319af33ea851b78982"},
+ {file = "coverage-7.15.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:226c66e80ec0598d3b9b4874123df167ccca342aca8714f77cac6829688ee09c"},
+ {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac41cc14bebda0dbfb0628036b7f75706935c95bcc07fefe9a0f93614aa60a57"},
+ {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8af623e5cd92080acddd02b38f2f406a2c3a0893c38950b211890361448fbf26"},
+ {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07545711d4f0f32852a18f18ad11f76f0109909d09e78b9008b4cfc67e829429"},
+ {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a0865421cfdc53654b342d515e5a233187590882d20b95752150e53f65460017"},
+ {file = "coverage-7.15.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:460115e32ee40566476db5048f9bec1e842c127ad8e6f8be745aad3ac9cbc839"},
+ {file = "coverage-7.15.4-cp314-cp314t-win32.whl", hash = "sha256:cbde877ef9dd7baf272b9bfef2b8a25edd45d9170fc326951dd20eb480335e85"},
+ {file = "coverage-7.15.4-cp314-cp314t-win_amd64.whl", hash = "sha256:3da9e92d1c551fd7563833e9ade686efb0c4b7363ab7681a94283958c950bf5e"},
+ {file = "coverage-7.15.4-cp314-cp314t-win_arm64.whl", hash = "sha256:3a54f5a0d85050c73a38f6793090ee83974531e67fe5e57a1da9bee11398aa5e"},
+ {file = "coverage-7.15.4-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:2c9872e4d9dc5d3cf616bf4b382f5a00359305a5be666a3dd0b5cdb4e49597f9"},
+ {file = "coverage-7.15.4-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:e101dbb4b9b72f0cddd8cdc8c9c5b47f456766f5e0ac82dbfb75e5c55409b78a"},
+ {file = "coverage-7.15.4-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7d1abebdb047729e852b9c77a00497dfbeb11eb3a117e037d7dbc3ac8e5f5c54"},
+ {file = "coverage-7.15.4-cp315-cp315-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d28a4a899354d0ea6214cc59b4fa19eefbce1b9ff1688ab579acf49e894bd3fb"},
+ {file = "coverage-7.15.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffb3c2aacea411cc7e1d27712490c11108e2de1d39019ae32915493a59a8b9ed"},
+ {file = "coverage-7.15.4-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9447978a92f405d301123cfd39ff49895490efb769a758fe2734c7f631bf8ce"},
+ {file = "coverage-7.15.4-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:050467a7983b8e2fe7dd41a78bb30c3e7f8c0b8cafda14b1c46f8b5e3cf2dd3c"},
+ {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:d003b7a5708ddad5c206c79607a6b92abb6fc13c57d99d8a4468cc03a2941ced"},
+ {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c38efe30fd74e5c19e9433f11fb1f5dc9c6522770971b7c6145bbaa413dc8800"},
+ {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:1f4f826d70f772ab8b0c052329580d7fe8b8abd191e4ce0c8f81aec6614665d3"},
+ {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:4a4bf917c9953f57c957be31c1cd504e3bd2f34d4a352b9d391a3025336f6768"},
+ {file = "coverage-7.15.4-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:1c9bf40ebef178a45192c75c4964760bb261b0e6ad725da5fc4c93f674f19753"},
+ {file = "coverage-7.15.4-cp315-cp315-win32.whl", hash = "sha256:43619d04c3671792d2c4706ae8bf45e265dc87bbd4078189ef8b847ea1e74be2"},
+ {file = "coverage-7.15.4-cp315-cp315-win_amd64.whl", hash = "sha256:be619439dbcd31a2eab10b32de9fff62c26ed4bab69dc32b8363fdaaa0882809"},
+ {file = "coverage-7.15.4-cp315-cp315-win_arm64.whl", hash = "sha256:def597967dafc2e8d97c9097ea453c464e0bb8ed38f193a43070f10dc623bb6d"},
+ {file = "coverage-7.15.4-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c7dbc748ac8a1e3e59a2b28bea47675e6e778081dbbf081bde0d75def2fcbe1d"},
+ {file = "coverage-7.15.4-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:2413074a5ecbb61a01a7888fc72db0ca324d13588c5b38bc0dd8564cdcdfea26"},
+ {file = "coverage-7.15.4-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4e6f6f632b7b2f714bf7a1346e8f97b650ee71f3c298aaad42a2ab60f0f07645"},
+ {file = "coverage-7.15.4-cp315-cp315t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8df457da2249d3c75ca2e5e835d59c725abfe92d27fdff6cd99eed85b51d5e9a"},
+ {file = "coverage-7.15.4-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:050f66a08805acb5b8a23c6d4a517b1ecf82c08e81ed0e4bd727df065e5c6624"},
+ {file = "coverage-7.15.4-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1587fb771d1ccceef708fdde1e5af8c7ed24b486b61d13a321acb7d8145390aa"},
+ {file = "coverage-7.15.4-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b4f1c3a69ca580f3fbd6b2046915f536d7f586874f25c1bb23add2a3c88d50f"},
+ {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:ffb58d7eff5b7f6ecc6fa21d6288ab7f968a212cb67d682c269c09b9eba3b66f"},
+ {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:d9df165544774574ee004b953023d1bebada1894a80b1052a43d798b0f676e67"},
+ {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:f9de0a24a4079b53e523b5c5e2c5945ec251ab486652659955187cf255a259bc"},
+ {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:150089274bdc9f940628552cb92844e0223c987f1902ab8efe9f45a2ec758d88"},
+ {file = "coverage-7.15.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:a58a94fed5da6997d258e8f7668c1e195fbd04a691d781b7558f1e468f9e68bc"},
+ {file = "coverage-7.15.4-cp315-cp315t-win32.whl", hash = "sha256:ebd5a6d8466ff30836572f3ba2cae8a5e8f85029b1c6d5e2ed338dc472a5166a"},
+ {file = "coverage-7.15.4-cp315-cp315t-win_amd64.whl", hash = "sha256:288bde2a2d7ab6b6c2d7252fcde8b524387f2d970bdba9658fc6f8bbcaef0f9b"},
+ {file = "coverage-7.15.4-cp315-cp315t-win_arm64.whl", hash = "sha256:68be5e1de60ff13c9095bbec0e5a7fa45b33b101752215b91345ea1f61c4a278"},
+ {file = "coverage-7.15.4-py3-none-any.whl", hash = "sha256:964730a1e9de9c0cf11be6a1a3c79ce419c34882842abd256086ba4698705e84"},
+ {file = "coverage-7.15.4.tar.gz", hash = "sha256:0548198fff07ccf4faf469520bce1c2eceb1ce3e62891921138dec10907f9d00"},
]
[package.dependencies]
@@ -1521,77 +1559,67 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
[[package]]
name = "cryptography"
-version = "46.0.7"
+version = "50.0.0"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
-python-versions = "!=3.9.0,!=3.9.1,>=3.8"
+python-versions = "!=3.9.0,!=3.9.1,>=3.9"
groups = ["main", "dev"]
files = [
- {file = "cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb"},
- {file = "cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b"},
- {file = "cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85"},
- {file = "cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e"},
- {file = "cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457"},
- {file = "cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b"},
- {file = "cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1"},
- {file = "cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2"},
- {file = "cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e"},
- {file = "cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee"},
- {file = "cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298"},
- {file = "cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb"},
- {file = "cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006"},
- {file = "cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0"},
- {file = "cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85"},
- {file = "cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e"},
- {file = "cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246"},
- {file = "cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3"},
- {file = "cryptography-46.0.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f"},
- {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15"},
- {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455"},
- {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65"},
- {file = "cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968"},
- {file = "cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4"},
- {file = "cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5"},
+ {file = "cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169"},
+ {file = "cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f"},
+ {file = "cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105"},
+ {file = "cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef"},
+ {file = "cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30"},
+ {file = "cryptography-50.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d"},
+ {file = "cryptography-50.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c"},
+ {file = "cryptography-50.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c"},
+ {file = "cryptography-50.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95"},
+ {file = "cryptography-50.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269"},
+ {file = "cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708"},
+ {file = "cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47"},
+ {file = "cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9"},
+ {file = "cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7"},
+ {file = "cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba"},
+ {file = "cryptography-50.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5e34edd123674534acd70147f0ca331eaa2c74e6325fb2028c886aa26ba0b68c"},
+ {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8eb5e1172eb569ea8a872796576e6a67c276351728b6455d5beb01242b027c6a"},
+ {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:910d11e1a385c654bf738bf3e6b8e6ed5de0f5610fcae2be9e5b398d8081d20e"},
+ {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:62598a8a57f815db4c6259a4e97d857dab56697e7de8e8ab02352ab74da1995d"},
+ {file = "cryptography-50.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:07479a1cb08219ab719147e742e76090c9c773321959bb94946fffdd397a6437"},
+ {file = "cryptography-50.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c99c003e088647b8a5b7c145d6f78c335f6348332b62e142d411c4b63d1460b9"},
+ {file = "cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9"},
]
markers = {main = "extra == \"all\" or extra == \"datamasking\""}
[package.dependencies]
-cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""}
+cffi = {version = ">=2.0.0", markers = "platform_python_implementation != \"PyPy\""}
typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11.0\""}
[package.extras]
-docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"]
-docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"]
-nox = ["nox[uv] (>=2024.4.15)"]
-pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.14)", "ruff (>=0.11.11)"]
-sdist = ["build (>=1.0.0)"]
ssh = ["bcrypt (>=3.1.5)"]
-test = ["certifi (>=2024)", "cryptography-vectors (==46.0.7)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
-test-randomorder = ["pytest-randomly"]
[[package]]
name = "datadog"
@@ -1882,15 +1910,15 @@ testing = ["hatch", "pre-commit", "pytest", "tox"]
[[package]]
name = "fastjsonschema"
-version = "2.21.2"
+version = "2.22.1"
description = "Fastest Python implementation of JSON schema"
optional = true
-python-versions = "*"
+python-versions = ">=3.10"
groups = ["main"]
markers = "extra == \"all\" or extra == \"validation\""
files = [
- {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"},
- {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"},
+ {file = "fastjsonschema-2.22.1-py3-none-any.whl", hash = "sha256:cf377ff5c9a6f4f3125fb35f75a2c5767bd824ffbcf62c209a93cd48d1453999"},
+ {file = "fastjsonschema-2.22.1.tar.gz", hash = "sha256:0b83d1ce8d7845b959dcb20e1a5c3c8883b6541d9c52ab02cce5166b75ec805f"},
]
[package.extras]
@@ -1898,14 +1926,14 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc
[[package]]
name = "filelock"
-version = "3.29.0"
+version = "3.29.7"
description = "A platform independent file lock."
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258"},
- {file = "filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90"},
+ {file = "filelock-3.29.7-py3-none-any.whl", hash = "sha256:987db6f789a3a2a59f55081801b2b3697cb97e2a736b5f1a9e99b559285fbc51"},
+ {file = "filelock-3.29.7.tar.gz", hash = "sha256:5b481979797ae69e72f0b389d89a80bdd585c260c5b3f1fb9c0a5ba9bb3f195d"},
]
[[package]]
@@ -1943,14 +1971,14 @@ smmap = ">=3.0.1,<6"
[[package]]
name = "gitpython"
-version = "3.1.50"
+version = "3.1.58"
description = "GitPython is a Python library used to interact with Git repositories"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
- {file = "gitpython-3.1.50-py3-none-any.whl", hash = "sha256:d352abe2908d07355014abdd21ddf798c2a961469239afec4962e9da884858f9"},
- {file = "gitpython-3.1.50.tar.gz", hash = "sha256:80da2d12504d52e1f998772dc5baf6e553f8d2fcfe1fcc226c9d9a2ee3372dcc"},
+ {file = "gitpython-3.1.58-py3-none-any.whl", hash = "sha256:d331e722577f0fd7fc1f857419b3ecc07af66282b933d2a4d95f84a042fdd50f"},
+ {file = "gitpython-3.1.58.tar.gz", hash = "sha256:621416df10ef3fd0e19fabf9172ddeed0fa704d353d04f194eec56a625a95b22"},
]
[package.dependencies]
@@ -1958,42 +1986,7 @@ gitdb = ">=4.0.1,<5"
[package.extras]
doc = ["sphinx (>=7.4.7,<8)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"]
-test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy (==1.18.2) ; python_version >= \"3.9\"", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""]
-
-[[package]]
-name = "griffe"
-version = "2.0.0"
-description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
-optional = false
-python-versions = ">=3.10"
-groups = ["dev"]
-files = [
- {file = "griffe-2.0.0-py3-none-any.whl", hash = "sha256:5418081135a391c3e6e757a7f3f156f1a1a746cc7b4023868ff7d5e2f9a980aa"},
- {file = "griffe-2.0.0.tar.gz", hash = "sha256:c68979cd8395422083a51ea7cf02f9c119d889646d99b7b656ee43725de1b80f"},
-]
-
-[package.dependencies]
-griffecli = "2.0.0"
-griffelib = "2.0.0"
-
-[package.extras]
-pypi = ["griffelib[pypi] (==2.0.0)"]
-
-[[package]]
-name = "griffecli"
-version = "2.0.0"
-description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
-optional = false
-python-versions = ">=3.10"
-groups = ["dev"]
-files = [
- {file = "griffecli-2.0.0-py3-none-any.whl", hash = "sha256:9f7cd9ee9b21d55e91689358978d2385ae65c22f307a63fb3269acf3f21e643d"},
- {file = "griffecli-2.0.0.tar.gz", hash = "sha256:312fa5ebb4ce6afc786356e2d0ce85b06c1c20d45abc42d74f0cda65e159f6ef"},
-]
-
-[package.dependencies]
-colorama = ">=0.4"
-griffelib = "2.0.0"
+test = ["basedpyright (==1.39.9) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy (==1.18.2) ; python_version >= \"3.9\"", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""]
[[package]]
name = "griffelib"
@@ -2113,7 +2106,7 @@ files = [
{file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"},
{file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"},
]
-markers = {main = "extra == \"datadog\" or extra == \"valkey\""}
+markers = {main = "extra == \"valkey\" or extra == \"datadog\""}
[package.extras]
all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
@@ -2307,14 +2300,14 @@ files = [
[[package]]
name = "jsii"
-version = "1.135.0"
+version = "1.140.0"
description = "Python client for jsii runtime"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "jsii-1.135.0-py3-none-any.whl", hash = "sha256:bfab0cc3f99bfbc13683af2afb8d62522af867fb826fc825ab6b27fe636bb087"},
- {file = "jsii-1.135.0.tar.gz", hash = "sha256:3d860404e9e350beae0bdae48b473173653bd2be3a901c620feb656b690f9c2f"},
+ {file = "jsii-1.140.0-py3-none-any.whl", hash = "sha256:aa24f27d15d8d7db1ff32a9c56074bc87e728b30330ead97fb149419a3721a50"},
+ {file = "jsii-1.140.0.tar.gz", hash = "sha256:454c874d963a862f6b90bc013c45a720e51292659f57249d9cae7cb2a189ec0e"},
]
[package.dependencies]
@@ -2404,103 +2397,150 @@ referencing = ">=0.31.0"
[[package]]
name = "librt"
-version = "0.11.0"
+version = "0.15.0"
description = "Mypyc runtime library"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
markers = "platform_python_implementation != \"PyPy\""
files = [
- {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"},
- {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"},
- {file = "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"},
- {file = "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"},
- {file = "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"},
- {file = "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"},
- {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"},
- {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"},
- {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"},
- {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"},
- {file = "librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"},
- {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"},
- {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"},
- {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"},
- {file = "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"},
- {file = "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"},
- {file = "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"},
- {file = "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"},
- {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"},
- {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"},
- {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"},
- {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"},
- {file = "librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"},
- {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"},
- {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"},
- {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"},
- {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"},
- {file = "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"},
- {file = "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"},
- {file = "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"},
- {file = "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"},
- {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"},
- {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"},
- {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"},
- {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"},
- {file = "librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"},
- {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"},
- {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"},
- {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"},
- {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"},
- {file = "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"},
- {file = "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"},
- {file = "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"},
- {file = "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"},
- {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"},
- {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"},
- {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"},
- {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"},
- {file = "librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"},
- {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"},
- {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"},
- {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"},
- {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"},
- {file = "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"},
- {file = "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"},
- {file = "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"},
- {file = "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"},
- {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"},
- {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"},
- {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"},
- {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"},
- {file = "librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"},
- {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"},
- {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"},
- {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"},
- {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"},
- {file = "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"},
- {file = "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"},
- {file = "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"},
- {file = "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"},
- {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"},
- {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"},
- {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"},
- {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"},
- {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"},
- {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"},
- {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"},
- {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"},
- {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"},
- {file = "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"},
- {file = "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"},
- {file = "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"},
- {file = "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"},
- {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"},
- {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"},
- {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"},
- {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"},
- {file = "librt-0.11.0-cp39-cp39-win32.whl", hash = "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"},
- {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"},
- {file = "librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"},
+ {file = "librt-0.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e1a49adf16a7c9d9646816c2946135527197b6fcf4347c7b8b761cf1bfbf4489"},
+ {file = "librt-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81a398f45b45a59200e13cd5ad1ae1d3f44334de98b148331afe2cdfee701c52"},
+ {file = "librt-0.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4eafbaff06b9563f8b1c850621ce51605de05208e09d4d71ce490bc972b7b9e8"},
+ {file = "librt-0.15.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:b0411b4066db926b80258c60dcb0e6db4c9cee312eab45b7e8866b17ddf9ada1"},
+ {file = "librt-0.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:febb1ce6cac545a54e6b769982824e955a700fdd9fbf3a08a3d82c990968b57d"},
+ {file = "librt-0.15.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b230acc1c3bfe2d6f2627ba2b95dc92e58aa494600e9722d0e6ccbc931e59702"},
+ {file = "librt-0.15.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6da110e5f314c19ab8478464d02ae18808ae73d522c15260fa4918acdcd64da9"},
+ {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:eab9208b00ca55bf75983ec99f7bf13acc746a36102e98953addaad7f7ea1e1b"},
+ {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6c013cd3a1721e69e14380ada97eaa4b7b0cdf1c6b96fa765d4ea47c875088db"},
+ {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:567b1c430f8bd560e689421468278ac5941bab4a05303b5d95b6ae10db03f451"},
+ {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:29c4cab9df457b19672c39be7f384ebb2bc925c4e2684b8780c222b43eb36389"},
+ {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bccbd8e5b0bffb7106cf18eb1baa3d7194b1cebb3b4b1cdbd4bdb19382a6ee6c"},
+ {file = "librt-0.15.0-cp310-cp310-win32.whl", hash = "sha256:8ae493ed5f659a7761c43d42f183db514536073ded9bcf671d2d1df47e29a07e"},
+ {file = "librt-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:bc25fb356d0c7810bb49ff3df908ad1fda6995d660ab099ded69244ed7ab6053"},
+ {file = "librt-0.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:823b92cf3c18ecd08afc70c42473888b41b6e8ef5046f3b82c05c154a2fa3d22"},
+ {file = "librt-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70bc1b602cf59917e8f0c7a2cbc8bcc6fbc14d5486136b00707a79619121d63"},
+ {file = "librt-0.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:814ff83a25b5fce8b9c80c4dd803153fb5c5599fc74db9e022466938368957ef"},
+ {file = "librt-0.15.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:57f5eeb6ad4c180de583b1038e61fe5fbd9796bb69a8a1c1a0c7ddbec4c8c60f"},
+ {file = "librt-0.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82909c8f7eb9952656b65d3147afde4cf8e6d5a991eebc86418b5e65843b0ab8"},
+ {file = "librt-0.15.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f779070399f991400fc451719e0ea388eb7de313388bada2c127a35de05f798a"},
+ {file = "librt-0.15.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bac89069bc496ebdf4f79ebb57bbd10d0b214c8454225deb672d91002bd17e18"},
+ {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e0d00c708fb2f5822b152429b1ac80a58dbbbc3f6c232c4d13a3f7fcf2ea5b4c"},
+ {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6c6624fe268625869485553dd7cc1daf30d22558215bb2a4ff16f67a9801a31a"},
+ {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f56b397858a23dacf35ede366ed2212fdc03a6a57a1ad36468ad6e9dc5fac091"},
+ {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4388184646efe2054911c5b00a1077d6d1ee86a95b7e8ba96dc7850a809f3f40"},
+ {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97335f59082f9fe2ce6c2a9cc6433a0114bbb6cd4d5c09dd76c95c68b9f9a8b0"},
+ {file = "librt-0.15.0-cp311-cp311-win32.whl", hash = "sha256:83380ffde38062a2e9bb55d83e74474f6614665528b98a6928720fc006dfffbb"},
+ {file = "librt-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:f75720477ee05d509a310e856cacc8d909adc182f7b91193c207bcc26d7ee6db"},
+ {file = "librt-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:256237037a3ab001ae8d9803b2d43562a4c3aa38739843694349e4d5ebb0fd56"},
+ {file = "librt-0.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e87bc679f86a99aa3b26e3c78eeb821a247c9a28eae48eaafcc32c3bf4c3bb9e"},
+ {file = "librt-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71599e011ac880e8e45d46047d714871894c7d4ab6f25626f8d4f89da21f368d"},
+ {file = "librt-0.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c802434092b769b1d613ed2e13fac15fbfce1934a74bd10283b03c0fae231cd1"},
+ {file = "librt-0.15.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5500eeae393a184d14e1f35645962c27129d20c81afa4069e6ef826ebc2b3aaa"},
+ {file = "librt-0.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6ecfc32dfb46fb7b565bcd6abf9412acf978775a998273d22888a6d7953730dd"},
+ {file = "librt-0.15.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cc46cfd15022e35084355478c9ac809d90b1152222706ac9a7655ec21df6fa"},
+ {file = "librt-0.15.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d5f51401d102c885b9ca509e62c79b1dbff286e1b9b047fde6f763780789356d"},
+ {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cc30523e3f1a23fb7511cc659834a0d01a1042bb9de359bc1c131cc4ec6c9656"},
+ {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:59fe030d8ae4a57e3fb7756bf35a858de74e04066fc8555c53d0af979132af81"},
+ {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a6526a2a956bbb1e4ae3568c82e650fc99119c66bb011ea60715744955a2b4d"},
+ {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:85ea21ec6730194d67156b0e0b5430ccb1d61f8b8b907e39b37f9812b74a13f0"},
+ {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1e47b8ba865d7ede071a91a7163073bbaeb72541f1ef8a07d512c45c7b5007f2"},
+ {file = "librt-0.15.0-cp312-cp312-win32.whl", hash = "sha256:a5207ec414d1c4a2a7231b2086970dc036f94293cdf338190984958a013a42f1"},
+ {file = "librt-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:73b30cfa976659b3917c8f6153bdb0591c6a9ec6583599fd24a689b690622022"},
+ {file = "librt-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:a54cf9e0ef47b96af580849db5471142200568ce1e02cbf416addab551369570"},
+ {file = "librt-0.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:db13ca398005abcbe538deda87b686d9bd08b7001cf40c4c06b444960ae10a26"},
+ {file = "librt-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa1f1995789dca3698bc550aaceb09a51bd5df0a057ff84ff15296cd1975b801"},
+ {file = "librt-0.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55456ea87d8df21808446d03817be2f65e20391c1c615d9187440dff28cd08dc"},
+ {file = "librt-0.15.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5a86a5a08c2235316bdb359d5dbb6ce0abfca7fac06363103e2c5af571d92f95"},
+ {file = "librt-0.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e56b6a368529bed262da40ce13f8fef590db0479819cca84f16a1f01ac356d0b"},
+ {file = "librt-0.15.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:234d8d394721fa0d786af15ebf1f3fb7f3ed82fd1cd0cde45c2f247b5d4281d2"},
+ {file = "librt-0.15.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d8363d7accb0286ac3a0e633f396e93800dafb8150494505daf9515bbda591f3"},
+ {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0f0ee3644d951f31055ad07d77d92520e84505dd7a432cc4cd501dd70ee06785"},
+ {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cfd1a81a648806e6a7717be4cc4d1bb392fa229752bf8444ba365e381e984d6"},
+ {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a6cd22c9da0d866558e46a041f1cc0c2bbb26b61b137b2347fa834c332e1d101"},
+ {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:6d5225ef8801e4ea5e482fa9b5dfb891dd9ef6f6d870f1f25d449ca2c70ac218"},
+ {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d28a05796b99f749bf8794f17ba9ba1612d0076b802e9cfc62c554634e9ce3b"},
+ {file = "librt-0.15.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:2067ff438048cead9d223ca5675bae2a25e520a7c3e6c1498bf9c6892d22caab"},
+ {file = "librt-0.15.0-cp313-cp313-win32.whl", hash = "sha256:1cd3b721f24c206398b9e26da3c3a9c011e6e89d06f318ba8ebefc30f1003890"},
+ {file = "librt-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:f395a4a9a03ac062dbe9a9f82e0c720502e590a38feee6a757bc82e9c63afbd8"},
+ {file = "librt-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:0a15cb554761247d84a3ec0cbdf4078d70725384f0e4662c0fa3b26266eb60ad"},
+ {file = "librt-0.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f5de7feedc56337a088eb15cd9fafa9938367362221d8cc62c642b7f94821993"},
+ {file = "librt-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c0eb900c0e91f4aebe680845242e614f1864edfd44106380d0752ac29522bf8"},
+ {file = "librt-0.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e8c9a650a188e38bac005048cbe6342e81407782944d01934540ab75e417df21"},
+ {file = "librt-0.15.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:92bfed8deec93df30286b9fe9e3b1dd17329cc076a192b4ee5ec223841d54953"},
+ {file = "librt-0.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec4b19788f835711a2072f9dbe6b03b3bf32ed1f0fb30cf399bdd59d9f0c33fa"},
+ {file = "librt-0.15.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4c7bacb70930f3d0a56f4ecf1be474a1f0d941b01dd73b756f3c256d42cb879"},
+ {file = "librt-0.15.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3e79f05e4a08b4d880342673312bbc895b56df7765605796f15902eb5367d3ae"},
+ {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a417149c0cba4d50b61e992e5a15e69eaf96746609b461cc4ed168aeef6b79dd"},
+ {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:da7a94d6a3411f579d72aa3e3bc5fbca7ed4549f3dbd7e5de3aa567333374285"},
+ {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:856f743ae607f2c1380eccb566c0038a9fb3eabf0fc2be2704d76d9f73557239"},
+ {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:779a6e7c894737e5983e7790a9c78c4000c30e23c9aada08081bdbea53b0fa60"},
+ {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:96bb17dbe8bab3c0954fbebfc69ed395599de75b6bbc35e3270a878e15d4dd65"},
+ {file = "librt-0.15.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:7220697efaa6e5348fc3d18ee7f8563d4bfecd9872b37ffb915bfc1d08840622"},
+ {file = "librt-0.15.0-cp314-cp314-win32.whl", hash = "sha256:f54598964d357b1c5ab77cf5d92f21e598fe0e23cdbe9618480807f81b4eba15"},
+ {file = "librt-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ff5893a2c23d886aa9ce786de5ac6ddc74aeeaf90743682b74d920e117d2e28"},
+ {file = "librt-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:3722a099730704c9a3d70c879fc0f51daec25fe5f1555672d97bc595abeafb95"},
+ {file = "librt-0.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:38c0c7d4b6fc06c3324b3f9162c8391bfc4fd9dde53afe1033ce7edb48d5a714"},
+ {file = "librt-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8b2fdd7ead3c995c37940a790690660d0ca006c302db26cc51933f6766866fc3"},
+ {file = "librt-0.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fde98cf1fc4bac144ce23c2c4c017b924ba714509ea9334977b0b27050c837d"},
+ {file = "librt-0.15.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:e3b461183c5fa7681b48560f91515f53a953122fb30c71e07abc67d7ddf58c38"},
+ {file = "librt-0.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4bbcc257e3babea20a91715c361b24554ec4e8f51aa578568afc230799fe1a19"},
+ {file = "librt-0.15.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b845b8d48088fad0cadc84be4b8fda63203be7e9237b71015b3925443c1f35ab"},
+ {file = "librt-0.15.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b30e600e8f337b9bd7f39b86d9fdfedc73cc46e3d0f745931a23a234220bb7e2"},
+ {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:64b0c8c35aa4c4ed79896359f3e0b285cbe4e610042106500da4811c322cc108"},
+ {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0da0d94cb802f32a0524653e7201f2cef72d5f700a5407678f5290483d4fcd08"},
+ {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4a6369168d371207339b1e50d4532b06a7121586141f82599505a3f315751d47"},
+ {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c434e072557ade9cbc642d052c89d031efe47d5c9614523619d0d74a02378e81"},
+ {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7eec6a42018bc1d45763b1c162d3d2bf7c3b9a1b0ed30d3e91dcba390efefcc"},
+ {file = "librt-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:6912fa5e635d74529ac7cdb1bdf6ca3af4453da8d1edbe0110ee1cb4ad407ebf"},
+ {file = "librt-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8e11699ed745931c395acd3621b07062e0f840efa6935aad87a64ed0995f0915"},
+ {file = "librt-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5d2a91724463bfed4f573cd7a9fdc856d2e230d0c0e5a61416a93481dccd8605"},
+ {file = "librt-0.15.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:8443e38dcfcfdbcf5add5118c623efd788d65ac2e25756d6251a54a06a4d0aca"},
+ {file = "librt-0.15.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:6d15a29033c57490cfe2069097c6fc4049e4e65ffbb749be7dc453b7c4c68965"},
+ {file = "librt-0.15.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2c05c729b589e734c09578bf5964be48a911765484840d017bbc84f49d4c4ad"},
+ {file = "librt-0.15.0-cp315-cp315-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:fa60887537e1d0cd2d9982269d33a709bf54b195cd2b9364fc0a758022af5bd9"},
+ {file = "librt-0.15.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d8bc24219b24c0af375718942ab75e3544b2763085f40f965be4326734ae8328"},
+ {file = "librt-0.15.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86a21a7bd3fe3a419512ef424cc1c020f6771d0b29cfddff36d1635a855e63f0"},
+ {file = "librt-0.15.0-cp315-cp315-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dbab647e88d90b3167b91efe7091e248653688ed4337e4f90907a722c7361bb9"},
+ {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:d8edcf6f550e918dca779c069b9e156385c60b406f99fc7641f32c52f7193659"},
+ {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:8b62076030baa2d8b1501a46bf0e19c27a489aa90671c55665bff7887f7660b0"},
+ {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:d00d20d1818e82a07a0ee0aa89a98b17ed7916b92441090b683719cb20a59b6d"},
+ {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:4e6ee93fc3cf848dcbf0cce2eca73d8e7dcd0cc2b6df3a529d57750b30a4c55c"},
+ {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:32896a0af72508ea979e0acb4e4c04cbeeae04938167950d535c83c45597167d"},
+ {file = "librt-0.15.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:ec3ba415afaf951f6951b1dd16d3c8e4f540065fc382d7e70b823a79567ca374"},
+ {file = "librt-0.15.0-cp315-cp315-win32.whl", hash = "sha256:d2813ba2503764f0450680c533d13df7cff9b49df1411062eded5f67db4195b9"},
+ {file = "librt-0.15.0-cp315-cp315-win_amd64.whl", hash = "sha256:b87d67e33afaf265262f2a66db578284b88ee2e6fcd224579cb5c15518677ad8"},
+ {file = "librt-0.15.0-cp315-cp315-win_arm64.whl", hash = "sha256:713bd7df21170b982e729e46870f31d6b437bd1a9b4648cffb529bd3c2ec5c4b"},
+ {file = "librt-0.15.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:3de789c82752730f94782a5ee518baf9c05edf85733aeaf73bb6e518755cdf54"},
+ {file = "librt-0.15.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:e0b5deec9a8664eb722c797241970fd4aa1894d25fda36a1ddac0f7407606bd6"},
+ {file = "librt-0.15.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5563302a8359bc2295bb7084d1a8ed1519df96afb30eb2aa4e0bff7b54228988"},
+ {file = "librt-0.15.0-cp315-cp315t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:22d6263b9d39d7bbb286fa791945646e3218f1be2d693e36fb630f1d0e59cd13"},
+ {file = "librt-0.15.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39ffd14646190c454f0d86e0d256b33f00a87a26ab410e619773b841d0e41416"},
+ {file = "librt-0.15.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47318cd3a61401452de11282242937e3e057c4fd3dbaf601e269d0928a06c0a"},
+ {file = "librt-0.15.0-cp315-cp315t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a56a1d4f859a82ca5b99fc4b82c9b027b15e3c455c5cd99e7d0719f27bb20b6c"},
+ {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:077471b3182db4e17c36ae91555f36a4d2c00080b267f749bcad34a478a9a302"},
+ {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:411ca4d1b905b860ceba7570dd6717a71dedaddcc4b0f77ece710aa41ee11f8d"},
+ {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:1256589e0b0adb31751d685a68bce29d73407ddf4ef05d4188f49d5dcf9566d9"},
+ {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:f42b74a53e5f26a0ba0007411a7455b66c67ce4022a39cc1f56fc4efd65bcbab"},
+ {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:291bf73caf78b9e88d6fae9bfd693207ff7d832e2fdbe2cf8e746bc13f5f892b"},
+ {file = "librt-0.15.0-cp315-cp315t-win32.whl", hash = "sha256:c16d15ee371643ab48dc8248a3e680ebbeca573a13af2c3dd0c985b142d77162"},
+ {file = "librt-0.15.0-cp315-cp315t-win_amd64.whl", hash = "sha256:dbd605739f228912dc49027cb764456b9757750bdc2b6b7773164db7096c6fd1"},
+ {file = "librt-0.15.0-cp315-cp315t-win_arm64.whl", hash = "sha256:84d244b00604d17df3fc7736c327892d6bba66181254aa4087be807b6c342bdc"},
+ {file = "librt-0.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0e2d0c0acf5b0ada7d045912b7cf787c21315c95b38b1fa939ef72d45d366b3d"},
+ {file = "librt-0.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9ca190fe9edc0eb08eec558a509a16d28d91c35667b8f043cba40ed5e77a959"},
+ {file = "librt-0.15.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80811e1c42386ea95c6fb30571d3250ad43d7863f883f787f70517f441150e59"},
+ {file = "librt-0.15.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:88c2a17815c266e6d8180204ff62cb739ab869ada4a746d4c505331526ac58f1"},
+ {file = "librt-0.15.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a5fa8f1f916988d0bf1afea005bda37f56ac41a18016e813ccf0097a8d460ca4"},
+ {file = "librt-0.15.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:355e3a4c725225a14262004fc1872a552b9d3634b4f791a0dfc80804aafbfd55"},
+ {file = "librt-0.15.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc1ed11c4ad0b91af24def2050f2840ea4567828e3dd058fbe608d982f6e5465"},
+ {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1f4ef2e71db33df4309167ed7f1520c4fae5e611226e159fa9cf33f93e6ddb3d"},
+ {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1a1a8cd430c7dd0c083f455cb1b328d7fc682b05c31b940906f7845bdff80881"},
+ {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:04d5387b908676c0b8d5d2f5fb58373b4ea382d81f7a6f0fab8ea2a462bb4738"},
+ {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:1172c6ad2a88b646e7fe3b480e3fac4ab4418b3443fd8a4061fdd531e0622fc7"},
+ {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:52e8db01f603f5da0ca30987479acff98769382efc8e142fa3962395dcf3ffdb"},
+ {file = "librt-0.15.0-cp39-cp39-win32.whl", hash = "sha256:e4c911f15a1652ca94ae9f1abd92e74cbb1b3597d2d92fdd556202f94e8cd455"},
+ {file = "librt-0.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:68242379c9b65a582b6e97318a1e9fbd6d445e58954f2d437991c4804ab11578"},
+ {file = "librt-0.15.0.tar.gz", hash = "sha256:4e66cbe84437497d951b799d3e1551291b6fb3d643820a7014b3655d57a59162"},
]
[[package]]
@@ -2816,14 +2856,14 @@ mdformat = ">=0.7.21"
[[package]]
name = "mkdocs-material"
-version = "9.7.6"
+version = "9.7.7"
description = "Documentation that simply works"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
- {file = "mkdocs_material-9.7.6-py3-none-any.whl", hash = "sha256:71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba"},
- {file = "mkdocs_material-9.7.6.tar.gz", hash = "sha256:00bdde50574f776d328b1862fe65daeaf581ec309bd150f7bff345a098c64a69"},
+ {file = "mkdocs_material-9.7.7-py3-none-any.whl", hash = "sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f"},
+ {file = "mkdocs_material-9.7.7.tar.gz", hash = "sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855"},
]
[package.dependencies]
@@ -2883,18 +2923,18 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
[[package]]
name = "mkdocstrings-python"
-version = "1.19.0"
+version = "2.0.5"
description = "A Python handler for mkdocstrings."
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "mkdocstrings_python-1.19.0-py3-none-any.whl", hash = "sha256:395c1032af8f005234170575cc0c5d4d20980846623b623b35594281be4a3059"},
- {file = "mkdocstrings_python-1.19.0.tar.gz", hash = "sha256:917aac66cf121243c11db5b89f66b0ded6c53ec0de5318ff5e22424eb2f2e57c"},
+ {file = "mkdocstrings_python-2.0.5-py3-none-any.whl", hash = "sha256:30c837bbff016549f659fcba6539ac351303f0fd7e713c89a040611072236e9d"},
+ {file = "mkdocstrings_python-2.0.5.tar.gz", hash = "sha256:3a4d92556ad39637e88af94a5374213af9a8e3040c3824ceaed04b486c017594"},
]
[package.dependencies]
-griffe = ">=1.13"
+griffelib = ">=2.0"
mkdocs-autorefs = ">=1.4"
mkdocstrings = ">=0.30"
typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
@@ -2948,61 +2988,69 @@ dill = ">=0.4.1"
[[package]]
name = "mypy"
-version = "2.1.0"
+version = "2.3.1"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "mypy-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:11a6beb180257a805961aea9ec591bbd0bd17f1e18d35b8456d57aee5bedfedc"},
- {file = "mypy-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ef78c1d306bbf9a8a12f526c44902c9c28dffd6c52c52bf6a72641ce18d3849"},
- {file = "mypy-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c209a90853081ff01d01ee895cafe10f7db1474e0d95beaeef0f6c1db9119bbd"},
- {file = "mypy-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47cebf61abde7c088a4e27718a8b13a81655686b2e9c251f5c0915a802248166"},
- {file = "mypy-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d57a90ae5e872138a425ec328edbc9b235d1934c4377881a33ec05b341acc9a8"},
- {file = "mypy-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:aea7f7a8a55b459c34275fc468ada6ca7c173a5e43a68f5dbe588a563d8a06b8"},
- {file = "mypy-2.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c989640253f0d76843e9c6c1bbf4bd48c5e85ada61bde4beb37cb3eca035685e"},
- {file = "mypy-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a683016b16fe2f572dc04c72be7ee0504ac1605a265d0200f5cea695fb788f41"},
- {file = "mypy-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a293c534adb55271fef24a26da04b855540a8c13cc07bc5917b9fd2c394f2ca"},
- {file = "mypy-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7406f4d048e71e576f5356d317e5b0a9e666dfd966bd99f9d14ca06e1a341538"},
- {file = "mypy-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0210d626fc8b31ccc90233754c7bc90e1f43205e85d96387f7db1285b55c398"},
- {file = "mypy-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3712c20deed54e814eaaa825603bada8ea1c390670a397c95b98405347acc563"},
- {file = "mypy-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fcaa0e479066e31f7cceb6a3bea39cb22b2ff51a6b2f24f193d19179ba17c389"},
- {file = "mypy-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:0b1a5260c95aa443083f9ed3592662941951bca3d4ca224a5dc517c38b7cf666"},
- {file = "mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af"},
- {file = "mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6"},
- {file = "mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211"},
- {file = "mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b"},
- {file = "mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22"},
- {file = "mypy-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b"},
- {file = "mypy-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8"},
- {file = "mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5"},
- {file = "mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e"},
- {file = "mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e"},
- {file = "mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285"},
- {file = "mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5"},
- {file = "mypy-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65"},
- {file = "mypy-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d"},
- {file = "mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2"},
- {file = "mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f"},
- {file = "mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4"},
- {file = "mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef"},
- {file = "mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135"},
- {file = "mypy-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21"},
- {file = "mypy-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57"},
- {file = "mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e"},
- {file = "mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780"},
- {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd"},
- {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08"},
- {file = "mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081"},
- {file = "mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7"},
- {file = "mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6"},
- {file = "mypy-2.1.0-py3-none-any.whl", hash = "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289"},
- {file = "mypy-2.1.0.tar.gz", hash = "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633"},
+ {file = "mypy-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:57a936373fc690c43a8cd7e7e12a35148e4ec5aa7698ad7fc0a9f918bdc5be41"},
+ {file = "mypy-2.3.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d00d769056bde2f4e69c175071eba45cfb44fa1ed92bdfbfe64a93e0543b0cf0"},
+ {file = "mypy-2.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2166b29228835e1f88ff411e96639e6ca3c7fdde84b62ec211f70f86b4051167"},
+ {file = "mypy-2.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:83d36c2924df7426333abe7faf4724a7e1aab0d9fd41625e81b4683034b80c13"},
+ {file = "mypy-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:f12fdb70459d0060dea40b29e52163a961b156106d68d57882a6a9f648983a53"},
+ {file = "mypy-2.3.1-cp310-cp310-win_arm64.whl", hash = "sha256:e099200a1b1b1223a4951f0a90cbff1b8c91b250ba599dab1f7217a628144d90"},
+ {file = "mypy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94f04929f1c44c35fb0061e912087edaf504acede963a4a7d00680bd089d8531"},
+ {file = "mypy-2.3.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f5d716048611e85ca9eefb2e1baa5d73ede389b5820ded260ea27c757d667af8"},
+ {file = "mypy-2.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b091a455111214cb5c9d54a57b9618e9a49f9fe2a42e4e1ac86e9d104ed96ce8"},
+ {file = "mypy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:df12e20c9efd614738c71b390007ecd0181125afc4ccafca04d78a1d2eed2c01"},
+ {file = "mypy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:52eaf3a155f35cf80b40220288c861eb45f14a2340c1f6cbfbdb0feff32879d1"},
+ {file = "mypy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:9b4eacbee8a69836c06eff6d0dd4e134a07c2b047755b30c08625fe214f322c6"},
+ {file = "mypy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a32bbbb940af990d3be0b8af321c7b6815bb1b3b48142fe7459b9cc5f58959ff"},
+ {file = "mypy-2.3.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff715e45b2231a8e85de1d163d1b42791e4d7aab8f5145f85fee1b710b735aff"},
+ {file = "mypy-2.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:858fc57d3d91fa728e33e7ad71def60fc6272694607b306cd3292db53ae39080"},
+ {file = "mypy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:851833db876e7b650f93719c74b7879a08e338979c96054fdfc3bfd90a486355"},
+ {file = "mypy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:4c5095a327483591c94e0c8d3ef9e50d4ab1369b541eae007c1f23bc2a41f6bb"},
+ {file = "mypy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:bbfe022634a2a195406bd469e888d2eaf193b02ba7e607391cd7640374aaae3b"},
+ {file = "mypy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:114dff494000f18bd10d5d95d84b8567b26da60279ecbe838131841df20e635d"},
+ {file = "mypy-2.3.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8637731bb5eee3671eb2c3200827aa3564ed8a9309ecee4d1afe77e6d031bdb"},
+ {file = "mypy-2.3.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c80fbc405ed8020f5ff3802dc18cf060197bcdd3fbdd6a26ef2fd34dfdd5226"},
+ {file = "mypy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:84081f538ce27375045c02e3d7f81bd11d853400621ae245d87ce7b6c420ec74"},
+ {file = "mypy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:e9144ac16fde007096f9563eb2041b4433c2d705c4218edeb79e7e9d01035ee6"},
+ {file = "mypy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:77ad9529e67dca28e511f5cd5671436584ce91f6d3bac159a353158187b986ac"},
+ {file = "mypy-2.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:192abaedf75da1bc0b1cef104927e70ec49c1ef0031cc4825c7ee10a438ed24d"},
+ {file = "mypy-2.3.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf678dffd16efcda2c15cbd30e9ecc0081388e29ea23687a88e686ed92638dc3"},
+ {file = "mypy-2.3.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e036f06b41630f4c8a1d48f9ac6aa26acc65f8be089973f5519da643318f03f"},
+ {file = "mypy-2.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71af9c8a894e862b58e92abb08e53b05a384a1e5e5d6dc7cda59126211a53d82"},
+ {file = "mypy-2.3.1-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:3c80cd23d85368bdd9f37d5231dfd97d35bcbf5bf41af96ef3a9b078ad1957f9"},
+ {file = "mypy-2.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:4956f34d145e145562a0a0bf367f642bbc85c04ec2baf47ae015947c3169a85d"},
+ {file = "mypy-2.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:cfb12e360242d23d91f5e978d94f58ea66acf5804c4fb6f2f794a20d4cb1b595"},
+ {file = "mypy-2.3.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5f1c50bb05b64e2026b52867e8d21106f01313c744a2c4ecc34c90d12e8d6e2"},
+ {file = "mypy-2.3.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:667196b352f4cf304ded4c10f90cfc179263a1acfb3cdcfa984bdfd340d498bc"},
+ {file = "mypy-2.3.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b9c53e395c12cad2c6d4b67d5da7c6057638a132d85c08b73646b18f802a0045"},
+ {file = "mypy-2.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:18162b128c3f9c703cd35f5537446900b0d21a2549aa7a95d21380d2ef643fb0"},
+ {file = "mypy-2.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:30c0477d4aab7b7f39c8397dc877f2c96b9fe5588ec379f372c56eb63d599f63"},
+ {file = "mypy-2.3.1-cp314-cp314t-win_arm64.whl", hash = "sha256:6941ab3619377bc3f32ca02876b07d27f216f5201604b664d3937ea0fdd23bb4"},
+ {file = "mypy-2.3.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:6f041a6de52c9217ca125e78ba0a335cb7fd98a1c0580978e49ab2b126f70b57"},
+ {file = "mypy-2.3.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5159ae60f5dbc3a498af5ba8365505808ac8031bc63f9e00304ad545d40bdd9b"},
+ {file = "mypy-2.3.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47a8a7a0a7f6f6e63995c0ac36fa0c07b127413fdc81f0439b7f3dccafd33561"},
+ {file = "mypy-2.3.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:2329c0501293d4e1f33bc15d04d6304d65a1cdda967ee93a05c1e681a3923133"},
+ {file = "mypy-2.3.1-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:bb26deed807bdb0457cf3e3f1cd7c4a1cf9d66864eaf1b4a61e06805d4c6b1f9"},
+ {file = "mypy-2.3.1-cp315-cp315-win_amd64.whl", hash = "sha256:375d7013876a8233b2d05be185bfa09f689696cd999ce8b1cfe6acac5c80e8a3"},
+ {file = "mypy-2.3.1-cp315-cp315-win_arm64.whl", hash = "sha256:586b3612214cceabb3c0f588c97e7d1e535393f06a60e912e994f6b3ace97523"},
+ {file = "mypy-2.3.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:ef0c6335cda9d807f8193d8ff6204a72bc909fa9882aacbca14f43cdb7188306"},
+ {file = "mypy-2.3.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e598c8c66401d26b150872154a286e6d484cf2789c3bb28a7556806298423021"},
+ {file = "mypy-2.3.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eda22fd4efa9dcd39331d1dede9b5b8b8a7fd69af07592e778433da98610d29e"},
+ {file = "mypy-2.3.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:2a0ba2e57847849fb0d1fcdabb32786d223095ed8bc121dfe322bcdb3d9c46bc"},
+ {file = "mypy-2.3.1-cp315-cp315t-win_amd64.whl", hash = "sha256:3f7e865dd51f235f60a2dbcd8728a1c095f5ca28f095d48a725b84cd935735c4"},
+ {file = "mypy-2.3.1-cp315-cp315t-win_arm64.whl", hash = "sha256:8ad80807dc3ab8ea978b1b2b6e4a657194ace1d4ef03e0e731aff1abd517da29"},
+ {file = "mypy-2.3.1-py3-none-any.whl", hash = "sha256:6ed5c7e3419083268e5c9258bd1c1ef91af44a9e89374dbcaf37b775716e72eb"},
+ {file = "mypy-2.3.1.tar.gz", hash = "sha256:47c1b1207258513a9d93495f69c8be9de73916186f0e52703e8c461b7a623419"},
]
[package.dependencies]
-ast-serialize = ">=0.3.0,<1.0.0"
-librt = {version = ">=0.11.0", markers = "platform_python_implementation != \"PyPy\""}
+ast-serialize = ">=0.6.0,<1.0.0"
+librt = {version = ">=0.13.0", markers = "platform_python_implementation != \"PyPy\""}
mypy_extensions = ">=1.0.0"
pathspec = ">=1.0.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
@@ -3308,6 +3356,22 @@ files = [
importlib-metadata = ">=6.0,<8.8.0"
typing-extensions = ">=4.5.0"
+[[package]]
+name = "outcome"
+version = "1.3.0.post0"
+description = "Capture the outcome of Python function calls."
+optional = true
+python-versions = ">=3.7"
+groups = ["main"]
+markers = "extra == \"valkey\""
+files = [
+ {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"},
+ {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"},
+]
+
+[package.dependencies]
+attrs = ">=19.2.0"
+
[[package]]
name = "packaging"
version = "26.0"
@@ -3384,20 +3448,20 @@ testing = ["coverage", "pytest", "pytest-benchmark"]
[[package]]
name = "protobuf"
-version = "7.34.1"
+version = "7.35.1"
description = ""
optional = false
python-versions = ">=3.10"
groups = ["main", "dev"]
files = [
- {file = "protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7"},
- {file = "protobuf-7.34.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b"},
- {file = "protobuf-7.34.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a"},
- {file = "protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4"},
- {file = "protobuf-7.34.1-cp310-abi3-win32.whl", hash = "sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a"},
- {file = "protobuf-7.34.1-cp310-abi3-win_amd64.whl", hash = "sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c"},
- {file = "protobuf-7.34.1-py3-none-any.whl", hash = "sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11"},
- {file = "protobuf-7.34.1.tar.gz", hash = "sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280"},
+ {file = "protobuf-7.35.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6"},
+ {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799"},
+ {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4"},
+ {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4"},
+ {file = "protobuf-7.35.1-cp310-abi3-win32.whl", hash = "sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30"},
+ {file = "protobuf-7.35.1-cp310-abi3-win_amd64.whl", hash = "sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87"},
+ {file = "protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9"},
+ {file = "protobuf-7.35.1.tar.gz", hash = "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a"},
]
markers = {main = "extra == \"kafka-consumer-protobuf\" or extra == \"valkey\""}
@@ -3414,15 +3478,15 @@ files = [
]
[[package]]
-name = "py-cpuinfo"
-version = "9.0.0"
+name = "py-cpuinfo2"
+version = "10.1.1"
description = "Get CPU info with pure Python"
optional = false
-python-versions = "*"
+python-versions = ">=3.9"
groups = ["dev"]
files = [
- {file = "py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690"},
- {file = "py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5"},
+ {file = "py_cpuinfo2-10.1.1-py3-none-any.whl", hash = "sha256:adc53396bfb206e6498d078ec2ab407f85799ecd819584ac36a8f80a2d4d762d"},
+ {file = "py_cpuinfo2-10.1.1.tar.gz", hash = "sha256:7861133863663f16e06eca63b12904ef100b5760415e92372dac0162799a4771"},
]
[[package]]
@@ -3436,7 +3500,7 @@ files = [
{file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"},
{file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"},
]
-markers = {main = "platform_python_implementation != \"PyPy\" and (extra == \"all\" or extra == \"datamasking\") and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""}
+markers = {main = "(extra == \"all\" or extra == \"datamasking\" or extra == \"valkey\") and (platform_python_implementation != \"PyPy\" or extra == \"valkey\") and implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""}
[[package]]
name = "pydantic"
@@ -3597,15 +3661,15 @@ typing-extensions = ">=4.14.1"
[[package]]
name = "pydantic-settings"
-version = "2.14.1"
+version = "2.14.2"
description = "Settings management using Pydantic"
optional = true
python-versions = ">=3.10"
groups = ["main"]
markers = "extra == \"all\""
files = [
- {file = "pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de"},
- {file = "pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa"},
+ {file = "pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440"},
+ {file = "pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f"},
]
[package.dependencies]
@@ -3637,14 +3701,14 @@ windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pymdown-extensions"
-version = "10.21.3"
+version = "11.0.1"
description = "Extension pack for Python Markdown."
optional = false
-python-versions = ">=3.9"
+python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "pymdown_extensions-10.21.3-py3-none-any.whl", hash = "sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6"},
- {file = "pymdown_extensions-10.21.3.tar.gz", hash = "sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354"},
+ {file = "pymdown_extensions-11.0.1-py3-none-any.whl", hash = "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2"},
+ {file = "pymdown_extensions-11.0.1.tar.gz", hash = "sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0"},
]
[package.dependencies]
@@ -3656,14 +3720,14 @@ extra = ["pygments (>=2.19.1)"]
[[package]]
name = "pytest"
-version = "9.1.0"
+version = "9.1.1"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "pytest-9.1.0-py3-none-any.whl", hash = "sha256:8ebb0e7888bdf2bdfc602ec51f8f62d50200af37356c74e503c79a94f5c81f32"},
- {file = "pytest-9.1.0.tar.gz", hash = "sha256:41dd9148c08072446394cefd3d79701701335a9f4cae69ba92e39f6c7f5c061c"},
+ {file = "pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c"},
+ {file = "pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313"},
]
[package.dependencies]
@@ -3701,18 +3765,18 @@ testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"]
[[package]]
name = "pytest-benchmark"
-version = "5.2.3"
+version = "5.3.0"
description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer."
optional = false
-python-versions = ">=3.9"
+python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "pytest_benchmark-5.2.3-py3-none-any.whl", hash = "sha256:bc839726ad20e99aaa0d11a127445457b4219bdb9e80a1afc4b51da7f96b0803"},
- {file = "pytest_benchmark-5.2.3.tar.gz", hash = "sha256:deb7317998a23c650fd4ff76e1230066a76cb45dcece0aca5607143c619e7779"},
+ {file = "pytest_benchmark-5.3.0-py3-none-any.whl", hash = "sha256:920ab1dfcffa718d49aa15ba144c7e357bda59216a0dc308016cc1c7236f719d"},
+ {file = "pytest_benchmark-5.3.0.tar.gz", hash = "sha256:358444d4e89be901ee2b6404fb043ac3d7684002ad7f3563cc153fca6339c965"},
]
[package.dependencies]
-py-cpuinfo = "*"
+py-cpuinfo2 = ">=10.1"
pytest = ">=8.1"
[package.extras]
@@ -3760,14 +3824,14 @@ dev = ["pre-commit", "pytest-asyncio", "tox"]
[[package]]
name = "pytest-socket"
-version = "0.8.0"
+version = "0.8.1"
description = "Pytest Plugin to disable socket calls during tests"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "pytest_socket-0.8.0-py3-none-any.whl", hash = "sha256:81821ba59f07d7600fe2b551d8714f40b068bd46e8b6704c48664e9d60cdacb8"},
- {file = "pytest_socket-0.8.0.tar.gz", hash = "sha256:af9bb5f487da72be63573a6194cfac033b6c7a1c1561e150521105970f9e99f2"},
+ {file = "pytest_socket-0.8.1-py3-none-any.whl", hash = "sha256:f9846bed1dcd96eed459e5e14795bbaf96715cf4e827891fe70773817ecb8ed4"},
+ {file = "pytest_socket-0.8.1.tar.gz", hash = "sha256:2f57787914ad2e1308d09ce141b95c3e55741fbb4fb7b7556593a6b063e0c9c7"},
]
[package.dependencies]
@@ -3996,14 +4060,14 @@ toml = ["tomli (>=2.0.1)"]
[[package]]
name = "redis"
-version = "7.4.0"
+version = "8.1.0"
description = "Python client for Redis database and key-value store"
optional = false
python-versions = ">=3.10"
groups = ["main", "dev"]
files = [
- {file = "redis-7.4.0-py3-none-any.whl", hash = "sha256:a9c74a5c893a5ef8455a5adb793a31bb70feb821c86eccb62eebef5a19c429ec"},
- {file = "redis-7.4.0.tar.gz", hash = "sha256:64a6ea7bf567ad43c964d2c30d82853f8df927c5c9017766c55a1d1ed95d18ad"},
+ {file = "redis-8.1.0-py3-none-any.whl", hash = "sha256:a4fe1aac3d3b3cc791d4b3d5931c5a956045dc951ee74d1c913ee3ac4d2ee9fb"},
+ {file = "redis-8.1.0.tar.gz", hash = "sha256:6e1a19beef9225c83efd689c7e6b7da2d5215b1f42cd13b7fc3714d0a09c7b25"},
]
markers = {main = "extra == \"redis\""}
@@ -4013,7 +4077,7 @@ async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\
[package.extras]
circuit-breaker = ["pybreaker (>=1.4.0)"]
hiredis = ["hiredis (>=3.2.0)"]
-jwt = ["pyjwt (>=2.9.0)"]
+jwt = ["pyjwt (>=2.13.0)"]
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (>=20.0.1)", "requests (>=2.31.0)"]
otel = ["opentelemetry-api (>=1.39.1)", "opentelemetry-exporter-otlp-proto-http (>=1.39.1)", "opentelemetry-sdk (>=1.39.1)"]
xxhash = ["xxhash (>=3.6.0,<3.7.0)"]
@@ -4161,14 +4225,14 @@ files = [
[[package]]
name = "requests"
-version = "2.33.1"
+version = "2.34.2"
description = "Python HTTP for Humans."
optional = false
python-versions = ">=3.10"
groups = ["main", "dev"]
files = [
- {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"},
- {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"},
+ {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"},
+ {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"},
]
markers = {main = "extra == \"datadog\""}
@@ -4342,30 +4406,30 @@ files = [
[[package]]
name = "ruff"
-version = "0.15.17"
+version = "0.16.4"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
- {file = "ruff-0.15.17-py3-none-linux_armv6l.whl", hash = "sha256:d9feddb927fc68bd295f5eebc587a7e42cfaf9b65f60ca4a2386febff575da8f"},
- {file = "ruff-0.15.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:25805a226d741c47d274a35ad5c10a7dde175fcddfa511d7cf3da0a21eb3eab7"},
- {file = "ruff-0.15.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f6ad73b14c2d18a3bf8ad7cb6974294d7f613a7898604826058e6ac64918ef4d"},
- {file = "ruff-0.15.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ba0c1e4f95bcb3869d0d30cbd5917071ef2e28665abfec970cdab0492c713ed"},
- {file = "ruff-0.15.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81647960f10bff57d2e51cadd0c3950fe598400c852863a038720ef5b8cca91e"},
- {file = "ruff-0.15.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e01a84ddbc8c16c23055ba3924476850f1bbc1917cebbb9376665a63e74260d"},
- {file = "ruff-0.15.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fe9f653152f8f294f9f7e03bf3a453d8b4a27f7a59c78c8666167f2b17b96c"},
- {file = "ruff-0.15.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c0fe88a7676e7a05b73174d4d4a59cb2ac21ff8263583f87a81a6018475a978"},
- {file = "ruff-0.15.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecfc3c7878fff94633ab0348524e093f9ce3243080416dd7d14f8ba400174719"},
- {file = "ruff-0.15.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b8461180b22420b1bdc289909410930761629fddf2a5aaf60fae1ab26cedc4c4"},
- {file = "ruff-0.15.17-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6eccbe50a038b503e7140b441aa9c7fc8c1f36edf23ebef9f4165c2f28f568b7"},
- {file = "ruff-0.15.17-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:382fc0521025f5a8ad447d8bdd523545d0d7646adb718eb1c2dac5065ec27c0f"},
- {file = "ruff-0.15.17-py3-none-musllinux_1_2_i686.whl", hash = "sha256:456d41fcd1b2777ad63f09a6e7121d43f7b688bbc76a800c10f7f8fb1f912c3f"},
- {file = "ruff-0.15.17-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b1a04bcc94ae6194e9db05d16ad31f298a7194bfbcb08258bbe589cee1d587b8"},
- {file = "ruff-0.15.17-py3-none-win32.whl", hash = "sha256:596065960ab1ff593f744220c9fe6580eda00a95003cffa9f4048bb5b1bf0392"},
- {file = "ruff-0.15.17-py3-none-win_amd64.whl", hash = "sha256:6769e5fa1710b179b92e0bfa5a51735b35baea9013dadb06d5f44cbcf9547084"},
- {file = "ruff-0.15.17-py3-none-win_arm64.whl", hash = "sha256:f3be1fbb34bcdfd146240d8fb92a709d4c2c8191348580a3c044ec60fa0b4456"},
- {file = "ruff-0.15.17.tar.gz", hash = "sha256:2ec446937fd16c8c4de2674a209cc5af64d9c6f17d21fbf1151054fa0bcf5219"},
+ {file = "ruff-0.16.4-py3-none-linux_armv6l.whl", hash = "sha256:df4075f71ddac40b9934af60c3ec8a53047dd5a5fdc43224e6e4e8e9a27cb6f7"},
+ {file = "ruff-0.16.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0c95538517af68004306b0fb3214ff2f2af67a65092aee77cd9eb86db6656604"},
+ {file = "ruff-0.16.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:963f83df8e69e575b64d67dd447ebbc917db41a14bf38d4593a4183e7aaa8255"},
+ {file = "ruff-0.16.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32a5057c7ff3f6e6480a48fccfb3a412a690f48a3d03ac5cf08177d6c2da3ade"},
+ {file = "ruff-0.16.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b3dce8d9b0c57c265b91885a66a567d8ea1372e8eb4e250fa8e5e3f579e99cff"},
+ {file = "ruff-0.16.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7dc651db49283c69f8e72c834eec4fe5573e4c646856aebece0ce385dceb2a80"},
+ {file = "ruff-0.16.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3817b87dbcabc92f13b05019257c5b89b5b4d51b5fb20f56fb5235ceb723cd07"},
+ {file = "ruff-0.16.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9fce1499134b2c8c68e5166f95705a5812062bb93aacc5f9873bb1a27084bc7"},
+ {file = "ruff-0.16.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2d812e482f5a7e02eee26cd73d2a37ebbdf47d795ea63ba1b89110ae93e9fb3"},
+ {file = "ruff-0.16.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:6baaf984aa7976edf93d3b627fe2d1d22ee94bbca05fa6f90fc76d73924e3454"},
+ {file = "ruff-0.16.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:bdfcf0b28662eb890372d50f92c283bb94e67e7635ed93c7fd533970acff7b2b"},
+ {file = "ruff-0.16.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b66b02cb9b04f537643cadf5768e5f98dc461890d530cb67113d71c8c76e605d"},
+ {file = "ruff-0.16.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8528bf9a4b291a60bf02ea453511e8ce6215bd2b982ee80405b66b008b6c30a0"},
+ {file = "ruff-0.16.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fbd85d2875fdd67e833213a651f613bbf25303abf6aa822a5121f4531195678d"},
+ {file = "ruff-0.16.4-py3-none-win32.whl", hash = "sha256:312769988007aaeb8e189b443ccdd03c0e6374489e053467be6d96518ebff76e"},
+ {file = "ruff-0.16.4-py3-none-win_amd64.whl", hash = "sha256:05d9d27a18c4bcbefada602480ec9e01e0bc949d432e0ced5df77edac195919c"},
+ {file = "ruff-0.16.4-py3-none-win_arm64.whl", hash = "sha256:a3a61621c9b6f6a89573e938a080e648f1695baa3f58570a3a707bc51ff65a21"},
+ {file = "ruff-0.16.4.tar.gz", hash = "sha256:13171aa9d9af2240ee3504e639de73122c67e74036de5ba2e1d01422cd17e3dc"},
]
[[package]]
@@ -4405,14 +4469,14 @@ pathspec = ">=0.10.1"
[[package]]
name = "sentry-sdk"
-version = "2.62.0"
+version = "2.63.0"
description = "Python client for Sentry (https://sentry.io)"
optional = false
python-versions = ">=3.6"
groups = ["dev"]
files = [
- {file = "sentry_sdk-2.62.0-py3-none-any.whl", hash = "sha256:27f61d13a86c3c1648dec666dd5a64f79772dd6a84b446f11866601ecab24f6f"},
- {file = "sentry_sdk-2.62.0.tar.gz", hash = "sha256:3c870b9f50d9fd15b58c817dbde1c7cfaa9fe3f05df0a4c6edd5571cb82f5491"},
+ {file = "sentry_sdk-2.63.0-py3-none-any.whl", hash = "sha256:3a9b5ddd403f79eb73bd670f75f04485819db53d28f76ced7bc09041cb0dfd6a"},
+ {file = "sentry_sdk-2.63.0.tar.gz", hash = "sha256:2a1502bf864769275dbc8c2c9fc7a0f7f5e18358180b615d262d13a31ffba216"},
]
[package.dependencies]
@@ -4505,16 +4569,29 @@ files = [
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
]
+[[package]]
+name = "sortedcontainers"
+version = "2.4.0"
+description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
+optional = true
+python-versions = "*"
+groups = ["main"]
+markers = "extra == \"valkey\""
+files = [
+ {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
+ {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
+]
+
[[package]]
name = "soupsieve"
-version = "2.8.3"
+version = "2.8.4"
description = "A modern CSS selector implementation for Beautiful Soup."
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
- {file = "soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95"},
- {file = "soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349"},
+ {file = "soupsieve-2.8.4-py3-none-any.whl", hash = "sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65"},
+ {file = "soupsieve-2.8.4.tar.gz", hash = "sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e"},
]
[[package]]
@@ -4549,14 +4626,14 @@ dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"]
[[package]]
name = "testcontainers"
-version = "4.14.2"
+version = "4.15.0"
description = "Python library for throwaway instances of anything that can run in a Docker container"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "testcontainers-4.14.2-py3-none-any.whl", hash = "sha256:0d0522c3cd8f8d9627cda41f7a6b51b639fa57bdc492923c045117933c668d68"},
- {file = "testcontainers-4.14.2.tar.gz", hash = "sha256:1340ccf16fe3acd9389a6c9e1d9ab21d9fe99a8afdf8165f89c3e69c1967d239"},
+ {file = "testcontainers-4.15.0-py3-none-any.whl", hash = "sha256:8796c14e76604031ad39cf0ed3b8e9806283a1fbf5270965c2b1c594caa31b74"},
+ {file = "testcontainers-4.15.0.tar.gz", hash = "sha256:085cde086337632e19002719460b7b80bbab2bdd51bb3ea04f77d0de96504706"},
]
[package.dependencies]
@@ -4574,8 +4651,9 @@ azurite = ["azure-storage-blob (>=12)"]
chroma = ["chromadb-client (>=1)"]
clickhouse = ["clickhouse-driver"]
cosmosdb = ["azure-cosmos (>=4)"]
-db2 = ["ibm-db-sa ; platform_machine != \"aarch64\" and platform_machine != \"arm64\"", "sqlalchemy (>=2)"]
-generic = ["httpx", "redis (>=7)"]
+cratedb = ["httpx", "sqlalchemy-cratedb"]
+db2 = ["ibm-db-sa ; platform_machine != \"aarch64\" and platform_machine != \"arm64\"", "sqlalchemy"]
+generic = ["httpx", "redis (>=7)", "sqlalchemy"]
google = ["google-cloud-datastore (>=2)", "google-cloud-pubsub (>=2)"]
influxdb = ["influxdb (>=5)", "influxdb-client (>=1)"]
k3s = ["kubernetes", "pyyaml (>=6.0.3)"]
@@ -4584,19 +4662,19 @@ localstack = ["boto3 (>=1)"]
mailpit = ["cryptography"]
minio = ["minio (>=7)"]
mongodb = ["pymongo (>=4)"]
-mssql = ["pymssql (>=2)", "sqlalchemy (>=2)"]
-mysql = ["pymysql[rsa] (>=1)", "sqlalchemy (>=2)"]
+mssql = ["pymssql (>=2)", "sqlalchemy"]
+mysql = ["pymysql[rsa] (>=1)", "sqlalchemy"]
nats = ["nats-py (>=2)"]
neo4j = ["neo4j (>=6)"]
openfga = ["openfga-sdk"]
opensearch = ["opensearch-py (>=3) ; python_version < \"4.0\""]
-oracle = ["oracledb (>=3)", "sqlalchemy (>=2)"]
-oracle-free = ["oracledb (>=3)", "sqlalchemy (>=2)"]
+oracle = ["oracledb (>=3)", "sqlalchemy"]
+oracle-free = ["oracledb (>=3)", "sqlalchemy"]
qdrant = ["qdrant-client (>=1)"]
rabbitmq = ["pika (>=1)"]
redis = ["redis (>=7)"]
registry = ["bcrypt (>=5)"]
-scylla = ["cassandra-driver (>=3)"]
+scylla = ["cassandra-driver (>=3) ; python_version < \"3.14\""]
selenium = ["selenium (>=4)"]
sftp = ["cryptography"]
test-module-import = ["httpx"]
@@ -4661,32 +4739,54 @@ files = [
{file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"},
]
+[[package]]
+name = "trio"
+version = "0.33.0"
+description = "A friendly Python library for async concurrency and I/O"
+optional = true
+python-versions = ">=3.10"
+groups = ["main"]
+markers = "extra == \"valkey\""
+files = [
+ {file = "trio-0.33.0-py3-none-any.whl", hash = "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b"},
+ {file = "trio-0.33.0.tar.gz", hash = "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970"},
+]
+
+[package.dependencies]
+attrs = ">=23.2.0"
+cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
+idna = "*"
+outcome = "*"
+sniffio = ">=1.3.0"
+sortedcontainers = "*"
+
[[package]]
name = "ty"
-version = "0.0.35"
+version = "0.0.49"
description = "An extremely fast Python type checker, written in Rust."
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
- {file = "ty-0.0.35-py3-none-linux_armv6l.whl", hash = "sha256:85ae1e59b9fb0b40e9d84fe61b29653c5f2f5e78b487ece371a7a38c20c781cf"},
- {file = "ty-0.0.35-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:709dbb7af4fcadb1196863c00b8791bbbbcc9dacbe15a0ff17f0af82b35d415b"},
- {file = "ty-0.0.35-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2cb0877419ab0c8708b6925cb0c2800b263842bd3c425113f200538772f3a0cc"},
- {file = "ty-0.0.35-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7afbcfc61904b7e82e7fe1a1db832a40d8f01e69dee1775f6594e552980536c"},
- {file = "ty-0.0.35-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b61498cc3e4178031c079951257fbdb209a891b4feb10ad6c40f615a51846f41"},
- {file = "ty-0.0.35-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:573b1eacda349fc8dba0d767b41631c3a6f66412363127c5bf2b1b40a1d898d2"},
- {file = "ty-0.0.35-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7209746158d6393c1040aa64b3ca29622e212ea7d8bae22ba50dbcbb4f96f0a"},
- {file = "ty-0.0.35-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4466a1470aa4418d49a9aa45d9da7de42033addd0a2837c5b2b0eb71d3c2bcd3"},
- {file = "ty-0.0.35-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb44bb742d52c309dcaa6598bcf4d82eb4bf1241b9e4940461e522e30093fe8b"},
- {file = "ty-0.0.35-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:34b219250736c989b2670a03782c61315f523f3a2be37f1f90b1207e2212c188"},
- {file = "ty-0.0.35-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:88e2ac497decc0940ef1a07571dee8a746112a93a09cdc7f8bca0099752e2e05"},
- {file = "ty-0.0.35-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:02cae51b53e6ec17d5d827ff1a3a76fd119705b56a92156e04399eda6e911596"},
- {file = "ty-0.0.35-py3-none-musllinux_1_2_i686.whl", hash = "sha256:11871d730c9400d899ac0b9f3d660ed2e7e433377c8725549f8250a36a7f2620"},
- {file = "ty-0.0.35-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ad0a2f0530d0933dcc99ad36ac556c63e384ea72ab9a18d23ad2e2c9fd61c73"},
- {file = "ty-0.0.35-py3-none-win32.whl", hash = "sha256:0e25d63ec4ab116e7f6757e44d16ca9216bca679d19ecc36d119cf80faada61a"},
- {file = "ty-0.0.35-py3-none-win_amd64.whl", hash = "sha256:6a0a6d259f6f2f8f2f954c6f013d4e0b5eba68af6b353bf19a47d59ec254a3d5"},
- {file = "ty-0.0.35-py3-none-win_arm64.whl", hash = "sha256:619c52c0fb2aa21961a848a1995135ad3b6d0a9aa54da0194e60f679cc200e13"},
- {file = "ty-0.0.35.tar.gz", hash = "sha256:8375c240ab38138a19db07996c9808fb7a92047c1492e1ce587c2ef5112ad3a9"},
+ {file = "ty-0.0.49-py3-none-linux_armv6l.whl", hash = "sha256:12c0c4310b936d762a8586c210b53d4fa4bb361a04429afa89bf84b922e5e065"},
+ {file = "ty-0.0.49-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:737bfdc2caf9712a8580944dcdc80a450a37a4f2bc83c8fa9b7433b374f9e471"},
+ {file = "ty-0.0.49-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ab90c1baf3b1701d282fce4b02fa552a962d109f8972c46ef6b22429503bfea4"},
+ {file = "ty-0.0.49-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ce8ecf6ba6fc79bd137cc0557a754f7e5f2dfe9436412551d480d680e248ad"},
+ {file = "ty-0.0.49-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:10d85c6865c984e78661e0bd20b180514b4a289739224e84816e342bdf381e04"},
+ {file = "ty-0.0.49-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d96a67a206619e01fa92f35a22267ec634bba62be24b1d0e947020cc179995b"},
+ {file = "ty-0.0.49-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3de9f648564e0a66344ef397770387cb0d093735f8679d2c5a08a4741e79814d"},
+ {file = "ty-0.0.49-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5779179ab397d15f8c9dbb8f506ec1b1745f54eac639982f76ef3ce538943b50"},
+ {file = "ty-0.0.49-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792d4974e93cc09bd32f934586080bbbe21b8e777099cb521cb2de18b68a49f0"},
+ {file = "ty-0.0.49-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:727bda86deb136073e525c2e78d60e38aedcce5d80579170844a52bbf7c1440d"},
+ {file = "ty-0.0.49-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4f2fc2bc4a8d2ff1cca59fd94772cabdfec4062d47a0b3a0784be46d94d0540b"},
+ {file = "ty-0.0.49-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3724bd9badef333321578b6a941fbc571ebf49141ec2356a8590fbe4c9aa588d"},
+ {file = "ty-0.0.49-py3-none-musllinux_1_2_i686.whl", hash = "sha256:166c6eb52ee4af3c5a9bb267d165d93000daa55c6758cd8ff3199741fb75917d"},
+ {file = "ty-0.0.49-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:91e81d832c287b05782ee32eb1b801f62c1fa08df37d589d2b88c3f1d51c9731"},
+ {file = "ty-0.0.49-py3-none-win32.whl", hash = "sha256:7186af5ca9829d1f5d8916bcf767b8e819bfbf61b1b8ec843bb3fc699cb502e1"},
+ {file = "ty-0.0.49-py3-none-win_amd64.whl", hash = "sha256:ae2142fc126a01effcca0c222908b0e6654b5ba1266d4e4d406e4866aef8e1d1"},
+ {file = "ty-0.0.49-py3-none-win_arm64.whl", hash = "sha256:75d5e2e7649765f31f4bed6c8adb149a75b18edd3fa6336dac4d0efc1a66466f"},
+ {file = "ty-0.0.49.tar.gz", hash = "sha256:0a027bd0c9c75d035641a365d087ad883446057f9be0b9826251c2aecafbf145"},
]
[[package]]
@@ -4762,14 +4862,14 @@ types-cffi = "*"
[[package]]
name = "types-python-dateutil"
-version = "2.9.0.20260508"
+version = "2.9.0.20260518"
description = "Typing stubs for python-dateutil"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "types_python_dateutil-2.9.0.20260508-py3-none-any.whl", hash = "sha256:bfc6fd2d81aa86e5ac97206a64304f6bd247426eedbca9b98619bbc48c6a1c10"},
- {file = "types_python_dateutil-2.9.0.20260508.tar.gz", hash = "sha256:596a6d63d81f587bf04c8254fb78df9d2344e915ce67948d7400512e3a6206d5"},
+ {file = "types_python_dateutil-2.9.0.20260518-py3-none-any.whl", hash = "sha256:d6a9c5bd0de61460c8fdef8ab2b400f956a1a1075cce08d4e2b4434e478c50b8"},
+ {file = "types_python_dateutil-2.9.0.20260518.tar.gz", hash = "sha256:51f02dc03b61c7f6a07df45797d4dfe8a1aa47f0b7db9ad89f6fd3a1a70e1b51"},
]
[[package]]
@@ -4790,14 +4890,14 @@ types-pyOpenSSL = "*"
[[package]]
name = "types-requests"
-version = "2.33.0.20260518"
+version = "2.33.0.20260712"
description = "Typing stubs for requests"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "types_requests-2.33.0.20260518-py3-none-any.whl", hash = "sha256:626d697d1adaaff76e2044dc8c5c051d8f21abc157bdfe204a75558076fe0bf0"},
- {file = "types_requests-2.33.0.20260518.tar.gz", hash = "sha256:df7bd3bfe0ca8402dfb841e7d9be714bb5578203283d66d7dc4ef69343449a5e"},
+ {file = "types_requests-2.33.0.20260712-py3-none-any.whl", hash = "sha256:de027e28c171d3da529689cbfa023b0b4eab188c8dfa22fd834eebd2cee6e7bb"},
+ {file = "types_requests-2.33.0.20260712.tar.gz", hash = "sha256:2141b67ab534a5c5cd2dac5034f2a35f42e699c5bf185eee608c5246a069d7fb"},
]
[package.dependencies]
@@ -4857,89 +4957,106 @@ typing-extensions = ">=4.12.0"
[[package]]
name = "ujson"
-version = "5.12.1"
+version = "5.13.0"
description = "Ultra fast JSON encoder and decoder for Python"
optional = true
python-versions = ">=3.10"
groups = ["main"]
markers = "extra == \"datadog\""
files = [
- {file = "ujson-5.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:71bdb5d10c6d7e710cfa78e743d9fb79a37c7c66fa916cd287bffbaa520f5abe"},
- {file = "ujson-5.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:558673c6c3a2309775683ca96d5f1e4cd99889f71b1ba5cb6be8aa37ae67f9e0"},
- {file = "ujson-5.12.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4b0c9f6a56aa94bb98b403e1f57a866f0b43abaa89757b24d4a4b3cd8643ced"},
- {file = "ujson-5.12.1-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:7bba5ab7965619db7d6f5503133b8e2d8bfce9bb6754224ca64d19261cc52f7c"},
- {file = "ujson-5.12.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:191d2077fd53441599a2efd3dcc205b9cc5f3a4d685a76e9f73f4b6c19aee0c9"},
- {file = "ujson-5.12.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d90d27953716ef206c42f166932b3dbb264dc638bbf32acae81b216ae35f566d"},
- {file = "ujson-5.12.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b6afa86c117b66034004ee83c5149c6dccf7cb88941f9d3a1640c7076577f2d4"},
- {file = "ujson-5.12.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9523d67d45334f9a1d62e423bd72be62b58d2289a50420ffffa9363763eab73f"},
- {file = "ujson-5.12.1-cp310-cp310-win32.whl", hash = "sha256:757f2026bef09d231d63a2250a2c7ad21ea1c9cb1ded6480659d202c4e2ef09e"},
- {file = "ujson-5.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:7e31afad20cd6837a5ac6965d95b44b0ff06e42a82b01a8d3dc606a07f0b7a2a"},
- {file = "ujson-5.12.1-cp310-cp310-win_arm64.whl", hash = "sha256:80f58ae2be100da0f525330ee274accd8892d1c125fea75076f60539d9a5f9cd"},
- {file = "ujson-5.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26dcb43869057373048cbd2678293c5b0f962d5774cc76fc9488564a209bcbf2"},
- {file = "ujson-5.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bca3f04b2f590a8211acdc3ca06649b65a7ed1e999437dccf095310be9d3ba4e"},
- {file = "ujson-5.12.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29d1d64ed2c3c17666f4f0e15462800f3477255dc53667ad5d099277866c5666"},
- {file = "ujson-5.12.1-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:2cfbd6b0c677d5d053964b8f98d8bb1af10c591c8c24454bcd40006ac8ba18db"},
- {file = "ujson-5.12.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f75caed5b6d1fc271bb720a780c4199914267f7b865f9bf17826c4feccea582c"},
- {file = "ujson-5.12.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b21b4c680594c8686bcd4cdda0fd3ea2567b9d42bcf1d1e3d92d39bcdb02e8f1"},
- {file = "ujson-5.12.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:50d07e79ec70d32b4fbe18ab706ed0b172be08710d5901b9d067d7951bfaa164"},
- {file = "ujson-5.12.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:080bc65ac7c0a6314d45d55b6171d3a48b1aeaf89895654d625b291cfe46309f"},
- {file = "ujson-5.12.1-cp311-cp311-win32.whl", hash = "sha256:251ba8229e19b4b0b3efb5e7e3ddfa67c5c466aa492707bc3f6568bf714604dc"},
- {file = "ujson-5.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:46315b82505c99101dcab3bd979f15fecfde85c02df7efbb4e428fa357665290"},
- {file = "ujson-5.12.1-cp311-cp311-win_arm64.whl", hash = "sha256:12e99e49c62322ed0394c914aff15403ba7ede0b74f05a0faa4ec12c7d17a139"},
- {file = "ujson-5.12.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:10f44bd08ae52ee23ca6e8b472692e5da1768af2d53ff1bad6f40b532e0bc7ee"},
- {file = "ujson-5.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cc6ea753b7303fa5629fa9ac9257ea4b001c4d72583b2bb36ff1855a07db49f"},
- {file = "ujson-5.12.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:289f13095764d03734adfa10107da9b530ceb64dc1b02a5f507588d978d5b7df"},
- {file = "ujson-5.12.1-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:427893168d074e59214b0ee058337c57f5bb80175cdd5b4799a9c931aae22022"},
- {file = "ujson-5.12.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7a81724d5d90a2da7155d15d8b156ce57eaed7cdd622df813f36a8e612fd4c8"},
- {file = "ujson-5.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3a6efff7dc6515416366819de4a1bc449b77107c5b48508b101fd40f7f8bec08"},
- {file = "ujson-5.12.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77a71fe53427a0cf49d56eafd801d9f7e203b784b7f99cc717783fd6f6f7b732"},
- {file = "ujson-5.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ea3bed53d2ea8e5642e814a9e41f3e29420a8067874ba03ace8c0462e160490c"},
- {file = "ujson-5.12.1-cp312-cp312-win32.whl", hash = "sha256:758e5c8fbe4e6d483041e03b307b01fb5d2f2dd4452d4d4b927ab902e188939e"},
- {file = "ujson-5.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:f6074d3d3267ba1914c624b6e1fa3d8152648ff36b0ab77ddf83b92db488c30d"},
- {file = "ujson-5.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:7642a41520ac1b2bc25ea282b66b8da522cc43424442e6fb5e039be4d4f96530"},
- {file = "ujson-5.12.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c4bdc052a5d097f0a2e56d93aed97355f9f7a62ef9baa4f8517e43245434af9c"},
- {file = "ujson-5.12.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5dc91fa06ea35920b704fd9d70871897680145998071cfbf5ee3e19f2c9fc242"},
- {file = "ujson-5.12.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5db0849c0e3da54822a5834f2dc51d7c51072d7f7d665014ee34600dc10889b"},
- {file = "ujson-5.12.1-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:949cb4863a5d4847edeb47c5364b334e8cadf23a7cbdaa547d86098a4b093106"},
- {file = "ujson-5.12.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8aa731138d6dfca4ab84501b72384e6c544bfb48cb87a0dd4d304df3246cac25"},
- {file = "ujson-5.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:727e983ef27892d86ee2d28fd517eeb02b2c1165aafcbe929dce988aeee81bfe"},
- {file = "ujson-5.12.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d57d731ecf492d3d011e65369f8330654f0875b19f646be5270d478e843d3b81"},
- {file = "ujson-5.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a09636220f26c66f80c6c6283023cb53120e843825f890be92696cd1aa43f39"},
- {file = "ujson-5.12.1-cp313-cp313-win32.whl", hash = "sha256:ee83fbac03a0896faf190177c938f94eb610b798d495a19d50997242c4eca685"},
- {file = "ujson-5.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:e08d9e096c416ddc34519241f97c201258b42639f2012d9547d8ae32921800dd"},
- {file = "ujson-5.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:963287e4b1bc463735c4056968a2dfa59bb831b6daba68bddd14f451191fe9e5"},
- {file = "ujson-5.12.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6f19e9a407a24230df0cc1ec1c0f5999872ba526b14a780f80ad6479f5eed9bc"},
- {file = "ujson-5.12.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8b657e870c77aaacdeea86cfad3e6d2ef9b52517e45988c9c367f7ee764fe4dd"},
- {file = "ujson-5.12.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:984b5a99d1e0a037c2046c3c4b34cec832565d62d5017be0a035bf3cbfab72dc"},
- {file = "ujson-5.12.1-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:f48ef8a16f1d85bd7982beac7adfd3fb704058631db84c1c61c8a1b7072b1508"},
- {file = "ujson-5.12.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f39ba3b65cc637b59731532f7e7c807786bff1d0332ab2d5b96a04d2584d78f"},
- {file = "ujson-5.12.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:07f307780f85b49cba93f291718421b6f5f3b627a323b431fad937a18f6587cb"},
- {file = "ujson-5.12.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:1c335caea51c31494e514b82d50763b9792d3960d2c7d9fdb6b6fb8ed50ebdd0"},
- {file = "ujson-5.12.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:19ea07e29a45d199f926aadf93a9974128438c01b83141fba32477c0ee604b33"},
- {file = "ujson-5.12.1-cp314-cp314-win32.whl", hash = "sha256:c8e626b6bc9bdd2e8f7393b7d99f3daa2ca4022e6203662e70de7bb3604b21b9"},
- {file = "ujson-5.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:c6d3bdd020333688ee60559437021ed68a98a28fdd609b5af16de5dd58f90cba"},
- {file = "ujson-5.12.1-cp314-cp314-win_arm64.whl", hash = "sha256:e3c9c894971f4ada3ded16a804ed4640e1f2b3e5239beaeec7c48296f39f4232"},
- {file = "ujson-5.12.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:49dd9c378e1c8e676785ff2b62cb490074229f15ab54abf45b623713cb2c36b5"},
- {file = "ujson-5.12.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6d8827904358d7da59ccf2e1fd8de59e78248036d17fecc0462e62c6721f1102"},
- {file = "ujson-5.12.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc26caebea90425662ef0b979f945f6ac832651881107d6ec9a3c4d4a4ba929c"},
- {file = "ujson-5.12.1-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:45022aae09ac3d45bda6fbfc631088d1aff9a0465542d40bd6d295ced378c430"},
- {file = "ujson-5.12.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b22aa0f644516d3d5b29464949e4b23fe784f84b4a1030ab9ac3cb42aaedabb1"},
- {file = "ujson-5.12.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7dc5cf44ea42365cd1b66e6ed3fc6ca040c86587b024a6659b98e99d31cff2cd"},
- {file = "ujson-5.12.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8df5d984ff4ac1ef292d70f30da03417038a7e1e0bc272d28ca9d34f02f41682"},
- {file = "ujson-5.12.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:485f0182a0c0b54c304061cdc826d8343ce595c4055f7a24e72772a8520e5f7b"},
- {file = "ujson-5.12.1-cp314-cp314t-win32.whl", hash = "sha256:4e12ca368b397aed7fa1eec534ea1ba8d94977b376f9df3e93ae1acfd004ec40"},
- {file = "ujson-5.12.1-cp314-cp314t-win_amd64.whl", hash = "sha256:cec6b9b539539affc1f01a795c99574592a635ce22331b64f2b42e0af570659e"},
- {file = "ujson-5.12.1-cp314-cp314t-win_arm64.whl", hash = "sha256:696224d4cfb8883fa5c0285dff31e5ce924704dd9ccd38e9ea8b5bf4a42b12fc"},
- {file = "ujson-5.12.1-graalpy312-graalpy250_312_native-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2c419bf42ae40963fc27f70c59e24e9a97f5cf168dbce2c572f3c0ce3595912"},
- {file = "ujson-5.12.1-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0be2b4f2f547b9f0f3d902640e410e5a2fc851576cbe033c88445a23e3e7aef1"},
- {file = "ujson-5.12.1-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:4ea0c490c702c20495e97345acfcf0c2f3153e658ef537ff111929c48b89e10a"},
- {file = "ujson-5.12.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3e30fa6bc7156ed709e13f8b52e917db08fbfd611ba61346b62630974ec0ba8e"},
- {file = "ujson-5.12.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f67c5f0d64eba0fbbd6d2d6a79b0c43c5bc06f27564378fd5d716e0d40360068"},
- {file = "ujson-5.12.1-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8416bb724db9accfa97bdb77245952494b1800c23e42defd46afb5c661c9af19"},
- {file = "ujson-5.12.1-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:66005b49c753a1b9f2f8853919dc58e1e6bd66846ea341a33afa76c6d7602485"},
- {file = "ujson-5.12.1-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bdc6b277dcd27663f7fb76b6a5088424c66e0407c23e9884f80cd733f7d71b19"},
- {file = "ujson-5.12.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:7957b64583793042521f7f7c71c01626b3d32a17528eaab980eb8cdc3d4eec68"},
- {file = "ujson-5.12.1.tar.gz", hash = "sha256:5b7e96406c301a1366534479a7352ec40ec68bb327c0c119091635acd5925e35"},
+ {file = "ujson-5.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:770643b4752266c5a466149848b78c3874940926a4ecef304f518b2b6cdb432f"},
+ {file = "ujson-5.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8e8c1203cb1a27720debc334f840a9170da741503522f86999710cb4738fbe3"},
+ {file = "ujson-5.13.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:65c1813fdd742fe3c249d9c417fa490e5b54e8a91bf343a88486ec50d175c444"},
+ {file = "ujson-5.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5aa9bf16f0131812720dd4ae70bc1a0cf68f79e93c07c66100d328e75944b567"},
+ {file = "ujson-5.13.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82c17b904c03c2b9629486ec91a8fa46a15f10d03504284f54ed7257a917d9f1"},
+ {file = "ujson-5.13.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0b5f6983b2469db00e540b68fa8297b7a0ccd0d5173c60cc3e84f336b09395f"},
+ {file = "ujson-5.13.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b877fe7926107d25d54b655c5b8dd94b294b22c157233163ad29fdb54ac10cf4"},
+ {file = "ujson-5.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f3cae1c811e787b9500e2830af8632dcb32a78dea5baf15aac51d681c59a59dd"},
+ {file = "ujson-5.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:820b78a6a183ab6591b2ea888020032ef0fe328d852af9a5c8d8084ababb2218"},
+ {file = "ujson-5.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1209c985d1f4c2ae085ced7325509650cdb3533bb7294558dd1f26d48377942"},
+ {file = "ujson-5.13.0-cp310-cp310-win32.whl", hash = "sha256:326553ae6c063c8246974906a6c137a0780fe46d143abebc52cd2cadda0f1814"},
+ {file = "ujson-5.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:0354d6b50b0d153ed7c629845b18a953d0c727b7e768fd94a94e0602abfa1f29"},
+ {file = "ujson-5.13.0-cp310-cp310-win_arm64.whl", hash = "sha256:7b4a05f61a96553995da6a4d502e07bc8aa5d07a90031df006239c6b00ce1c83"},
+ {file = "ujson-5.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b7badefa73f96bad9e295ea22bd06967b851c8aad68c74196437e3584f25de5"},
+ {file = "ujson-5.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:09effd42924a80df20a63b31a1ede905e66b0ce24aafe7a4cbedb05c783f8bb3"},
+ {file = "ujson-5.13.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:89d0bfc986d02b4ce76b00e0f560bc8d30dfe8c05a1bfd8529e085eb6c1a77d9"},
+ {file = "ujson-5.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cdd9618e07b3b142a02f0ab8227fd52453688b8e8e60ac0511f13a25fa8009db"},
+ {file = "ujson-5.13.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0806683e8171ec06817e6af22f14ba0cd2f16def8a2ffb22a28a10615249355d"},
+ {file = "ujson-5.13.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1cf46c79498c81f088cad4165b1669a78bba7bfbeb778c7cc1aff316e062b0d"},
+ {file = "ujson-5.13.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2282039eb26f08ed1a1381360395f8a310f39a45ef7314cb0f258a7d2917ea3"},
+ {file = "ujson-5.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c75eb7fac0fe92925b959cf2fa18f88d9fb76b10781fd2a6ccb895d5fb89171"},
+ {file = "ujson-5.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:12078e81def2790140583abefc1b979f3c77be15d53c524bf0e232f669822052"},
+ {file = "ujson-5.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e12192a37c6c0e476554b62647acdf6139a47b6f13d8bad8dd2316763c4cee12"},
+ {file = "ujson-5.13.0-cp311-cp311-win32.whl", hash = "sha256:ae53b3f046529c193d533ca8111492330b204d6007611cdfa20e8b764c7c1389"},
+ {file = "ujson-5.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:2275bbaaea3eddd2e8ec0863e28a420f5f520b14a760fc3f1e49fd07a974448c"},
+ {file = "ujson-5.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:32a59e7151fe2fec8fdf9a565ee66fcf87918d48827e21cdab5e15ff9f274b78"},
+ {file = "ujson-5.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bf81570ac056cb058f9117b52ca5dd800bfe9381d0076d0bb30a08a54591d654"},
+ {file = "ujson-5.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7edf16359c52ed53406e216565d83e6b98c23c3cb9a0a01673f2493f8fb15edf"},
+ {file = "ujson-5.13.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:24539618fb3243cfdf27dab9a850acab80798a01501e9586b61fb9ecd016a891"},
+ {file = "ujson-5.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fdde6341d213b29f413b5fa9fad1392d5408074c75f0900ed949e97e546fa5df"},
+ {file = "ujson-5.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:229faf041ef249ee3fd57bac1cedb123d2718ab63f6ccd50eca95ea902eb0dca"},
+ {file = "ujson-5.13.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d02f31c2f59cc6a1c2c3633b377701fc2d8e876cc01950735d7a01132ccc233"},
+ {file = "ujson-5.13.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea7204e9fa7538bfbb1396e1ee8c2bbcd3818b3633ef5bb14d4fdea52994d14d"},
+ {file = "ujson-5.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c5a2478a3a1fa4421f7e035b87194eea0cf44c7971a3f32ad1b42a0dfd63c03"},
+ {file = "ujson-5.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b535e0970c96957e999cfe5ec89361f0e8d0bb987fb5d5144f6f495cb3ed9e19"},
+ {file = "ujson-5.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d0ad1207694988498fca7e0bb28eba7564fa33261d2f9fdf66a3aaab376b803"},
+ {file = "ujson-5.13.0-cp312-cp312-win32.whl", hash = "sha256:d6bc9fa43a49e403c68c7eb164eef0feee9dd29474a7c6e0d3b6267025371990"},
+ {file = "ujson-5.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:6692d49ff970aaa5008f4a6fe06974bc91fd957bf13173f765e46d8ba44906ea"},
+ {file = "ujson-5.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:5737ffe0740a788b0e6255f0ffb281db49305fd6e6a587be44c73d9e92b554c4"},
+ {file = "ujson-5.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46998fc8d11aec34a20e2010905e7059732a3d192d9a3c3fe4f9ffd146c87ec8"},
+ {file = "ujson-5.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ee03ce288ba25b05cf0de87203165642277a25caa4f00a437e13152e5214e310"},
+ {file = "ujson-5.13.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:cdf33b588a81b05d0b585c66f83050c49cb670623424d10e4d1ad37ba2f7eed9"},
+ {file = "ujson-5.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4cabd73c114ce93c21d7db2e2d8e16217fd8a5b2b3ec754629eebef5c262d47f"},
+ {file = "ujson-5.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ffc61fc756a64f4d169a78cc638d769e3c324f45fc51997626abf4e5e5dd6460"},
+ {file = "ujson-5.13.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c00323c13a35822c9a67a26c0b2a0787510bf1ef490922b58009b362d1a3e21"},
+ {file = "ujson-5.13.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:496e662a6b46d5f936d77fb68259cece19213bb2301ddd520dbd75ac7c90c5f4"},
+ {file = "ujson-5.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7fd41b86444df14f8b4b7afaaa9f27bacfbf8c18380872317aeab6cd125dcede"},
+ {file = "ujson-5.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bf3c2c4ea55d4187903fcdc689a9bf5b0fc72d8c0eaff39db18c1f337c8832c1"},
+ {file = "ujson-5.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b6eca7751d61045a9b1e7f9a8c97ac24b164f085b60bef1c4668654bb2338011"},
+ {file = "ujson-5.13.0-cp313-cp313-win32.whl", hash = "sha256:b63d3820f978bc8e98cc3f1fe26a33b0d2ea237733a23fe5e9cb5d51f466bd97"},
+ {file = "ujson-5.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:17a59d5cf23ef98f7c9314524976b4b288374d83200add01d953024fb06404f9"},
+ {file = "ujson-5.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:b49516fbe803ff30d6caa9ccc3799ec7f968992747ce3099eae4758928577b53"},
+ {file = "ujson-5.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:cc9dfd41fed397ab03bb9d9fe1cbd83301211c772a17536033ce7d68877ac82b"},
+ {file = "ujson-5.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ca7ef2fa6c408a7c0f558e4d33d93b32ddc35ed6d3cfc505747931a64b7465d5"},
+ {file = "ujson-5.13.0-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:a554b2e5bee85030369514cef8b0b913cebe1a4c2c0c13541966d50bcba22b1a"},
+ {file = "ujson-5.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ea939ff629ab03ae970d03eca6d1febd8ed55ba38ca44aec64ce997537cd3fa0"},
+ {file = "ujson-5.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b98bf2faa5e37ecfe752226ea08290031e375a0c43d425a0b955fb3e702a2a71"},
+ {file = "ujson-5.13.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a4b92344b16e414aeb609e57f62c466500e53c94f1698f5b149dc0b7223ec3e"},
+ {file = "ujson-5.13.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7df805aad707507a1fa165fb716218ca3a89f142125dc4b23c9fcc08fa402d97"},
+ {file = "ujson-5.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7576bdbef327c3528f011002a2d74486f6fe4e33289bdb7a042b7f1a6e9d8285"},
+ {file = "ujson-5.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6eee5d7cce3f32a468905f9ff61807a60287a90258d849460f6fa826e810870d"},
+ {file = "ujson-5.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:144e9d8a454cfa727e0f755e1863738ed68068583bda5463052cb446835bd56c"},
+ {file = "ujson-5.13.0-cp314-cp314-win32.whl", hash = "sha256:576f35c35b918d67d41b933878062ec0a5c9f4d1e9e14e04aeef35384963feae"},
+ {file = "ujson-5.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:d5e206e9f849ead27e51ef8da44e52b38da7c6dbd929a7340ab44533edcda8d7"},
+ {file = "ujson-5.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:dc470179775468f9a007d3a6a2734624248c94bf47c6645e808c7e50a5070d1a"},
+ {file = "ujson-5.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:69b4e36bb7d5f413ba8c00c8006b2ec627cc5ace97301462f6aadb66ec9d2979"},
+ {file = "ujson-5.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8b644d50f66de5490c1823c7176618cead5e8e8a88cba9f40a6308ca52e79267"},
+ {file = "ujson-5.13.0-cp314-cp314t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:15107aaa4f559d55201165ec32abb35c283a861be1fa67229578cb7d93fcd93a"},
+ {file = "ujson-5.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6e343c5f0c058523f1edbf6ae4eceb4e0d934205a53bbdd8d9a945c83324662a"},
+ {file = "ujson-5.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:02200035bc80e830f076ffc1b329a94c295aee6d9de8c9043647cb9a7bd4f76f"},
+ {file = "ujson-5.13.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d7f19b81b73ff28f5c5022ee794f94122bfcda07a76423078e349465d71223a1"},
+ {file = "ujson-5.13.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:82e1393e6dbe3c95fdfc95c6c528890e191351a1f024ef51126cf1f22543af52"},
+ {file = "ujson-5.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38afcf994b28ed85ea2420e2a8d79a37d0a77348b3daf53850c16edda66f942d"},
+ {file = "ujson-5.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1bdf2518971586f2b413156c49d9dd8b56cc990a8647081e1bd00af60564d469"},
+ {file = "ujson-5.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:751ad01042472f1c7c02f5c597c7aee79834e82a6cc384ca302173bbc8e8deb8"},
+ {file = "ujson-5.13.0-cp314-cp314t-win32.whl", hash = "sha256:74f3dd61aeb01b7b2a6754e400224e819279041b3867935a55ccf57fb86a43b2"},
+ {file = "ujson-5.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:5c31317d5e4504dae8f98795358b6082fc0ef96e7394806db0a76a4a8717f446"},
+ {file = "ujson-5.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aefd3c9c95f9b62348956396ff7b31818476f8f54dc4a4e64cbd4f0491db6fca"},
+ {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3e074a1f7778d58aa3b3056bab7b6251aabb3f381808018ca2b7fb8dbdeef7ab"},
+ {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8bb53ef95d35875262b8d0aa28506ca612ddd07058bee2a90f609938e69dc801"},
+ {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fb296a0aa480ab88d895ddaa90372604c08ccc72323f02590612c775426ab413"},
+ {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2862f81af44b3a7e74c5d80caa118d736be1991ce6f1d5c723716fa403060cc6"},
+ {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c16e07581172f08585b409246f4535dab13ee85af0e3d3cfa8684b653ca44fa8"},
+ {file = "ujson-5.13.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:9bd0f2dd05937c3b089af316884de18c6f6182ddb8ffce597d2e7c7a9ba9f447"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:96e7e019b097b4b25fccddadb369d13f412c13695fcf0680b6bf906376156151"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:7892ea6dd85ede6d30fbbd22af1239b9d81dabdf9b7a8f10ca6d4464d4d9b8ab"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:e1842e10adc8f0db0d3e8aa3a1f8b05ce0456b39e180c8553d7f36dd0bf24b6b"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8bbb1f5ab810954fb307b6c5e68af58210c31da8569f9e6498a3958c1859e72"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3f6d55c68985654a84a9b47ac51f2655adac4fd264e4189f832960c2270dcf70"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b266f182d4bce74a6a9e1f86988485e8cd422efdcc7c3f537e00cc956f52678"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfaa8302eb9bb7f5e231f256caf83040760585e32751d19155c0f0c0225f8de1"},
+ {file = "ujson-5.13.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:43dee3081b00fe447c5b9e2fe7ebfd57f7bcc5dd25b8a439c26c8c174dd581be"},
+ {file = "ujson-5.13.0.tar.gz", hash = "sha256:d62e3d7625384c08082abad81a077af587fdef2761bb14c3822f4234b8d07d75"},
]
[[package]]
@@ -4963,55 +5080,48 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""]
[[package]]
name = "valkey-glide"
-version = "2.3.1"
+version = "2.5.1"
description = "Valkey GLIDE Async client. Supports Valkey and Redis OSS."
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "extra == \"valkey\""
files = [
- {file = "valkey_glide-2.3.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:736a3e58393fa4f0f2fbb10031d46da5f18ebb8e72d2f9428ff24f0f6addeb3f"},
- {file = "valkey_glide-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b2cd6f5c4e9b67b78873f34f19b9182bab5b07a9151855cf059303e05dac3b2f"},
- {file = "valkey_glide-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ddf70bc7888d565273e4bf858ff6047d5284140ff380a732f807c775be8e108"},
- {file = "valkey_glide-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f947dd44ba9741eadcab154443f447c19f23dab56de33f56d5f133ee0d597c2"},
- {file = "valkey_glide-2.3.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6ddc4c6bee1a9c102f003cddc5d1bad8173a9d90e1c9a0f73a285228ed8625af"},
- {file = "valkey_glide-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30590532136e4ea38b6a6389cbcfe4edc554418563c6e4f6357b0749907b2c20"},
- {file = "valkey_glide-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bbdb7baa7aac12c109aefd97f69f9780a4812429db18786254ef288ecf75f19"},
- {file = "valkey_glide-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fd64d77ae26efd524be58456e22636ce4cb0a6110ad722e89f249a45d098692"},
- {file = "valkey_glide-2.3.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:406b73f5ee080406fbfeda542d37de7e330fb4d83b0aa7212b92707d7b7b82a6"},
- {file = "valkey_glide-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0940d4069cbc4896dec3a1ab39db7bf86667fb32892df4dbf3b043129d26d6e5"},
- {file = "valkey_glide-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b47de0ec3d5a253c2b37d33266aaeb22503014f9e8f0611ba999e06f9804966a"},
- {file = "valkey_glide-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a364210002dd0e7c3362299f61a2a1cacf867594a8a0bbf157a345f3f40d4d94"},
- {file = "valkey_glide-2.3.1-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:86d56756842acd6286601128822c5f1f9dcd61305f0c6a80c3e7fb3a7e0404ef"},
- {file = "valkey_glide-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b307795a23473b8e7cff781eb54936cc672a430820f5fa71c6b6fb3748cc1189"},
- {file = "valkey_glide-2.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb570f5d637ee55300ccdecd39a51cbf25c67ab6e25f2022d42f32a7bec6163"},
- {file = "valkey_glide-2.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:506c7800eec05caf17136645cc642941a9536578f4d6733845e7d0ed36ed4e3e"},
- {file = "valkey_glide-2.3.1-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:3d6626e6f9ddfa7f8706023e167b4a2eca8a0f7b7fee1d30f91a83b4811349e4"},
- {file = "valkey_glide-2.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3466a0c113a951d722036704795ff0377eef11a44ab224472f98d99ac2c5ef28"},
- {file = "valkey_glide-2.3.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe53e4808bdac5b4e6482c66583e1980ecf75666b4e4d0984d89e8b693026543"},
- {file = "valkey_glide-2.3.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1a9662885ea8f3df97a6d873131dea983d42e4735750af368fe2d47e7e44f0c"},
- {file = "valkey_glide-2.3.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7cd8c7d52411d8add7640eb4982942e0fd0154db5d010e3a8094ae028f91d136"},
- {file = "valkey_glide-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b3037c5d477172d82ae443f1fbc664dba04a0184efd5a227d541cdf06be478f"},
- {file = "valkey_glide-2.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcac3e3064de88c57042eaa34980c6f35c8c09138148cceafd7dddbd830602ea"},
- {file = "valkey_glide-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1de33b66aba099e3f17199da4edefbeb38c91349a6c0d958581fa77be3475140"},
- {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5533a090953fd6af4c07b80bd042231540fbd1ede95fff42614750b435f01184"},
- {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f814ad759e9fdc6c5ced18ddba38cc2a3badb2839ce3555ec9b44beb794096e4"},
- {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dc6dea7ce627a8b166d33232aa7bc7f8dd9d224870235a560bc5d1c4ccec8cb"},
- {file = "valkey_glide-2.3.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1e135bb43e50b1cd6558d93b3108c40a79ce8dc119de883cebb7458d470f629"},
- {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:993c9bffde847fa3d36c6f11e5e50872dd491f245850d7c6ae1bbb8db5bff346"},
- {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:918ce3b8a2a3602e82d03f254bad5cc5bd1398eb84dec8eef77aefccc039bd5d"},
- {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28d4cbf00b07db273214488f17d59232baaddd0cc30c26064cf3bf384b03e9cd"},
- {file = "valkey_glide-2.3.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d93ef822a524c8f18c1b750f061373d95e842005116ebcf832d166533bf2bc2"},
- {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f66459238f68b165d6b3b8c1a0cb48e63ce291afa82e82f029dbd37b7b27099b"},
- {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7bc45d65196d03f8651a4f40d5be5faf6925edb3d8d37cc57a79fd555f70c368"},
- {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:115bd85a443fec57d12094aa8ae627a718df64044a978bc4d407f82a29db4c83"},
- {file = "valkey_glide-2.3.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beb25b2445e9be63784e67200fdf708694e842f3a6e93530fe974200411dfaf4"},
- {file = "valkey_glide-2.3.1.tar.gz", hash = "sha256:f4bae030c0aa6e55edb2c27dbd55f82cfb5f581904fff1318eec1c062f30d4b3"},
+ {file = "valkey_glide-2.5.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d66f47bbc5cea7155b0b3ca002043bfd950c09a9ac08e10923a6bcb0a3aa0a1c"},
+ {file = "valkey_glide-2.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:47a666862faa47766d4c4814203c3b9f9a8cb466200fd5f71e330eef6ed0d8f1"},
+ {file = "valkey_glide-2.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecd82dab35f30d96785b1405ebe3a6931dd858c8f26a0b7a12b46609e75212"},
+ {file = "valkey_glide-2.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44435ed9fdb6322a4b167c9f56fdc0145a1fab4736dd2659165bbb5358d3a68f"},
+ {file = "valkey_glide-2.5.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:d9bbf26f9ea2b72ef0b8541dfefa479a82a69bdec77fce917192a262893edfda"},
+ {file = "valkey_glide-2.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94256d3335f4c31f19ad1ff02447d9eecd94b8c9e8d51c7b77811277c957e807"},
+ {file = "valkey_glide-2.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d46a9903acb1204deefad88162ac77404f052c7d51ab9d5851d2335ed2fda1e8"},
+ {file = "valkey_glide-2.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e5c17169d07564f0cc23b78c4904c8e03063c8750d8ccf413d229ce9a3092d5"},
+ {file = "valkey_glide-2.5.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:75da4cb54fe6a0e03a78681237545aa0638dd5a6dd0ff51af6ff4cacf9f99443"},
+ {file = "valkey_glide-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:787010bbce1b8f270ae5d74ca8af15bca3bbc625e1a5467fb01025864bc4e792"},
+ {file = "valkey_glide-2.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de2e202a8376c6b67735bd589ce0e46683f8a782fcb1745b0b44cce768e13856"},
+ {file = "valkey_glide-2.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ab1c7ce52b098fcb0ee6223136a024fc90a8ae1c600db298c30c044d1b47ee2"},
+ {file = "valkey_glide-2.5.1-cp313-cp313-macosx_10_7_x86_64.whl", hash = "sha256:55c87ecc3146480adaddf42d659b688089ca417596208ca9df5c2249c8f9e6fe"},
+ {file = "valkey_glide-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae6b0cedd3d2aafdc53c460bdfe4d0319d10301fd2128a56d41486e49de88dfe"},
+ {file = "valkey_glide-2.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8a3c5298899ea18fc7e40438643e2f8ee15955fe9bba66ce5daf3dfd29462f2"},
+ {file = "valkey_glide-2.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb5e0094d576ce99a2453c9fdd923f70732db6f4b59a722c27c420343d96b75d"},
+ {file = "valkey_glide-2.5.1-cp314-cp314-macosx_10_7_x86_64.whl", hash = "sha256:1bc5d0e0241aa5b78c398b981fe19801e36c09572c1dac69286a9a3c817e0b35"},
+ {file = "valkey_glide-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec658ed7770c05f3ea431ca1301e47d0a24cf27c4c23ca30eb030f7e0ac7488d"},
+ {file = "valkey_glide-2.5.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2cdb26952b650e25af4a14360f65364b8015e49e2967779ba850c9e62c1f237"},
+ {file = "valkey_glide-2.5.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:696635581f0692f640b94021b4cfbc2ec01108f6ae02f25dfea3cfdaa98331de"},
+ {file = "valkey_glide-2.5.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:f5e733adc4718b93c5b228de7e543a6641e231d5839202ce7b22487e079059e7"},
+ {file = "valkey_glide-2.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ffd8f0fdb6ef982161a2350ad1562e5e345bea263b81304c7282f3385deac20"},
+ {file = "valkey_glide-2.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6b81727c4d7a3b49f10172787296c87d6ef8d729fb958de358b278d5a6c563f"},
+ {file = "valkey_glide-2.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12fff287f02caa9302d7c64d0520c3cee86e0f952ec55a537a4f9378889265d7"},
+ {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f656ef6e722d6ab4a28bc66e36ef616dff28622bc712c41f4172ac1e7c4826d8"},
+ {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:65b2add9f19a2e48080130ee968af45dc14e8457b5db20262703a4604afc478b"},
+ {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9b725afe94f0515e296003942d6c96c5090a956f2217f6305dc87fa14dfa51"},
+ {file = "valkey_glide-2.5.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a131c08951b865f753f1bd42f7db19c6a96e7c4faf9dc78718f8909fc95eb8b4"},
+ {file = "valkey_glide-2.5.1.tar.gz", hash = "sha256:b2efb23c987a995ad6ce2a72616996638137dd2504ac262bdd6c045378394090"},
]
[package.dependencies]
-anyio = ">=4.9.0"
-protobuf = ">=6.20"
+anyio = {version = ">=4.9.0", extras = ["trio"]}
+cffi = ">=1.0.0"
+protobuf = ">=3.20"
sniffio = "*"
typing-extensions = {version = ">=4.8.0", markers = "python_version < \"3.11\""}
@@ -5223,4 +5333,4 @@ valkey = ["valkey-glide"]
[metadata]
lock-version = "2.1"
python-versions = ">=3.10,<4.0.0"
-content-hash = "325feb84a282310b016844cd52100d9a18841c17bb80d556c550fe8f83c86f04"
+content-hash = "368940a68ae8b3bbb72ab67bbb91e4da4170e07a7faf28011343cfcb809ce84a"
diff --git a/pyproject.toml b/pyproject.toml
index f4c2d56541e..0510319e5f8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "aws_lambda_powertools"
-version = "3.29.0"
+version = "3.34.0"
description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity."
authors = ["Amazon Web Services"]
include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"]
@@ -50,9 +50,9 @@ fastjsonschema = { version = "^2.14.5", optional = true }
pydantic = { version = "^2.4.0", optional = true }
pydantic-settings = {version = "^2.6.1", optional = true}
boto3 = { version = "^1.34.32", optional = true }
-redis = { version = ">=4.4,<8.0", optional = true }
+redis = { version = ">=4.4,<9.0", optional = true }
valkey-glide = { version = ">=1.3.5,<3.0", optional = true }
-aws-encryption-sdk = { version = ">=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4,<5.0.0", optional = true }
+aws-encryption-sdk = { version = ">=4.0.5,<5.0.0", optional = true }
jsonpath-ng = { version = "^1.6.0", optional = true }
datadog-lambda = { version = ">=8.114.0,<9.0.0", optional = true }
avro = { version = "^1.12.0", optional = true }
@@ -116,7 +116,7 @@ types-python-dateutil = "^2.8.19.6"
aws-cdk-aws-appsync-alpha = "^2.59.0a0"
httpx = ">=0.23.3,<0.29.0"
sentry-sdk = ">=1.22.2,<3.0.0"
-ruff = ">=0.5.1,<0.15.18"
+ruff = ">=0.5.1,<0.16.5"
retry2 = "^0.9.5"
pytest-socket = ">=0.6,<0.9"
types-redis = "^4.6.0.7"
@@ -124,12 +124,12 @@ testcontainers = { extras = ["redis"], version = ">=3.7.1,<5.0.0" }
multiprocess = "^0.70.16"
boto3-stubs = {extras = ["appconfig", "appconfigdata", "cloudformation", "cloudwatch", "dynamodb", "lambda", "logs", "s3", "secretsmanager", "ssm", "xray"], version = "^1.34.139"}
nox = ">=2024.4.15,<2027.0.0"
-mkdocstrings-python = "^1.13.0"
+mkdocstrings-python = ">=1.13,<3.0"
mkdocs-llmstxt = ">=0.2,<0.5"
avro = "^1.12.0"
protobuf = ">=6.30.2,<8.0.0"
types-protobuf = ">=6.30.2.20250516,<8.0.0.0"
-ty = ">=0.0.23,<0.0.36"
+ty = ">=0.0.23,<0.0.50"
[tool.coverage.run]
source = ["aws_lambda_powertools"]
diff --git a/ruff.toml b/ruff.toml
index fa89816a7de..1bdb7ffa4ae 100644
--- a/ruff.toml
+++ b/ruff.toml
@@ -33,6 +33,7 @@ lint.select = [
lint.ignore = [
"W291", # https://beta.ruff.rs/docs/rules/trailing-whitespace/
"PLR0913", # https://beta.ruff.rs/docs/rules/too-many-arguments/
+ "PLR0917", # https://docs.astral.sh/ruff/rules/too-many-positional-arguments/
"PLR2004", #https://beta.ruff.rs/docs/rules/magic-value-comparison/
"PLW0603", #https://beta.ruff.rs/docs/rules/global-statement/
"B904", # raise-without-from-inside-except - disabled temporarily
@@ -41,6 +42,9 @@ lint.ignore = [
"A005",
"TC006", # https://docs.astral.sh/ruff/rules/runtime-cast-value/
"PLC0415", # https://docs.astral.sh/ruff/rules/import-outside-top-level/
+ "UP006",
+ "UP007",
+ "UP035",
]
# Exclude files and directories
@@ -62,7 +66,7 @@ exclude = [
# Maximum line length
line-length = 120
-target-version = "py38"
+target-version = "py310"
fix = true
lint.fixable = ["I", "COM812", "W"]
diff --git a/tests/e2e/utils/data_fetcher/common.py b/tests/e2e/utils/data_fetcher/common.py
index 1300daa55aa..61a56386251 100644
--- a/tests/e2e/utils/data_fetcher/common.py
+++ b/tests/e2e/utils/data_fetcher/common.py
@@ -2,7 +2,7 @@
import time
from concurrent.futures import Future, ThreadPoolExecutor
from datetime import datetime
-from typing import List, Optional, Tuple
+from typing import List, Tuple
import boto3
import requests
@@ -18,8 +18,8 @@
class GetLambdaResponseOptions(BaseModel):
lambda_arn: str
- payload: Optional[str] = None
- client: Optional[LambdaClient] = None
+ payload: str | None = None
+ client: LambdaClient | None = None
raise_on_error: bool = True
model_config = ConfigDict(
@@ -29,8 +29,8 @@ class GetLambdaResponseOptions(BaseModel):
def get_lambda_response(
lambda_arn: str,
- payload: Optional[str] = None,
- client: Optional[LambdaClient] = None,
+ payload: str | None = None,
+ client: LambdaClient | None = None,
raise_on_error: bool = True,
) -> GetLambdaResponse:
"""Invoke function synchronously
@@ -39,9 +39,9 @@ def get_lambda_response(
----------
lambda_arn : str
Lambda function ARN to invoke
- payload : Optional[str], optional
+ payload : str | None, optional
JSON payload for Lambda invocation, by default None
- client : Optional[LambdaClient], optional
+ client : LambdaClient | None, optional
Boto3 Lambda SDK client, by default None
raise_on_error : bool, optional
Whether to raise exception upon invocation error, by default True
diff --git a/tests/e2e/utils/data_fetcher/logs.py b/tests/e2e/utils/data_fetcher/logs.py
index dc036cba36e..eaa783fbba5 100644
--- a/tests/e2e/utils/data_fetcher/logs.py
+++ b/tests/e2e/utils/data_fetcher/logs.py
@@ -1,6 +1,6 @@
import json
from datetime import datetime
-from typing import List, Optional, Union
+from typing import Any, List, Union
import boto3
from mypy_boto3_logs.client import CloudWatchLogsClient
@@ -14,12 +14,12 @@ class Log(BaseModel, extra="allow"):
message: Union[dict, str]
timestamp: str
service: str
- cold_start: Optional[bool] = None
- function_name: Optional[str] = None
- function_memory_size: Optional[str] = None
- function_arn: Optional[str] = None
- function_request_id: Optional[str] = None
- xray_trace_id: Optional[str] = None
+ cold_start: bool | None = None
+ function_name: str | None = None
+ function_memory_size: str | None = None
+ function_arn: str | None = None
+ function_request_id: str | None = None
+ xray_trace_id: str | None = None
class LogFetcher:
@@ -27,8 +27,8 @@ def __init__(
self,
function_name: str,
start_time: datetime,
- log_client: Optional[CloudWatchLogsClient] = None,
- filter_expression: Optional[str] = None,
+ log_client: CloudWatchLogsClient | None = None,
+ filter_expression: str | None = None,
minimum_log_entries: int = 1,
):
"""Fetch and expose Powertools for AWS Lambda (Python) Logger logs from CloudWatch Logs
@@ -39,9 +39,9 @@ def __init__(
Name of Lambda function to fetch logs for
start_time : datetime
Start date range to filter traces
- log_client : Optional[CloudWatchLogsClient], optional
+ log_client : CloudWatchLogsClient | None, optional
Amazon CloudWatch Logs Client, by default boto3.client('logs)
- filter_expression : Optional[str], optional
+ filter_expression : str | None, optional
CloudWatch Logs Filter Pattern expression, by default "message"
minimum_log_entries: int
Minimum number of log entries to be retrieved before exhausting retry attempts
@@ -54,14 +54,14 @@ def __init__(
self.minimum_log_entries = minimum_log_entries
self.logs: List[Log] = self._get_logs()
- def get_log(self, key: str, value: Optional[any] = None) -> List[Log]:
+ def get_log(self, key: str, value: Any | None = None) -> List[Log]:
"""Get logs based on key or key and value
Parameters
----------
key : str
Log key name
- value : Optional[any], optional
+ value : Any | None, optional
Log value, by default None
Returns
@@ -132,8 +132,8 @@ def get_logs(
function_name: str,
start_time: datetime,
minimum_log_entries: int = 1,
- filter_expression: Optional[str] = None,
- log_client: Optional[CloudWatchLogsClient] = None,
+ filter_expression: str | None = None,
+ log_client: CloudWatchLogsClient | None = None,
) -> LogFetcher:
"""_summary_
@@ -145,9 +145,9 @@ def get_logs(
Start date range to filter traces
minimum_log_entries : int
Minimum number of log entries to be retrieved before exhausting retry attempts
- log_client : Optional[CloudWatchLogsClient], optional
+ log_client : CloudWatchLogsClient | None, optional
Amazon CloudWatch Logs Client, by default boto3.client('logs)
- filter_expression : Optional[str], optional
+ filter_expression : str | None, optional
CloudWatch Logs Filter Pattern expression, by default "message"
Returns
diff --git a/tests/e2e/utils/data_fetcher/traces.py b/tests/e2e/utils/data_fetcher/traces.py
index f8b364fc97c..4309fa0d520 100644
--- a/tests/e2e/utils/data_fetcher/traces.py
+++ b/tests/e2e/utils/data_fetcher/traces.py
@@ -1,6 +1,6 @@
import json
from datetime import datetime, timedelta
-from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional
+from typing import TYPE_CHECKING, Any, Dict, Generator, List
import boto3
from botocore.paginate import PageIterator
@@ -17,10 +17,10 @@ class TraceSubsegment(BaseModel):
name: str
start_time: float
end_time: float
- aws: Optional[dict] = None
- subsegments: Optional[List["TraceSubsegment"]] = None
- annotations: Optional[Dict[str, Any]] = None
- metadata: Optional[Dict[str, Dict[str, Any]]] = None
+ aws: dict | None = None
+ subsegments: List["TraceSubsegment"] | None = None
+ annotations: Dict[str, Any] | None = None
+ metadata: Dict[str, Dict[str, Any]] | None = None
class TraceDocument(BaseModel):
@@ -29,10 +29,10 @@ class TraceDocument(BaseModel):
start_time: float
end_time: float
trace_id: str
- parent_id: Optional[str] = None
+ parent_id: str | None = None
aws: Dict
origin: str
- subsegments: Optional[List[TraceSubsegment]] = None
+ subsegments: List[TraceSubsegment] | None = None
class TraceFetcher:
@@ -42,11 +42,11 @@ def __init__(
self,
filter_expression: str,
start_date: datetime,
- end_date: Optional[datetime] = None,
- xray_client: Optional[XRayClient] = None,
- exclude_segment_name: Optional[List[str]] = None,
- resource_name: Optional[List[str]] = None,
- origin: Optional[List[str]] = None,
+ end_date: datetime | None = None,
+ xray_client: XRayClient | None = None,
+ exclude_segment_name: List[str] | None = None,
+ resource_name: List[str] | None = None,
+ origin: List[str] | None = None,
minimum_traces: int = 1,
):
"""Fetch and expose traces from X-Ray based on parameters
@@ -67,15 +67,15 @@ def __init__(
see: https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html
start_date : datetime
Start date range to filter traces
- end_date : Optional[datetime], optional
+ end_date : datetime | None, optional
End date range to filter traces, by default 5 minutes past start_date
- xray_client : Optional[XRayClient], optional
+ xray_client : XRayClient | None, optional
AWS X-Ray SDK Client, by default boto3.client('xray')
- exclude_segment_name : Optional[List[str]], optional
+ exclude_segment_name : List[str] | None, optional
Name of segments to exclude, by default ["Initialization", "Invocation", "Overhead"]
- resource_name : Optional[List[str]], optional
+ resource_name : List[str] | None, optional
Name of resource to filter traces (e.g., function name), by default None
- origin : Optional[List[str]], optional
+ origin : List[str] | None, optional
Trace origin name to filter traces, by default ["AWS::Lambda::Function"]
minimum_traces : int
Minimum number of traces to be retrieved before exhausting retry attempts
@@ -106,7 +106,7 @@ def __init__(
self.trace_documents = self._get_trace_documents(trace_ids)
self.subsegments = self._get_subsegments()
- def get_annotation(self, key: str, value: Optional[any] = None) -> List:
+ def get_annotation(self, key: str, value: Any | None = None) -> List:
return [
annotation
for annotation in self.annotations
@@ -223,11 +223,11 @@ def _get_trace_documents(self, trace_ids: List[str]) -> Dict[str, TraceDocument]
def get_traces(
filter_expression: str,
start_date: datetime,
- end_date: Optional[datetime] = None,
- xray_client: Optional[XRayClient] = None,
- exclude_segment_name: Optional[List[str]] = None,
- resource_name: Optional[List[str]] = None,
- origin: Optional[List[str]] = None,
+ end_date: datetime | None = None,
+ xray_client: XRayClient | None = None,
+ exclude_segment_name: List[str] | None = None,
+ resource_name: List[str] | None = None,
+ origin: List[str] | None = None,
minimum_traces: int = 1,
) -> TraceFetcher:
"""Fetch traces from AWS X-Ray
@@ -239,15 +239,15 @@ def get_traces(
see: https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html
start_date : datetime
Start date range to filter traces
- end_date : Optional[datetime], optional
+ end_date : datetime | None, optional
End date range to filter traces, by default 5 minutes past start_date
- xray_client : Optional[XRayClient], optional
+ xray_client : XRayClient | None, optional
AWS X-Ray SDK Client, by default boto3.client('xray')
- exclude_segment_name : Optional[List[str]], optional
+ exclude_segment_name : List[str] | None, optional
Name of segments to exclude, by default ["Initialization", "Invocation", "Overhead"]
- resource_name : Optional[List[str]], optional
+ resource_name : List[str] | None, optional
Name of resource to filter traces (e.g., function name), by default None
- origin : Optional[List[str]], optional
+ origin : List[str] | None, optional
Trace origin name to filter traces, by default ["AWS::Lambda::Function"]
minimum_traces : int
Minimum number of traces to be retrieved before exhausting retry attempts
diff --git a/tests/events/eventBridgeEvent.json b/tests/events/eventBridgeEvent.json
index 65872cf9a34..f7c6d4c0d37 100644
--- a/tests/events/eventBridgeEvent.json
+++ b/tests/events/eventBridgeEvent.json
@@ -6,12 +6,9 @@
"account": "111122223333",
"time": "2017-12-22T18:43:48Z",
"region": "us-west-1",
- "resources": [
- "arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0"
- ],
+ "resources": [],
"detail": {
"instance_id": "i-1234567890abcdef0",
"state": "terminated"
- },
- "replay-name": "replay_archive"
-}
+ }
+}
\ No newline at end of file
diff --git a/tests/functional/batch/_pydantic/sample_models.py b/tests/functional/batch/_pydantic/sample_models.py
index c2912b3f8a3..d3974ccce82 100644
--- a/tests/functional/batch/_pydantic/sample_models.py
+++ b/tests/functional/batch/_pydantic/sample_models.py
@@ -1,5 +1,5 @@
import json
-from typing import Dict, Optional
+from typing import Dict
from pydantic import field_validator
@@ -44,8 +44,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]):
class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel):
- NewImage: Optional[OrderDynamoDB] = None
- OldImage: Optional[OrderDynamoDB] = None
+ NewImage: OrderDynamoDB | None = None
+ OldImage: OrderDynamoDB | None = None
class OrderDynamoDBRecord(DynamoDBStreamRecordModel):
diff --git a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py
index 382cbdb0335..1e6a0452d2a 100644
--- a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py
+++ b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py
@@ -1,7 +1,7 @@
import json
import uuid
from random import randint
-from typing import Any, Awaitable, Callable, Dict, Optional
+from typing import Any, Awaitable, Callable, Dict
import pytest
from pydantic import BaseModel, field_validator
@@ -311,8 +311,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]):
return json.loads(value)
class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel):
- NewImage: Optional[OrderDynamoDB] = None
- OldImage: Optional[OrderDynamoDB] = None
+ NewImage: OrderDynamoDB | None = None
+ OldImage: OrderDynamoDB | None = None
class OrderDynamoDBRecord(DynamoDBStreamRecordModel):
dynamodb: OrderDynamoDBChangeRecord
@@ -355,8 +355,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]):
return json.loads(value)
class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel):
- NewImage: Optional[OrderDynamoDB] = None
- OldImage: Optional[OrderDynamoDB] = None
+ NewImage: OrderDynamoDB | None = None
+ OldImage: OrderDynamoDB | None = None
class OrderDynamoDBRecord(DynamoDBStreamRecordModel):
dynamodb: OrderDynamoDBChangeRecord
diff --git a/tests/functional/batch/required_dependencies/test_utilities_batch.py b/tests/functional/batch/required_dependencies/test_utilities_batch.py
index 43c2aa16191..e8e544c127e 100644
--- a/tests/functional/batch/required_dependencies/test_utilities_batch.py
+++ b/tests/functional/batch/required_dependencies/test_utilities_batch.py
@@ -1,6 +1,7 @@
from __future__ import annotations
import json
+import logging
import uuid
from random import randint
from typing import TYPE_CHECKING, Any
@@ -861,3 +862,76 @@ async def simple_async_handler(record: SQSRecord):
# THEN record is processed successfully using asyncio.run()
assert result == {"batchItemFailures": []}
assert result == {"batchItemFailures": []}
+
+
+def test_batch_processor_logs_exception_with_injected_logger(sqs_event_factory, caplog):
+ fail_record = sqs_event_factory("fail")
+ success_record = sqs_event_factory("success")
+
+ def handler(record):
+ if "fail" in record["body"]:
+ raise ValueError("intentional failure")
+ return record["body"]
+
+ test_logger = logging.getLogger("test_logger")
+ processor = BatchProcessor(event_type=EventType.SQS, logger=test_logger)
+
+ with caplog.at_level(logging.WARNING, logger="test_logger"):
+ process_partial_response(
+ event={"Records": [fail_record, success_record]},
+ record_handler=handler,
+ processor=processor,
+ )
+
+ warning_records = [r for r in caplog.records if r.levelno == logging.WARNING]
+ assert len(warning_records) == 1, f"Expected 1 WARNING log, got {len(warning_records)}"
+ assert "intentional failure" in warning_records[0].getMessage() or warning_records[0].exc_info is not None
+ assert warning_records[0].exc_info is not None, "Expected exc_info (traceback) in log record"
+ assert warning_records[0].exc_info[0] is ValueError
+
+
+def test_batch_processor_does_not_log_without_injected_logger(sqs_event_factory, caplog):
+ fail_record = sqs_event_factory("fail")
+
+ def handler(record):
+ raise ValueError("intentional failure")
+
+ processor = BatchProcessor(event_type=EventType.SQS, raise_on_entire_batch_failure=False, logger=None)
+
+ with caplog.at_level(logging.WARNING, logger="aws_lambda_powertools.utilities.batch.base"):
+ process_partial_response(
+ event={"Records": [fail_record]},
+ record_handler=handler,
+ processor=processor,
+ )
+
+ warning_records = [r for r in caplog.records if r.levelno == logging.WARNING]
+ assert len(warning_records) == 0, "Expected no WARNING logs when logger is None"
+
+
+def test_sqs_fifo_circuit_breaker_does_not_log(sqs_event_fifo_factory, caplog):
+ failing_record = sqs_event_fifo_factory("fail", "group-1")
+ short_circuited_record = sqs_event_fifo_factory("would-succeed", "group-1")
+
+ def handler(record):
+ if "fail" in record["body"]:
+ raise ValueError("first record failure")
+ return record["body"]
+
+ test_logger = logging.getLogger("test_logger")
+ processor = SqsFifoPartialProcessor(logger=test_logger)
+ processor.raise_on_entire_batch_failure = False
+
+ with caplog.at_level(logging.WARNING, logger="test_logger"):
+ process_partial_response(
+ event={"Records": [failing_record, short_circuited_record]},
+ record_handler=handler,
+ processor=processor,
+ )
+
+ warning_records = [r for r in caplog.records if r.levelno == logging.WARNING]
+ assert len(warning_records) == 1, (
+ f"Expected exactly 1 WARNING (real exception only), got {len(warning_records)}: "
+ + str([r.getMessage() for r in warning_records])
+ )
+ assert warning_records[0].exc_info[0] is ValueError
diff --git a/tests/functional/circuit_breaker/__init__.py b/tests/functional/circuit_breaker/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/functional/circuit_breaker/conftest.py b/tests/functional/circuit_breaker/conftest.py
new file mode 100644
index 00000000000..30925dfc5e8
--- /dev/null
+++ b/tests/functional/circuit_breaker/conftest.py
@@ -0,0 +1,113 @@
+from __future__ import annotations
+
+import threading
+
+import pytest
+
+import aws_lambda_powertools.utilities.circuit_breaker.base as base_module
+from aws_lambda_powertools.utilities.circuit_breaker.base import CircuitBreakerHandler
+from aws_lambda_powertools.utilities.circuit_breaker.persistence.base import (
+ CircuitBreakerExistingLockError,
+ CircuitBreakerPersistenceLayer,
+)
+from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord
+from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitState
+
+
+class FakePersistence(CircuitBreakerPersistenceLayer):
+ """In-memory store for exercising the handler state machine without DynamoDB."""
+
+ # Each DynamoDB operation is atomic, including the conditional put; the fake must be
+ # too, or threaded tests race inside the fake instead of the code under test.
+ # Class-level so store instances sharing a db (multi-environment tests) share it.
+ _db_lock = threading.Lock()
+
+ def __init__(self):
+ self.db: dict[str, CircuitStateRecord] = {}
+ super().__init__()
+
+ def _get_record(self, name: str) -> CircuitStateRecord | None:
+ with self._db_lock:
+ if name not in self.db:
+ return None
+ stored = self.db[name]
+ # Return a copy so the handler can't mutate stored state by reference.
+ return CircuitStateRecord(
+ name=stored.name,
+ state=stored.state,
+ failure_count=stored.failure_count,
+ opened_at=stored.opened_at,
+ half_open_owner=stored.half_open_owner,
+ probe_lease_expiry=stored.probe_lease_expiry,
+ )
+
+ def _put_record(
+ self,
+ record: CircuitStateRecord,
+ condition: str | None = None,
+ expected_opened_at: int | None = None,
+ ) -> None:
+ with self._db_lock:
+ if condition == "half_open":
+ existing = self.db.get(record.name)
+ now = CircuitBreakerHandler._now()
+
+ # Mirror the DynamoDB condition: two valid paths
+ # Path 1: state=OPEN AND no owner (AND opened_at matches if provided)
+ # Path 2: state=HALF_OPEN AND probe_lease_expiry <= now (lease takeover)
+ fresh_election_ok = existing is None or (
+ existing.state == CircuitState.OPEN
+ and existing.half_open_owner is None
+ and (expected_opened_at is None or existing.opened_at == expected_opened_at)
+ )
+ lease_takeover_ok = (
+ existing is not None
+ and existing.state == CircuitState.HALF_OPEN
+ and existing.probe_lease_expiry is not None
+ and now >= existing.probe_lease_expiry
+ )
+
+ if not fresh_election_ok and not lease_takeover_ok:
+ raise CircuitBreakerExistingLockError
+ self.db[record.name] = record
+
+ def _update_record(self, record: CircuitStateRecord) -> None:
+ # Mirror DynamoDB UpdateItem semantics: a partial merge driven by which
+ # attributes the backend actually writes, NOT a wholesale replace. This is
+ # what exposes attributes the update path forgets to clear (e.g. a stale
+ # half_open_owner left behind on reopen).
+ with self._db_lock:
+ existing = self.db.get(record.name)
+ if existing is None:
+ self.db[record.name] = record
+ return
+ existing.state = record.state
+ existing.failure_count = record.failure_count
+ existing.expiry_timestamp = record.expiry_timestamp
+ # Leaving HALF_OPEN (close or reopen) always releases the probe-owner lock and
+ # probe lease; only opened_at differs between the two transitions.
+ existing.half_open_owner = None
+ existing.probe_lease_expiry = None
+ existing.opened_at = record.opened_at
+
+
+@pytest.fixture
+def store() -> FakePersistence:
+ return FakePersistence()
+
+
+@pytest.fixture(autouse=True)
+def reset_local_counters():
+ """Clear the per-environment module-level counters between tests."""
+ base_module._LOCAL_FAILURES.clear()
+ base_module._LOCAL_SUCCESSES.clear()
+ base_module._LAST_OBSERVED_STATE.clear()
+ yield
+ base_module._LOCAL_FAILURES.clear()
+ base_module._LOCAL_SUCCESSES.clear()
+ base_module._LAST_OBSERVED_STATE.clear()
+
+
+@pytest.fixture
+def now() -> int:
+ return base_module.CircuitBreakerHandler._now()
diff --git a/tests/functional/circuit_breaker/test_circuit_breaker.py b/tests/functional/circuit_breaker/test_circuit_breaker.py
new file mode 100644
index 00000000000..1db372ee900
--- /dev/null
+++ b/tests/functional/circuit_breaker/test_circuit_breaker.py
@@ -0,0 +1,836 @@
+from __future__ import annotations
+
+import threading
+import time
+import warnings
+
+import pytest
+
+import aws_lambda_powertools.utilities.circuit_breaker.base as base_module
+from aws_lambda_powertools.utilities.circuit_breaker import (
+ CircuitBreakerConfig,
+ CircuitBreakerOpenError,
+ CircuitState,
+ CircuitTransition,
+ circuit_breaker,
+)
+from aws_lambda_powertools.utilities.circuit_breaker.exceptions import CircuitBreakerError
+from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord
+
+# All tests disable the local read cache (max_age=0) so each call re-reads the fake store.
+
+
+def test_closed_circuit_returns_result_and_writes_nothing(store):
+ @circuit_breaker(name="c", persistence_store=store, config=CircuitBreakerConfig(local_cache_max_age=0))
+ def call(value):
+ return value * 2
+
+ assert call(21) == 42
+ assert store.db == {}, "healthy path must not write to the store"
+
+
+def test_trips_open_after_failure_threshold(store):
+ config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ raise ConnectionError("downstream down")
+
+ for _ in range(3):
+ with pytest.raises(ConnectionError):
+ call()
+
+ assert store.db["c"].state == CircuitState.OPEN
+ assert store.db["c"].opened_at is not None
+
+
+def test_open_with_callback_returns_callback_value_without_calling_protected(store, now):
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now)
+ protected_ran = {"value": False}
+
+ def on_open(order, circuit):
+ return {"buffered": order, "state": str(circuit.state)}
+
+ config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, on_circuit_open=on_open, config=config)
+ def charge(order):
+ protected_ran["value"] = True
+ return f"charged {order}"
+
+ result = charge({"id": 1})
+ assert result == {"buffered": {"id": 1}, "state": "OPEN"}
+ assert protected_ran["value"] is False
+
+
+def test_open_without_callback_raises_with_circuit_info(store, now):
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=7, opened_at=now)
+ config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def charge(order):
+ return f"charged {order}"
+
+ with pytest.raises(CircuitBreakerOpenError) as exc_info:
+ charge({"id": 1})
+
+ assert exc_info.value.circuit.name == "c"
+ assert exc_info.value.circuit.failure_count == 7
+
+
+def test_half_open_probe_success_closes_after_success_threshold(store, now):
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100)
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ return "ok"
+
+ call() # wins the probe lock, state becomes HALF_OPEN
+ assert store.db["c"].state == CircuitState.HALF_OPEN
+
+ call() # second consecutive probe success closes the circuit
+ assert store.db["c"].state == CircuitState.CLOSED
+
+
+def test_half_open_probe_failure_reopens(store, now):
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100)
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ raise ConnectionError("still down")
+
+ with pytest.raises(ConnectionError):
+ call()
+
+ assert store.db["c"].state == CircuitState.OPEN
+
+
+# --------------------------------------------------------------------------- bug regressions
+
+
+def test_half_open_can_be_reacquired_after_failed_probe_reopens(store, now):
+ # Bug #1: a failed probe (HALF_OPEN -> OPEN) must clear the half_open_owner so a
+ # later recovery window can elect a prober again. Otherwise the circuit is stuck
+ # OPEN forever because attribute_not_exists(half_open_owner) never holds again.
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100)
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0)
+
+ outcomes = iter([ConnectionError("still down"), "recovered"])
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ result = next(outcomes)
+ if isinstance(result, Exception):
+ raise result
+ return result
+
+ # First recovery window: env wins the probe, probe fails, circuit reopens.
+ with pytest.raises(ConnectionError):
+ call()
+ assert store.db["c"].state == CircuitState.OPEN
+ assert store.db["c"].half_open_owner is None, "reopen must release the probe lock"
+
+ # Second recovery window (opened_at is fresh, push it into the past again).
+ store.db["c"].opened_at = now - 100
+ # Downstream recovered: the env must be able to acquire the probe again and run it.
+ assert call() == "recovered"
+ assert store.db["c"].state == CircuitState.HALF_OPEN
+
+
+def test_open_callback_receives_keyword_arguments_intact(store, now):
+ # Bug #3: the callback must receive the same kwargs the protected function got,
+ # as kwargs, not flattened into positional values.
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now)
+ config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0)
+
+ captured = {}
+
+ def on_open(order, customer, circuit):
+ captured["order"] = order
+ captured["customer"] = customer
+ return "buffered"
+
+ @circuit_breaker(name="c", persistence_store=store, on_circuit_open=on_open, config=config)
+ def charge(order, customer):
+ return "charged"
+
+ # Called entirely with keyword arguments, deliberately out of signature order.
+ assert charge(customer="alice", order={"id": 1}) == "buffered"
+ assert captured["order"] == {"id": 1}
+ assert captured["customer"] == "alice"
+
+
+def test_consecutive_failures_trip_but_a_success_resets_the_streak(store):
+ # The failure counter is per-environment and counts *consecutive* failures as this
+ # env sees them: any success in between must reset the streak.
+ config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0)
+
+ should_fail = {"value": True}
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ if should_fail["value"]:
+ raise ConnectionError("down")
+ return "ok"
+
+ # Two failures, then a success: the streak resets, so the circuit must NOT be tripping.
+ for _ in range(2):
+ with pytest.raises(ConnectionError):
+ call()
+ should_fail["value"] = False
+ assert call() == "ok"
+ assert "c" not in store.db
+
+ # A fresh run of 3 consecutive failures from here must trip it.
+ should_fail["value"] = True
+ for _ in range(3):
+ with pytest.raises(ConnectionError):
+ call()
+ assert store.db["c"].state == CircuitState.OPEN
+
+
+def test_circuit_can_retrip_after_a_previous_close(store):
+ # Regression guard: a healthy circuit's steady state is a *persisted CLOSED* record.
+ # Reading that record must not reset the running failure counter, or the circuit
+ # could never trip again after it has closed once.
+ config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0)
+
+ # Pretend a prior recovery left a persisted CLOSED record behind.
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.CLOSED, failure_count=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ raise ConnectionError("down again")
+
+ for _ in range(3):
+ with pytest.raises(ConnectionError):
+ call()
+
+ assert store.db["c"].state == CircuitState.OPEN, "circuit must re-trip even with a prior CLOSED record present"
+
+
+def test_full_lifecycle_survives_multiple_recovery_cycles(store):
+ # End-to-end guard tying #1 together: the circuit must cycle OPEN -> HALF_OPEN ->
+ # CLOSED, re-trip, survive a failed probe (which reopens and must release the lock),
+ # and then recover again. Before the owner-release fix the second recovery dead-locked.
+ config = CircuitBreakerConfig(
+ failure_threshold=2,
+ recovery_timeout=30,
+ success_threshold=2,
+ local_cache_max_age=0,
+ )
+ mode = {"value": "fail"}
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ if mode["value"] == "fail":
+ raise ConnectionError("down")
+ return "ok"
+
+ def elapse_recovery_window():
+ store.db["c"].opened_at -= 100
+
+ # Trip open.
+ for _ in range(2):
+ with pytest.raises(ConnectionError):
+ call()
+ assert store.db["c"].state == CircuitState.OPEN
+
+ # Recover through two successful probes.
+ mode["value"] = "ok"
+ elapse_recovery_window()
+ assert call() == "ok"
+ assert store.db["c"].state == CircuitState.HALF_OPEN
+ assert call() == "ok"
+ assert store.db["c"].state == CircuitState.CLOSED
+
+ # Re-trip from the now-CLOSED state.
+ mode["value"] = "fail"
+ for _ in range(2):
+ with pytest.raises(ConnectionError):
+ call()
+ assert store.db["c"].state == CircuitState.OPEN
+
+ # A failed probe reopens it and must release the probe lock.
+ elapse_recovery_window()
+ with pytest.raises(ConnectionError):
+ call()
+ assert store.db["c"].state == CircuitState.OPEN
+ assert store.db["c"].half_open_owner is None
+
+ # The lock being free, recovery must be possible again.
+ mode["value"] = "ok"
+ elapse_recovery_window()
+ assert call() == "ok"
+ assert store.db["c"].state == CircuitState.HALF_OPEN
+ assert call() == "ok"
+ assert store.db["c"].state == CircuitState.CLOSED
+
+
+def test_opened_at_zero_is_treated_as_a_real_timestamp(store):
+ # Bug #7: opened_at == 0 is a valid (if pathological) epoch timestamp, not "missing".
+ # `record.opened_at or self._now()` wrongly re-anchors it to now, pinning OPEN forever.
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=0)
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ return "recovered"
+
+ # opened_at=0 is far in the past, so the recovery window has long elapsed:
+ # the call must be allowed to probe, not short-circuited.
+ assert call() == "recovered"
+ assert store.db["c"].state in (CircuitState.HALF_OPEN, CircuitState.CLOSED)
+
+
+def test_ignored_exception_does_not_trip_circuit(store):
+ config = CircuitBreakerConfig(
+ failure_threshold=2,
+ handled_exceptions=(ConnectionError,),
+ local_cache_max_age=0,
+ )
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ raise ValueError("caller error, not a downstream failure")
+
+ for _ in range(5):
+ with pytest.raises(ValueError):
+ call()
+
+ assert "c" not in store.db
+
+
+def test_disabled_env_bypasses_circuit(store, now, monkeypatch):
+ monkeypatch.setenv("POWERTOOLS_CIRCUIT_BREAKER_DISABLED", "true")
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=9, opened_at=now)
+ config = CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ return "ran anyway"
+
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ assert call() == "ran anyway"
+
+
+def test_config_is_optional(store):
+ @circuit_breaker(name="c", persistence_store=store)
+ def call():
+ return "ok"
+
+ assert call() == "ok"
+
+
+# --------------------------------------------------------------------------- on_transition hook
+
+
+def test_on_transition_fires_for_each_state_change(store):
+ transitions: list[CircuitTransition] = []
+ config = CircuitBreakerConfig(
+ failure_threshold=2,
+ recovery_timeout=30,
+ success_threshold=1,
+ local_cache_max_age=0,
+ )
+ mode = {"value": "fail"}
+
+ @circuit_breaker(
+ name="c",
+ persistence_store=store,
+ on_transition=transitions.append,
+ config=config,
+ )
+ def call():
+ if mode["value"] == "fail":
+ raise ConnectionError("down")
+ return "ok"
+
+ # CLOSED -> OPEN after 2 failures.
+ for _ in range(2):
+ with pytest.raises(ConnectionError):
+ call()
+ # OPEN -> HALF_OPEN (election) -> CLOSED (success_threshold=1) on the recovery probe.
+ mode["value"] = "ok"
+ store.db["c"].opened_at -= 100
+ assert call() == "ok"
+
+ pairs = [(t.from_state, t.to_state) for t in transitions]
+ assert pairs == [
+ (CircuitState.CLOSED, CircuitState.OPEN),
+ (CircuitState.OPEN, CircuitState.HALF_OPEN),
+ (CircuitState.HALF_OPEN, CircuitState.CLOSED),
+ ]
+ assert all(t.circuit_name == "c" for t in transitions)
+ # opened_at carried on the open/probe transitions, absent on close.
+ assert transitions[0].opened_at is not None
+ assert transitions[-1].opened_at is None
+
+
+def test_on_transition_fires_on_failed_probe_reopen(store, now):
+ transitions: list[CircuitTransition] = []
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100)
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, on_transition=transitions.append, config=config)
+ def call():
+ raise ConnectionError("still down")
+
+ with pytest.raises(ConnectionError):
+ call()
+
+ pairs = [(t.from_state, t.to_state) for t in transitions]
+ assert pairs == [
+ (CircuitState.OPEN, CircuitState.HALF_OPEN),
+ (CircuitState.HALF_OPEN, CircuitState.OPEN),
+ ]
+
+
+def test_raising_on_transition_hook_is_swallowed(store):
+ config = CircuitBreakerConfig(failure_threshold=1, local_cache_max_age=0)
+
+ def boom(_transition):
+ raise RuntimeError("hook blew up")
+
+ @circuit_breaker(name="c", persistence_store=store, on_transition=boom, config=config)
+ def call():
+ raise ConnectionError("down")
+
+ # The hook raises during the CLOSED->OPEN notify, but the protected call's own
+ # ConnectionError must surface unchanged, not the hook's RuntimeError.
+ with pytest.raises(ConnectionError):
+ call()
+ assert store.db["c"].state == CircuitState.OPEN
+
+
+# --------------------------------------------------------------------------- bug regressions
+
+
+def test_stale_local_failures_reset_on_external_close(store, now):
+ """Bug 1: a partial failure streak in env A must not survive an external recovery cycle."""
+ config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=0)
+ mode = {"value": "fail"}
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ if mode["value"] == "fail":
+ raise ConnectionError("down")
+ return "ok"
+
+ # Env A accumulates 2 failures (below threshold of 3).
+ for _ in range(2):
+ with pytest.raises(ConnectionError):
+ call()
+ assert base_module._LOCAL_FAILURES["c"] == 2
+
+ # Simulate: another env trips the circuit, then a third closes it.
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=3, opened_at=now)
+ # Force env A to observe OPEN so _LAST_OBSERVED_STATE tracks the transition.
+ with pytest.raises(CircuitBreakerOpenError):
+ call()
+ # Now the circuit is externally closed.
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.CLOSED, failure_count=0)
+
+ # A single failure in env A must NOT re-trip (stale streak was invalidated).
+ mode["value"] = "fail"
+ with pytest.raises(ConnectionError):
+ call()
+ assert "c" not in store.db or store.db["c"].state == CircuitState.CLOSED
+ assert base_module._LOCAL_FAILURES["c"] == 1 # fresh count, not 3
+
+
+def test_store_write_failure_does_not_mask_downstream_result(store, now):
+ """Bug 2: if save_closed() fails, the successful probe result must still be returned."""
+ config = CircuitBreakerConfig(failure_threshold=3, recovery_timeout=30, success_threshold=1, local_cache_max_age=0)
+
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=3, opened_at=now - 100)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ return "payment_charged"
+
+ # Make the persistence write fail.
+ original_update = store._update_record
+
+ def failing_update(record):
+ raise RuntimeError("DynamoDB timeout")
+
+ store._update_record = failing_update
+
+ # The probe should still return the downstream result despite the write failure.
+ result = call()
+ assert result == "payment_charged"
+
+ store._update_record = original_update
+
+
+def test_store_write_failure_on_trip_does_not_replace_downstream_exception(store):
+ """Bug 2 (trip path): if save_open() fails, the downstream's own exception must propagate."""
+ config = CircuitBreakerConfig(failure_threshold=2, local_cache_max_age=0)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ raise ConnectionError("the real error")
+
+ # Make the persistence write fail.
+ def failing_put(record, condition=None, expected_opened_at=None):
+ raise RuntimeError("DynamoDB throttle")
+
+ store._put_record = failing_put
+
+ # Two failures should raise the ORIGINAL ConnectionError, not a RuntimeError from the store.
+ for _ in range(2):
+ with pytest.raises(ConnectionError, match="the real error"):
+ call()
+
+
+def test_probe_lease_takeover_when_owner_recycled(store, now):
+ """Design issue 1: a stranded HALF_OPEN probe with expired lease can be taken over."""
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0)
+
+ # Simulate: the probe owner ("dead-env") was recycled, lease has expired.
+ store.db["c"] = CircuitStateRecord(
+ name="c",
+ state=CircuitState.HALF_OPEN,
+ opened_at=now - 200,
+ half_open_owner="dead-env",
+ probe_lease_expiry=now - 10, # expired
+ )
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ return "recovered"
+
+ # Current environment should take over the expired lease and succeed.
+ result = call()
+ assert result == "recovered"
+ assert store.db["c"].state == CircuitState.CLOSED
+
+
+def test_half_open_non_owner_with_active_lease_is_rejected(store, now):
+ """Design issue 1 negative: active lease must NOT allow takeover."""
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0)
+
+ # Probe owner is alive (lease not expired yet).
+ store.db["c"] = CircuitStateRecord(
+ name="c",
+ state=CircuitState.HALF_OPEN,
+ opened_at=now - 50,
+ half_open_owner="other-env",
+ probe_lease_expiry=now + 999, # far in the future
+ )
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ return "should not run"
+
+ with pytest.raises(CircuitBreakerOpenError):
+ call()
+
+
+def test_half_open_expired_lease_lost_takeover_returns_open_response(store, now):
+ """Losing the takeover election must NOT probe: another thread/environment won
+ the conditional write between our expiry check and our acquire, so the call
+ has to get the open-circuit response — electing every candidate is exactly
+ the multi-prober bug the per-thread owner id exists to prevent."""
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0)
+
+ # A stranded probe with an expired lease, owned by someone else.
+ store.db["c"] = CircuitStateRecord(
+ name="c",
+ state=CircuitState.HALF_OPEN,
+ opened_at=now - 200,
+ half_open_owner="dead-env",
+ probe_lease_expiry=now - 10, # expired — takeover will be attempted
+ )
+
+ # The race's loser: the conditional election fails.
+ def lost_election(name, owner_id, opened_at):
+ return False
+
+ store.try_acquire_half_open = lost_election
+
+ protected_ran = {"value": False}
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ protected_ran["value"] = True
+ return "must not probe"
+
+ with pytest.raises(CircuitBreakerOpenError):
+ call()
+ assert protected_ran["value"] is False
+
+
+def test_open_lost_election_returns_open_response(store, now):
+ """Branch: try_acquire_half_open returns False (another env won the race)."""
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=1, local_cache_max_age=0)
+
+ # Circuit is OPEN and recovery window has elapsed, but election will fail
+ # because another env already holds the lock.
+ store.db["c"] = CircuitStateRecord(
+ name="c",
+ state=CircuitState.OPEN,
+ failure_count=5,
+ opened_at=now - 100,
+ half_open_owner="winner-env",
+ )
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ return "should not run"
+
+ with pytest.raises(CircuitBreakerOpenError):
+ call()
+
+
+def test_probe_ignored_exception_propagates_without_affecting_circuit(store, now):
+ """Branch: probe raises an exception that doesn't count as failure."""
+ config = CircuitBreakerConfig(
+ recovery_timeout=30,
+ success_threshold=1,
+ handled_exceptions=(ConnectionError,),
+ local_cache_max_age=0,
+ )
+
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 100)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ raise ValueError("not a counted failure")
+
+ with pytest.raises(ValueError, match="not a counted failure"):
+ call()
+ # Circuit should still be HALF_OPEN (not reopened), the ValueError didn't count.
+ assert store.db["c"].state == CircuitState.HALF_OPEN
+
+
+def test_local_cache_serves_state_without_store_read(store):
+ """Covers the cache hit path (persistence/base.py line 140)."""
+ config = CircuitBreakerConfig(failure_threshold=3, local_cache_max_age=60)
+ call_count = {"value": 0}
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ call_count["value"] += 1
+ return "ok"
+
+ # First call reads the store (cache miss).
+ assert call() == "ok"
+ # Second call should serve from cache — override _get_record to detect reads.
+ original_get = store._get_record
+ get_called = {"value": False}
+
+ def tracked_get(name):
+ get_called["value"] = True
+ return original_get(name)
+
+ store._get_record = tracked_get
+ assert call() == "ok"
+ assert not get_called["value"], "second call should have used the cache, not the store"
+ store._get_record = original_get
+
+
+def test_error_with_details_formatting():
+ """Covers exceptions.py line 28 — __str__ with details."""
+ err = CircuitBreakerError("main message", "extra detail")
+ assert str(err) == "main message - (extra detail)"
+
+
+# --------------------------------------------------------------------------- thread safety (#8320)
+
+
+def _run_in_threads(worker, count):
+ threads = [threading.Thread(target=worker) for _ in range(count)]
+ for thread in threads:
+ thread.start()
+ for thread in threads:
+ thread.join()
+
+
+def test_threads_elect_a_single_prober_on_recovery(store, now):
+ """Regression for #8320: after one thread wins the election, siblings must not also probe."""
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60)
+ # success_threshold=2 keeps the circuit HALF_OPEN after the winning probe, so a
+ # late-reading loser can never legitimately run the function through a closed circuit.
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0)
+ probes = []
+ open_responses = []
+ barrier = threading.Barrier(8)
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ probes.append(threading.current_thread().name)
+ return "ok"
+
+ def worker():
+ barrier.wait(timeout=10)
+ try:
+ call()
+ except CircuitBreakerOpenError:
+ open_responses.append(threading.current_thread().name)
+
+ _run_in_threads(worker, 8)
+
+ assert len(probes) == 1, "exactly one thread must probe per recovery window"
+ assert len(open_responses) == 7, "every other thread must get the open response"
+ assert store.db["c"].state == CircuitState.HALF_OPEN
+ assert store.db["c"].half_open_owner is not None
+
+
+class _RacyCounters(dict):
+ """Counter dict that yields between the read and the write of an increment.
+
+ Without this, the GIL makes the unlocked read-modify-write effectively atomic
+ (the interpreter rarely switches threads inside those few bytecodes), so a
+ missing lock would still pass. Holding every reader mid-increment long enough
+ for its siblings to read the same stale value makes the lost update
+ deterministic: unlocked, all threads write back the same count and the
+ threshold is never reached.
+ """
+
+ def get(self, key, default=None):
+ value = super().get(key, default)
+ time.sleep(0.005) # park mid-increment so sibling threads read the same stale value
+ return value
+
+
+def test_threads_trip_at_exactly_the_failure_threshold(store, monkeypatch):
+ """Racing increments must neither lose updates (tripping late) nor persist the trip twice."""
+ monkeypatch.setattr(base_module, "_LOCAL_FAILURES", _RacyCounters())
+ threads_count, threshold = 8, 5
+ config = CircuitBreakerConfig(failure_threshold=threshold, local_cache_max_age=0)
+ barrier = threading.Barrier(threads_count)
+ siblings_done = threading.Event()
+ done_lock = threading.Lock()
+ finished = []
+ save_open_counts = []
+ original_save_open = store.save_open
+
+ def blocking_save_open(name, failure_count, opened_at):
+ save_open_counts.append(failure_count)
+ if len(save_open_counts) > 1:
+ # A second persist is the bug itself; unblock immediately so it fails fast.
+ siblings_done.set()
+ # Park the tripping thread mid-persist until every sibling has recorded its
+ # failure. Code that resets the counter only after persisting lets the
+ # remaining threads cross the threshold too and persist the trip again.
+ siblings_done.wait(timeout=10)
+ original_save_open(name, failure_count=failure_count, opened_at=opened_at)
+
+ store.save_open = blocking_save_open
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ # Hold every thread inside the protected call so all pass the CLOSED check
+ # before any failure is recorded, forcing the increments to race.
+ barrier.wait(timeout=10)
+ raise ConnectionError("downstream down")
+
+ raised = []
+
+ def worker():
+ try:
+ call()
+ except ConnectionError:
+ raised.append(threading.current_thread().name)
+ finally:
+ with done_lock:
+ finished.append(threading.current_thread().name)
+ if len(finished) == threads_count - 1:
+ # Only the tripping thread is still parked in the persist spy.
+ siblings_done.set()
+
+ _run_in_threads(worker, threads_count)
+
+ assert save_open_counts == [threshold], "the trip must be persisted exactly once, at the threshold"
+ assert store.db["c"].state == CircuitState.OPEN
+ assert len(raised) == threads_count
+ assert base_module._LOCAL_FAILURES["c"] == threads_count - threshold, "post-trip failures restart the streak"
+
+
+def test_probe_ownership_is_per_thread_and_stable_across_invocations(store, now):
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60)
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0)
+ calls = []
+
+ @circuit_breaker(name="c", persistence_store=store, config=config)
+ def call():
+ calls.append(threading.current_thread().name)
+ return "ok"
+
+ # This thread wins the election; one more probe success is needed to close.
+ assert call() == "ok"
+ assert store.db["c"].state == CircuitState.HALF_OPEN
+
+ # A sibling thread must not inherit ownership (it did when the id was per-process).
+ sibling_outcome = []
+
+ def sibling():
+ try:
+ sibling_outcome.append(call())
+ except CircuitBreakerOpenError:
+ sibling_outcome.append("rejected")
+
+ _run_in_threads(sibling, 1)
+ assert sibling_outcome == ["rejected"]
+
+ # The owner's identity must survive across invocations so it can finish the recovery;
+ # a per-handler or per-invocation id would strand the circuit until the lease expired.
+ assert call() == "ok"
+ assert store.db["c"].state == CircuitState.CLOSED
+ assert len(calls) == 2
+
+
+def test_single_probe_spans_environments_and_threads(store, now):
+ """The same election covers threads in one process and separate environments."""
+ other_env = type(store)()
+ other_env.db = store.db
+ store.db["c"] = CircuitStateRecord(name="c", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60)
+ config = CircuitBreakerConfig(recovery_timeout=30, success_threshold=2, local_cache_max_age=0)
+ probes = []
+ open_responses = []
+ barrier = threading.Barrier(8)
+
+ def protect(persistence):
+ @circuit_breaker(name="c", persistence_store=persistence, config=config)
+ def call():
+ probes.append(threading.current_thread().name)
+ return "ok"
+
+ return call
+
+ calls = [protect(store), protect(other_env)]
+
+ def worker(index):
+ env_call = calls[index % 2]
+ barrier.wait(timeout=10)
+ try:
+ env_call()
+ except CircuitBreakerOpenError:
+ open_responses.append(threading.current_thread().name)
+
+ threads = [threading.Thread(target=worker, args=(index,)) for index in range(8)]
+ for thread in threads:
+ thread.start()
+ for thread in threads:
+ thread.join()
+
+ assert len(probes) == 1, "one probe across all threads of all environments"
+ assert len(open_responses) == 7
+
+
+def test_settings_are_kept_per_circuit_on_a_shared_layer(store, now):
+ """Configuring another circuit on the same layer must not stamp this one's probe lease."""
+ store.configure(CircuitBreakerConfig(recovery_timeout=30, local_cache_max_age=0), circuit_name="a")
+ store.configure(CircuitBreakerConfig(recovery_timeout=9999, local_cache_max_age=0), circuit_name="b")
+ store.db["a"] = CircuitStateRecord(name="a", state=CircuitState.OPEN, failure_count=5, opened_at=now - 60)
+
+ assert store.try_acquire_half_open("a", "owner-1", now - 60)
+
+ lease = store.db["a"].probe_lease_expiry
+ assert lease is not None
+ assert lease <= now + 30 + 2, "the lease must derive from circuit 'a' recovery_timeout, not 'b'"
diff --git a/tests/functional/circuit_breaker/test_dynamodb_persistence.py b/tests/functional/circuit_breaker/test_dynamodb_persistence.py
new file mode 100644
index 00000000000..ac67bfd0897
--- /dev/null
+++ b/tests/functional/circuit_breaker/test_dynamodb_persistence.py
@@ -0,0 +1,397 @@
+from __future__ import annotations
+
+import boto3
+import pytest
+from botocore.config import Config
+from botocore.stub import Stubber
+
+from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig
+from aws_lambda_powertools.utilities.circuit_breaker.exceptions import CircuitBreakerConfigError
+from aws_lambda_powertools.utilities.circuit_breaker.persistence import (
+ CircuitBreakerDynamoDBPersistence,
+)
+from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitState
+from aws_lambda_powertools.warnings import PowertoolsUserWarning
+
+TABLE_NAME = "CircuitBreakerState"
+
+
+@pytest.fixture
+def persistence():
+ client = boto3.client("dynamodb", config=Config(region_name="us-east-1"))
+ layer = CircuitBreakerDynamoDBPersistence(table_name=TABLE_NAME, boto3_client=client)
+ layer.configure(CircuitBreakerConfig(local_cache_max_age=0), circuit_name="payment")
+ return layer
+
+
+def test_get_state_missing_item_returns_closed(persistence):
+ stubber = Stubber(persistence.client)
+ stubber.add_response(
+ "get_item",
+ {},
+ {"TableName": TABLE_NAME, "Key": {"id": {"S": "payment"}}, "ConsistentRead": False},
+ )
+ with stubber:
+ record = persistence.get_state("payment")
+ assert record.state == CircuitState.CLOSED
+
+
+def test_get_state_failing_store_fails_open(persistence):
+ stubber = Stubber(persistence.client)
+ stubber.add_client_error("get_item", service_error_code="InternalServerError")
+ with stubber:
+ record = persistence.get_state("payment")
+ assert record.state == CircuitState.CLOSED, "store failure must fail open (CLOSED)"
+
+
+def _capture_put_item(persistence):
+ """Patch put_item to capture its params instead of asserting a time-dependent TTL."""
+ captured = {}
+ original = persistence.client.put_item
+
+ def capturing(**kwargs):
+ captured.update(kwargs)
+ return {}
+
+ persistence.client.put_item = capturing
+ return captured, lambda: setattr(persistence.client, "put_item", original)
+
+
+def test_save_open_writes_open_item(persistence):
+ captured, restore = _capture_put_item(persistence)
+ try:
+ persistence.save_open("payment", failure_count=5, opened_at=1000)
+ finally:
+ restore()
+
+ item = captured["Item"]
+ assert item["id"] == {"S": "payment"}
+ assert item["state"] == {"S": "OPEN"}
+ assert item["failure_count"] == {"N": "5"}
+ assert item["opened_at"] == {"N": "1000"}
+ assert "expiration" in item, "open item must carry a TTL"
+
+
+def test_try_acquire_half_open_wins(persistence):
+ captured, restore = _capture_put_item(persistence)
+ try:
+ assert persistence.try_acquire_half_open("payment", "env-a", 1000) is True
+ finally:
+ restore()
+
+ item = captured["Item"]
+ assert item["state"] == {"S": "HALF_OPEN"}
+ assert item["half_open_owner"] == {"S": "env-a"}
+ assert item["opened_at"] == {"N": "1000"}
+ assert "expiration" in item
+ # Condition supports both fresh election (OPEN, no owner, matching opened_at) and
+ # lease takeover (HALF_OPEN with expired lease).
+ assert "#state = :open AND attribute_not_exists(#half_open_owner)" in captured["ConditionExpression"]
+ assert "#probe_lease_expiry <= :now" in captured["ConditionExpression"]
+ assert captured["ExpressionAttributeValues"][":open"] == {"S": "OPEN"}
+ assert captured["ExpressionAttributeValues"][":expected_opened_at"] == {"N": "1000"}
+ assert "probe_lease_expiry" in item
+
+
+def test_try_acquire_half_open_loses_on_conditional_failure(persistence):
+ stubber = Stubber(persistence.client)
+ stubber.add_client_error("put_item", service_error_code="ConditionalCheckFailedException")
+ with stubber:
+ assert persistence.try_acquire_half_open("payment", "env-b", 1000) is False
+
+
+def test_save_closed_updates_record(persistence):
+ stubber = Stubber(persistence.client)
+ stubber.add_response("update_item", {})
+ with stubber:
+ persistence.save_closed("payment")
+ stubber.assert_no_pending_responses()
+
+
+# --------------------------------------------------------------------------- bug regressions
+
+
+def test_save_reopen_removes_half_open_owner(persistence):
+ # Bug #1: HALF_OPEN -> OPEN must clear half_open_owner, otherwise the next
+ # probe election (attribute_not_exists(half_open_owner)) can never succeed.
+ captured = {}
+ original_update = persistence.client.update_item
+
+ def capturing_update(**kwargs):
+ captured.update(kwargs)
+ return {}
+
+ persistence.client.update_item = capturing_update
+ try:
+ persistence.save_reopen("payment", opened_at=2000)
+ finally:
+ persistence.client.update_item = original_update
+
+ expression = captured["UpdateExpression"]
+ assert "REMOVE" in expression
+ assert captured["ExpressionAttributeNames"]["#half_open_owner"] == "half_open_owner"
+ assert "#half_open_owner" in expression.split("REMOVE", 1)[1], "owner must be in the REMOVE clause"
+
+
+def test_save_open_item_contains_expiration_attribute(persistence):
+ # Bug #2: the written item must carry the TTL (expiration) attribute, otherwise
+ # the documented self-cleaning of abandoned circuits never happens. Capture the
+ # actual PutItem params rather than asserting an exact (time-dependent) value.
+ captured = {}
+
+ original_put = persistence.client.put_item
+
+ def capturing_put(**kwargs):
+ captured.update(kwargs)
+ return {}
+
+ persistence.client.put_item = capturing_put
+ try:
+ persistence.save_open("payment", failure_count=5, opened_at=1000)
+ finally:
+ persistence.client.put_item = original_put
+
+ item = captured["Item"]
+ assert "expiration" in item, "open item must carry a DynamoDB TTL attribute"
+
+
+# --------------------------------------------------------------------------- serialization coverage
+
+
+def test_item_to_record_full_item(persistence):
+ """Cover _item_to_record with all fields present (lines 109-122)."""
+ item = {
+ "id": {"S": "payment"},
+ "state": {"S": "HALF_OPEN"},
+ "failure_count": {"N": "3"},
+ "opened_at": {"N": "1000"},
+ "half_open_owner": {"S": "env-x"},
+ "probe_lease_expiry": {"N": "2000"},
+ "expiration": {"N": "9999"},
+ }
+ record = persistence._item_to_record(item)
+ assert record.name == "payment"
+ assert record.state == CircuitState.HALF_OPEN
+ assert record.failure_count == 3
+ assert record.opened_at == 1000
+ assert record.half_open_owner == "env-x"
+ assert record.probe_lease_expiry == 2000
+ assert record.expiry_timestamp == 9999
+
+
+def test_item_to_record_minimal_item(persistence):
+ """Cover _item_to_record with optional fields absent."""
+ item = {
+ "id": {"S": "payment"},
+ "state": {"S": "CLOSED"},
+ }
+ record = persistence._item_to_record(item)
+ assert record.name == "payment"
+ assert record.state == CircuitState.CLOSED
+ assert record.failure_count == 0
+ assert record.opened_at is None
+ assert record.half_open_owner is None
+ assert record.probe_lease_expiry is None
+
+
+def test_record_to_item_full_record(persistence):
+ """Cover _record_to_item with all fields set (lines 124-139)."""
+ from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord
+
+ record = CircuitStateRecord(
+ name="payment",
+ state=CircuitState.HALF_OPEN,
+ failure_count=5,
+ opened_at=1000,
+ half_open_owner="env-a",
+ probe_lease_expiry=2000,
+ expiry_timestamp=9999,
+ )
+ item = persistence._record_to_item(record)
+ assert item["id"] == {"S": "payment"}
+ assert item["state"] == {"S": "HALF_OPEN"}
+ assert item["failure_count"] == {"N": "5"}
+ assert item["opened_at"] == {"N": "1000"}
+ assert item["half_open_owner"] == {"S": "env-a"}
+ assert item["probe_lease_expiry"] == {"N": "2000"}
+ assert item["expiration"] == {"N": "9999"}
+
+
+def test_record_to_item_minimal_record(persistence):
+ """Cover _record_to_item with optional fields as None (branch misses on lines 131-137)."""
+ from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord
+
+ record = CircuitStateRecord(name="payment", state=CircuitState.CLOSED)
+ item = persistence._record_to_item(record)
+ assert item == {
+ "id": {"S": "payment"},
+ "state": {"S": "CLOSED"},
+ "failure_count": {"N": "0"},
+ }
+ assert "opened_at" not in item
+ assert "half_open_owner" not in item
+ assert "probe_lease_expiry" not in item
+ assert "expiration" not in item
+
+
+def test_get_record_returns_deserialized_item(persistence):
+ """Cover _get_record success path (lines 141-153)."""
+ stubber = Stubber(persistence.client)
+ stubber.add_response(
+ "get_item",
+ {
+ "Item": {
+ "id": {"S": "payment"},
+ "state": {"S": "OPEN"},
+ "failure_count": {"N": "5"},
+ "opened_at": {"N": "1000"},
+ },
+ },
+ {"TableName": TABLE_NAME, "Key": {"id": {"S": "payment"}}, "ConsistentRead": False},
+ )
+ with stubber:
+ record = persistence._get_record("payment")
+ assert record.state == CircuitState.OPEN
+ assert record.failure_count == 5
+ assert record.opened_at == 1000
+
+
+def test_build_half_open_condition_without_expected_opened_at(persistence):
+ """Cover _build_half_open_condition when expected_opened_at is None (line 172 branch)."""
+ result = persistence._build_half_open_condition(expected_opened_at=None)
+ assert ":expected_opened_at" not in result["ConditionExpression"]
+ assert "#opened_at" not in result["ExpressionAttributeNames"]
+
+
+def test_build_half_open_condition_with_expected_opened_at(persistence):
+ """Cover _build_half_open_condition when expected_opened_at is set (lines 172-177)."""
+ result = persistence._build_half_open_condition(expected_opened_at=5000)
+ assert "#opened_at = :expected_opened_at" in result["ConditionExpression"]
+ assert result["ExpressionAttributeNames"]["#opened_at"] == "opened_at"
+ assert result["ExpressionAttributeValues"][":expected_opened_at"] == {"N": "5000"}
+
+
+# --------------------------------------------------------------------------- composite (single-table) key
+
+
+COMPOSITE_KEY = {"PK": {"S": "CIRCUIT_BREAKER"}, "SK": {"S": "payment"}}
+
+
+@pytest.fixture
+def composite_persistence():
+ client = boto3.client("dynamodb", config=Config(region_name="us-east-1"))
+ layer = CircuitBreakerDynamoDBPersistence(
+ table_name=TABLE_NAME,
+ boto3_client=client,
+ key_attr="PK",
+ sort_key_attr="SK",
+ static_pk_value="CIRCUIT_BREAKER",
+ )
+ layer.configure(CircuitBreakerConfig(local_cache_max_age=0), circuit_name="payment")
+ return layer
+
+
+def test_composite_get_state_reads_composite_key(composite_persistence):
+ stubber = Stubber(composite_persistence.client)
+ stubber.add_response(
+ "get_item",
+ {},
+ {"TableName": TABLE_NAME, "Key": COMPOSITE_KEY, "ConsistentRead": False},
+ )
+ with stubber:
+ record = composite_persistence.get_state("payment")
+ assert record.state == CircuitState.CLOSED
+
+
+def test_composite_save_open_writes_composite_key(composite_persistence):
+ captured, restore = _capture_put_item(composite_persistence)
+ try:
+ composite_persistence.save_open("payment", failure_count=5, opened_at=1000)
+ finally:
+ restore()
+
+ item = captured["Item"]
+ assert item["PK"] == {"S": "CIRCUIT_BREAKER"}
+ assert item["SK"] == {"S": "payment"}
+ assert "id" not in item
+ assert item["state"] == {"S": "OPEN"}
+
+
+def test_composite_try_acquire_half_open_writes_composite_key(composite_persistence):
+ captured, restore = _capture_put_item(composite_persistence)
+ try:
+ assert composite_persistence.try_acquire_half_open("payment", "env-a", 1000) is True
+ finally:
+ restore()
+
+ item = captured["Item"]
+ assert item["PK"] == {"S": "CIRCUIT_BREAKER"}
+ assert item["SK"] == {"S": "payment"}
+ assert item["state"] == {"S": "HALF_OPEN"}
+ # The conditional election is still emitted in composite mode (condition is key-independent).
+ assert "#state = :open AND attribute_not_exists(#half_open_owner)" in captured["ConditionExpression"]
+ assert "#probe_lease_expiry <= :now" in captured["ConditionExpression"]
+
+
+def test_composite_try_acquire_half_open_loses_on_conditional_failure(composite_persistence):
+ stubber = Stubber(composite_persistence.client)
+ stubber.add_client_error("put_item", service_error_code="ConditionalCheckFailedException")
+ with stubber:
+ assert composite_persistence.try_acquire_half_open("payment", "env-b", 1000) is False
+
+
+def test_composite_save_closed_updates_composite_key(composite_persistence):
+ captured = {}
+ original_update = composite_persistence.client.update_item
+
+ def capturing_update(**kwargs):
+ captured.update(kwargs)
+ return {}
+
+ composite_persistence.client.update_item = capturing_update
+ try:
+ composite_persistence.save_closed("payment")
+ finally:
+ composite_persistence.client.update_item = original_update
+
+ assert captured["Key"] == COMPOSITE_KEY
+
+
+def test_composite_item_to_record_reads_name_from_sort_key(composite_persistence):
+ item = {
+ "PK": {"S": "CIRCUIT_BREAKER"},
+ "SK": {"S": "payment"},
+ "state": {"S": "OPEN"},
+ "failure_count": {"N": "2"},
+ }
+ record = composite_persistence._item_to_record(item)
+ assert record.name == "payment"
+ assert record.state == CircuitState.OPEN
+
+
+def test_sort_key_equal_to_key_attr_raises():
+ client = boto3.client("dynamodb", config=Config(region_name="us-east-1"))
+ with pytest.raises(CircuitBreakerConfigError, match="cannot be the same"):
+ CircuitBreakerDynamoDBPersistence(
+ table_name=TABLE_NAME,
+ boto3_client=client,
+ key_attr="PK",
+ sort_key_attr="PK",
+ )
+
+
+def test_default_static_pk_value_namespaces_function_name(monkeypatch):
+ monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", "orders-fn")
+ client = boto3.client("dynamodb", config=Config(region_name="us-east-1"))
+ layer = CircuitBreakerDynamoDBPersistence(table_name=TABLE_NAME, boto3_client=client, sort_key_attr="SK")
+ assert layer.static_pk_value == "circuit_breaker#orders-fn"
+
+
+def test_static_pk_value_without_sort_key_attr_warns():
+ client = boto3.client("dynamodb", config=Config(region_name="us-east-1"))
+ with pytest.warns(PowertoolsUserWarning, match="static_pk_value is ignored unless sort_key_attr"):
+ CircuitBreakerDynamoDBPersistence(
+ table_name=TABLE_NAME,
+ boto3_client=client,
+ static_pk_value="CIRCUIT_BREAKER",
+ )
diff --git a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py
index 9c46fe24eb7..90e9e69790b 100644
--- a/tests/functional/event_handler/_pydantic/test_bedrock_agent.py
+++ b/tests/functional/event_handler/_pydantic/test_bedrock_agent.py
@@ -1,5 +1,6 @@
import json
-from typing import Any, Dict, Optional
+from functools import partial
+from typing import Any, Dict
import pytest
from typing_extensions import Annotated
@@ -191,7 +192,7 @@ def test_openapi_schema_for_pydanticv2(openapi30_schema):
# WHEN we have a simple handler
@app.get("/", description="Testing")
- def handler() -> Optional[Dict]:
+ def handler() -> Dict | None:
pass
# WHEN we get the schema
@@ -335,7 +336,7 @@ def test_bedrock_resolver_with_openapi_extensions():
# WHEN we have a simple handler with openapi extension
@app.get("/", description="Testing", openapi_extensions={"x-requireConfirmation": "ENABLED"})
- def handler() -> Optional[Dict]:
+ def handler() -> Dict | None:
pass
# WHEN we get the schema
@@ -383,3 +384,37 @@ def run_sql_query(query: Annotated[str, Query()]):
# THEN the parameter with commas should be correctly passed to the handler
body = json.loads(result["response"]["responseBody"]["application/json"]["body"])
assert body["result"] == "SELECT a.source_name, b.thing FROM table"
+
+
+def test_bedrock_agent_with_default_serializer_escapes_non_ascii():
+ # GIVEN a Bedrock Agent resolver using the default serializer
+ app = BedrockAgentResolver()
+
+ @app.get("/claims", description="Gets claims")
+ def claims() -> Dict[str, Any]:
+ return {"output": "잔액은 1,000원입니다 💰"}
+
+ # WHEN calling the event handler
+ result = app(load_event("bedrockAgentEvent.json"), {})
+
+ # THEN the body is valid JSON and non-ASCII characters are escaped (default json.dumps behavior)
+ body = result["response"]["responseBody"]["application/json"]["body"]
+ assert "\\uc794" in body # "잔" escaped
+ assert json.loads(body) == {"output": "잔액은 1,000원입니다 💰"}
+
+
+def test_bedrock_agent_with_custom_serializer_preserves_non_ascii():
+ # GIVEN a Bedrock Agent resolver initialized with a custom serializer that keeps non-ASCII characters
+ app = BedrockAgentResolver(serializer=partial(json.dumps, ensure_ascii=False))
+
+ @app.get("/claims", description="Gets claims")
+ def claims() -> Dict[str, Any]:
+ return {"output": "잔액은 1,000원입니다 💰"}
+
+ # WHEN calling the event handler
+ result = app(load_event("bedrockAgentEvent.json"), {})
+
+ # THEN the non-ASCII characters are preserved verbatim in the response body
+ body = result["response"]["responseBody"]["application/json"]["body"]
+ assert "잔액은 1,000원입니다 💰" in body
+ assert json.loads(body) == {"output": "잔액은 1,000원입니다 💰"}
diff --git a/tests/functional/event_handler/_pydantic/test_depends.py b/tests/functional/event_handler/_pydantic/test_depends.py
index 0cbc05b83c7..1a4be667377 100644
--- a/tests/functional/event_handler/_pydantic/test_depends.py
+++ b/tests/functional/event_handler/_pydantic/test_depends.py
@@ -214,3 +214,82 @@ def handler(name: str = "world", greeting: Annotated[str, Depends(get_greeting)]
result = app(event, {})
assert result["statusCode"] == 200
assert json.loads(result["body"]) == {"message": "hello, Lambda!"}
+
+
+class ArbitraryClient:
+ """Stand-in for an arbitrary non-Pydantic type such as a boto3 client."""
+
+ def __init__(self, name: str = "default"):
+ self.name = name
+
+
+def test_depends_with_arbitrary_return_type_and_validation():
+ """A dependency returning a non-Pydantic type must not crash under enable_validation (#8330)."""
+ app = APIGatewayHttpResolver(enable_validation=True)
+
+ def get_client() -> ArbitraryClient:
+ return ArbitraryClient(name="orders")
+
+ @app.get("/items")
+ def handler(client: Annotated[ArbitraryClient, Depends(get_client)]):
+ return {"client": client.name}
+
+ event = {**API_GW_V2_EVENT}
+ event["rawPath"] = "/items"
+ event["requestContext"] = {
+ **event["requestContext"],
+ "http": {"method": "GET", "path": "/items"},
+ }
+
+ result = app(event, {})
+ assert result["statusCode"] == 200
+ assert json.loads(result["body"]) == {"client": "orders"}
+
+
+def test_depends_nested_arbitrary_return_types_and_validation():
+ """A nested dependency chain of non-Pydantic return types must resolve (#8330).
+
+ Mirrors the reported chain: botocore session -> boto3 session -> dynamodb client.
+ """
+ app = APIGatewayHttpResolver(enable_validation=True)
+
+ def get_session() -> ArbitraryClient:
+ return ArbitraryClient(name="session")
+
+ def get_client(session: Annotated[ArbitraryClient, Depends(get_session)]) -> ArbitraryClient:
+ return ArbitraryClient(name=f"client-of-{session.name}")
+
+ @app.get("/items")
+ def handler(client: Annotated[ArbitraryClient, Depends(get_client)]):
+ return {"client": client.name}
+
+ event = {**API_GW_V2_EVENT}
+ event["rawPath"] = "/items"
+ event["requestContext"] = {
+ **event["requestContext"],
+ "http": {"method": "GET", "path": "/items"},
+ }
+
+ result = app(event, {})
+ assert result["statusCode"] == 200
+ assert json.loads(result["body"]) == {"client": "client-of-session"}
+
+
+def test_depends_arbitrary_return_type_excluded_from_openapi_schema():
+ """A non-Pydantic dependency return type must not appear in (or break) the OpenAPI schema (#8330)."""
+ app = APIGatewayHttpResolver(enable_validation=True)
+
+ def get_client() -> ArbitraryClient:
+ return ArbitraryClient()
+
+ @app.get("/items")
+ def handler(client: Annotated[ArbitraryClient, Depends(get_client)]):
+ return {"ok": True}
+
+ # Schema generation itself must not raise, and the dependency must not leak into params/body.
+ schema = app.get_openapi_schema()
+ get_op = schema.paths["/items"].get
+ param_names = [p.name for p in (get_op.parameters or [])]
+
+ assert "client" not in param_names
+ assert get_op.requestBody is None
diff --git a/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py b/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py
index 7cab58a1b70..e088527e359 100644
--- a/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py
+++ b/tests/functional/event_handler/_pydantic/test_http_resolver_pydantic.py
@@ -13,10 +13,6 @@
from aws_lambda_powertools.event_handler.http_resolver import MockLambdaContext
from aws_lambda_powertools.event_handler.openapi.params import Query
-# Suppress warning for all tests
-pytestmark = pytest.mark.filterwarnings("ignore:HttpResolverLocal is intended for local development")
-
-
# =============================================================================
# ASGI Test Helpers
# =============================================================================
diff --git a/tests/functional/event_handler/_pydantic/test_openapi_params.py b/tests/functional/event_handler/_pydantic/test_openapi_params.py
index 18087a228d1..b9426bf4da7 100644
--- a/tests/functional/event_handler/_pydantic/test_openapi_params.py
+++ b/tests/functional/event_handler/_pydantic/test_openapi_params.py
@@ -1,7 +1,7 @@
import json
from dataclasses import dataclass
from datetime import datetime
-from typing import List, Optional, Tuple
+from typing import List, Literal, Tuple
import pytest
from pydantic import BaseModel, Field
@@ -34,7 +34,7 @@ def test_openapi_pydantic_query_params():
class QueryParams(BaseModel):
limit: int = Field(default=10, ge=1, le=100, description="Number of items to return")
offset: int = Field(default=0, ge=0, description="Number of items to skip")
- search: Optional[str] = Field(default=None, description="Search term")
+ search: str | None = Field(default=None, description="Search term")
@app.get("/search")
def search_handler(params: Annotated[QueryParams, Query()]):
@@ -82,7 +82,7 @@ def test_openapi_pydantic_header_params():
class HeaderParams(BaseModel):
authorization: str = Field(description="Authorization token")
user_agent: str = Field(default="PowerTools/1.0", description="User agent")
- language: Optional[str] = Field(default=None, alias="accept-language", description="Language preference")
+ language: str | None = Field(default=None, alias="accept-language", description="Language preference")
@app.get("/protected")
def protected_handler(headers: Annotated[HeaderParams, Header()]):
@@ -915,6 +915,24 @@ def mixed_body_endpoint(user_data: Annotated[UserData, Body(media_type="applicat
assert "application/json" in request_body.content
+def test_openapi_excludes_content_type_header_parameter():
+ """Content-Type is described by requestBody content, not an OpenAPI header parameter."""
+ app = APIGatewayRestResolver(enable_validation=True)
+
+ @app.patch("/json-patch")
+ def json_patch(
+ operations: Annotated[list[dict], Body(media_type="application/json-patch+json")],
+ content_type: Annotated[Literal["application/json-patch+json"], Header(alias="Content-Type")],
+ ):
+ return {"status": "updated"}
+
+ schema = app.get_openapi_schema()
+ patch_op = schema.paths["/json-patch"].patch
+
+ assert "application/json-patch+json" in patch_op.requestBody.content
+ assert all(parameter.name.lower() != "content-type" for parameter in patch_op.parameters or [])
+
+
def test_openapi_form_parameter_edge_cases():
"""Test Form parameters with various edge cases."""
@@ -923,7 +941,7 @@ def test_openapi_form_parameter_edge_cases():
@app.post("/form-edge-cases")
def form_edge_cases(
required_field: Annotated[str, Form(description="Required field")],
- optional_field: Annotated[Optional[str], Form(description="Optional field")] = None,
+ optional_field: Annotated[str | None, Form(description="Optional field")] = None,
field_with_default: Annotated[str, Form(description="Field with default")] = "default_value",
):
return {"required": required_field, "optional": optional_field, "default": field_with_default}
@@ -986,7 +1004,7 @@ def get_items(params: Annotated[QueryParams, Query()]):
def test_openapi_pydantic_header_with_alias():
- """Test that Pydantic field aliases work correctly in Header parameters"""
+ """Test that Pydantic header aliases are emitted, except Content-Type."""
app = APIGatewayRestResolver()
class HeaderParams(BaseModel):
@@ -1003,7 +1021,7 @@ def test_handler(headers: Annotated[HeaderParams, Header()]):
# Check that aliases are used as parameter names
param_names = [param.name for param in get_operation.parameters]
- assert "content-type" in param_names
+ assert "content-type" not in param_names
assert "user-agent" in param_names
assert "content_type" not in param_names # Original field name should not be used
assert "user_agent" not in param_names
@@ -1016,7 +1034,7 @@ def test_openapi_pydantic_required_vs_optional():
class QueryParams(BaseModel):
required_field: str = Field(description="Required field")
optional_with_default: str = Field(default="default", description="Optional with default")
- optional_nullable: Optional[str] = Field(default=None, description="Optional nullable")
+ optional_nullable: str | None = Field(default=None, description="Optional nullable")
@app.get("/test")
def test_handler(params: Annotated[QueryParams, Query()]):
diff --git a/tests/functional/event_handler/_pydantic/test_openapi_responses.py b/tests/functional/event_handler/_pydantic/test_openapi_responses.py
index dccfae3e28d..c00b4e00462 100644
--- a/tests/functional/event_handler/_pydantic/test_openapi_responses.py
+++ b/tests/functional/event_handler/_pydantic/test_openapi_responses.py
@@ -1,5 +1,5 @@
from secrets import randbelow
-from typing import Optional, Union
+from typing import Union
from pydantic import BaseModel
@@ -325,7 +325,7 @@ def test_openapi_response_examples_preserved_with_model():
class UserResponse(BaseModel):
id: int
name: str
- email: Optional[str] = None
+ email: str | None = None
@app.get(
"/",
diff --git a/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py b/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py
index d25811d24ae..6f4b89e47cc 100644
--- a/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py
+++ b/tests/functional/event_handler/_pydantic/test_openapi_schema_pydantic_v2.py
@@ -1,6 +1,6 @@
import json
import warnings
-from typing import Literal, Optional
+from typing import Literal
import pytest
from pydantic import BaseModel, Field, computed_field
@@ -52,7 +52,7 @@ def test_openapi_3_1_complex_handler(openapi31_schema):
# GIVEN a complex pydantic model
class TodoAttributes(BaseModel):
userId: int
- id_: Optional[int] = Field(alias="id", default=None)
+ id_: int | None = Field(alias="id", default=None)
title: str
completed: bool
diff --git a/tests/functional/event_handler/_pydantic/test_openapi_serialization.py b/tests/functional/event_handler/_pydantic/test_openapi_serialization.py
index ef5c8ddd938..9bad2c61422 100644
--- a/tests/functional/event_handler/_pydantic/test_openapi_serialization.py
+++ b/tests/functional/event_handler/_pydantic/test_openapi_serialization.py
@@ -1,6 +1,6 @@
import json
from dataclasses import dataclass
-from typing import Dict, Optional, Set
+from typing import Dict, Set
import pytest
from pydantic import BaseModel
@@ -81,7 +81,7 @@ class Model(BaseModel):
age: int
@app.get("/valid_optional")
- def handler_valid_optional() -> Optional[Model]:
+ def handler_valid_optional() -> Model | None:
return Model(name="John", age=30)
# WHEN returning a valid model for an Optional type
diff --git a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py
index 0da092f8aea..ec14c14fa08 100644
--- a/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py
+++ b/tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py
@@ -5,7 +5,7 @@
from dataclasses import dataclass
from enum import Enum
from pathlib import PurePath
-from typing import Any, Dict, List, Literal, Optional, Tuple, Union
+from typing import Any, Dict, List, Literal, Tuple, Union
import pytest
from pydantic import (
@@ -30,7 +30,7 @@
VPCLatticeV2Resolver,
)
from aws_lambda_powertools.event_handler.openapi.exceptions import ResponseValidationError
-from aws_lambda_powertools.event_handler.openapi.params import Body, Form, Header, Query
+from aws_lambda_powertools.event_handler.openapi.params import Body, Form, Header, Path, Query
from tests.functional.utils import load_event
@@ -59,6 +59,27 @@ def handler(user_id: int):
assert any(text in result["body"] for text in ["type_error.integer", "int_parsing"])
+def test_content_type_header_validation_remains_enabled(gw_event):
+ """Content-Type header validation remains available when it is omitted from the OpenAPI schema."""
+ app = APIGatewayRestResolver(enable_validation=True)
+
+ @app.patch("/json-patch")
+ def json_patch(
+ operations: Annotated[list[dict], Body(media_type="application/json-patch+json")],
+ content_type: Annotated[Literal["application/json-patch+json"], Header(alias="Content-Type")],
+ ):
+ return {"status": "updated"}
+
+ gw_event["httpMethod"] = "PATCH"
+ gw_event["path"] = "/json-patch"
+ gw_event["headers"]["Content-Type"] = "application/json"
+ gw_event["body"] = '[{"op": "replace"}]'
+
+ result = app(gw_event, {})
+
+ assert result["statusCode"] == 422
+
+
def test_validate_pydantic_query_params(gw_event):
"""Test that Pydantic models in Query parameters are validated correctly"""
@@ -67,7 +88,7 @@ def test_validate_pydantic_query_params(gw_event):
class QueryParams(BaseModel):
limit: int = Field(default=10, ge=1, le=100, description="Number of items")
- search: Optional[str] = Field(default=None, description="Search term")
+ search: str | None = Field(default=None, description="Search term")
@app.get("/search")
def search_handler(params: Annotated[QueryParams, Query()]):
@@ -1756,7 +1777,7 @@ class Model(BaseModel):
age: int
@app.get("/none_allowed")
- def handler_none_allowed() -> Optional[Model]:
+ def handler_none_allowed() -> Model | None:
return None
# WHEN returning None for an Optional type
@@ -2654,6 +2675,77 @@ def create_action(action: Annotated[action_type, Body()]):
assert result["statusCode"] == 422
+def test_field_annotation_with_all_param_types(gw_event):
+ """A reusable Annotated type carrying a Pydantic Field works with every parameter location."""
+ app = APIGatewayRestResolver(enable_validation=True)
+
+ # Reusable annotated type, the same kind you'd use inside a model
+ str_field = Annotated[str, Field()]
+
+ @app.get("/header")
+ def get_header(h: Annotated[str_field, Header()]):
+ return {"value": h}
+
+ @app.get("/path/")
+ def get_path(p: Annotated[str_field, Path()]):
+ return {"value": p}
+
+ @app.get("/query")
+ def get_query(q: Annotated[str_field, Query()]):
+ return {"value": q}
+
+ @app.post("/body")
+ def post_body(b: Annotated[str_field, Body()]):
+ return {"value": b}
+
+ del gw_event["multiValueHeaders"]
+ del gw_event["multiValueQueryStringParameters"]
+
+ # Header
+ gw_event["path"] = "/header"
+ gw_event["httpMethod"] = "GET"
+ gw_event["headers"] = {"h": "test"}
+ assert app(gw_event, {})["statusCode"] == 200
+
+ # Path
+ gw_event["path"] = "/path/test"
+ gw_event["pathParameters"] = {"p": "test"}
+ assert app(gw_event, {})["statusCode"] == 200
+
+ # Query
+ gw_event["path"] = "/query"
+ gw_event["pathParameters"] = None
+ gw_event["queryStringParameters"] = {"q": "test"}
+ assert app(gw_event, {})["statusCode"] == 200
+
+ # Body
+ gw_event["path"] = "/body"
+ gw_event["httpMethod"] = "POST"
+ gw_event["headers"]["content-type"] = "application/json"
+ gw_event["body"] = '"test"'
+ assert app(gw_event, {})["statusCode"] == 200
+
+
+def test_field_constraints_apply_with_param_type(gw_event):
+ """Constraints declared on a Field are enforced when paired with a location marker."""
+ app = APIGatewayRestResolver(enable_validation=True)
+
+ @app.get("/items")
+ def get_items(quantity: Annotated[int, Field(gt=0), Query()]):
+ return {"quantity": quantity}
+
+ gw_event["path"] = "/items"
+ gw_event["httpMethod"] = "GET"
+
+ # Passes the gt=0 constraint
+ gw_event["queryStringParameters"] = {"quantity": "5"}
+ assert app(gw_event, {})["statusCode"] == 200
+
+ # Violates gt=0
+ gw_event["queryStringParameters"] = {"quantity": "-1"}
+ assert app(gw_event, {})["statusCode"] == 422
+
+
def test_validate_pydantic_query_params_with_config_dict_and_validators(gw_event):
"""Test that Pydantic models with ConfigDict, aliases, and validators work correctly"""
@@ -3031,15 +3123,15 @@ def _post_json(app, path, payload):
return result["statusCode"], json.loads(result["body"])
-# ---------- Optional[List[Model]] ----------
+# ---------- List[Model] | None ----------
def test_optional_list_body_with_list():
- """Optional[List[Model]] must preserve the full list."""
+ """List[Model] | None must preserve the full list."""
app = APIGatewayRestResolver(enable_validation=True)
@app.post("/items")
- def handler(items: Annotated[Optional[List[_Item]], Body()]) -> Dict[str, Any]:
+ def handler(items: Annotated[List[_Item] | None, Body()]) -> Dict[str, Any]:
assert isinstance(items, list)
return {"count": len(items)}
@@ -3049,11 +3141,11 @@ def handler(items: Annotated[Optional[List[_Item]], Body()]) -> Dict[str, Any]:
def test_optional_list_body_with_none():
- """Optional[List[Model]] must accept a null body gracefully."""
+ """List[Model] | None must accept a null body gracefully."""
app = APIGatewayRestResolver(enable_validation=True)
@app.post("/items")
- def handler(items: Annotated[Optional[List[_Item]], Body()] = None) -> Dict[str, Any]:
+ def handler(items: Annotated[List[_Item] | None, Body()] = None) -> Dict[str, Any]:
return {"received_none": items is None}
status, body = _post_json(app, "/items", None)
@@ -3061,15 +3153,15 @@ def handler(items: Annotated[Optional[List[_Item]], Body()] = None) -> Dict[str,
assert body["received_none"] is True
-# ---------- Optional[Union[Model, List[Model]]] ----------
+# ---------- Union[Model, List[Model]] | None ----------
def test_optional_union_model_or_list_with_list():
- """Optional[Union[Model, List[Model]]] — send list, get full list."""
+ """Union[Model, List[Model]] | None — send list, get full list."""
app = APIGatewayRestResolver(enable_validation=True)
@app.post("/items")
- def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Dict[str, Any]:
+ def handler(items: Annotated[Union[_Item, List[_Item]] | None, Body()]) -> Dict[str, Any]:
assert isinstance(items, list)
return {"count": len(items)}
@@ -3079,11 +3171,11 @@ def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Di
def test_optional_union_model_or_list_with_single():
- """Optional[Union[Model, List[Model]]] — send single obj, get single obj."""
+ """Union[Model, List[Model]] | None — send single obj, get single obj."""
app = APIGatewayRestResolver(enable_validation=True)
@app.post("/items")
- def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Dict[str, Any]:
+ def handler(items: Annotated[Union[_Item, List[_Item]] | None, Body()]) -> Dict[str, Any]:
assert not isinstance(items, list)
return {"name": items.name}
@@ -3093,11 +3185,11 @@ def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()]) -> Di
def test_optional_union_model_or_list_with_none():
- """Optional[Union[Model, List[Model]]] — send null, get None."""
+ """Union[Model, List[Model]] | None — send null, get None."""
app = APIGatewayRestResolver(enable_validation=True)
@app.post("/items")
- def handler(items: Annotated[Optional[Union[_Item, List[_Item]]], Body()] = None) -> Dict[str, Any]:
+ def handler(items: Annotated[Union[_Item, List[_Item]] | None, Body()] = None) -> Dict[str, Any]:
return {"is_none": items is None}
status, body = _post_json(app, "/items", None)
@@ -3196,11 +3288,11 @@ def handler(data: Annotated[Union[str, List[Dict[str, Any]]], Body()]) -> Dict[s
def test_optional_rootmodel_list_body():
- """Optional[RootModel[List[Model]]] — list must not be truncated."""
+ """RootModel[List[Model]] | None — list must not be truncated."""
app = APIGatewayRestResolver(enable_validation=True)
@app.post("/items")
- def handler(items: Annotated[Optional[_ItemCollection], Body()]) -> Dict[str, Any]:
+ def handler(items: Annotated[_ItemCollection | None, Body()]) -> Dict[str, Any]:
return {"count": len(items.root)}
status, body = _post_json(app, "/items", _THREE_ITEMS)
diff --git a/tests/functional/event_handler/required_dependencies/test_http_resolver.py b/tests/functional/event_handler/required_dependencies/test_http_resolver.py
index 40fb3d20c64..4665812e64a 100644
--- a/tests/functional/event_handler/required_dependencies/test_http_resolver.py
+++ b/tests/functional/event_handler/required_dependencies/test_http_resolver.py
@@ -1,4 +1,4 @@
-"""Tests for HttpResolverLocal - ASGI-compatible HTTP resolver for local development."""
+"""Tests for HttpResolverLocal - ASGI-compatible HTTP resolver."""
from __future__ import annotations
@@ -11,10 +11,6 @@
from aws_lambda_powertools.event_handler import HttpResolverLocal, Response
from aws_lambda_powertools.event_handler.http_resolver import MockLambdaContext
-# Suppress warning for all tests
-pytestmark = pytest.mark.filterwarnings("ignore:HttpResolverLocal is intended for local development")
-
-
# =============================================================================
# ASGI Test Helpers
# =============================================================================
@@ -1242,3 +1238,219 @@ def hello():
# THEN it returns 404 (method mismatch is treated as not found)
assert captured["status_code"] == 404
+
+
+# =============================================================================
+# CORS Tests (issue #8267)
+# =============================================================================
+
+
+@pytest.mark.asyncio
+async def test_cors_options_preflight_returns_204():
+ # GIVEN an app with CORSConfig and a POST route
+ from aws_lambda_powertools.event_handler.api_gateway import CORSConfig
+
+ app = HttpResolverLocal(cors=CORSConfig(allow_origin="*"))
+
+ @app.post("/items")
+ def create_item():
+ return {"ok": True}
+
+ # WHEN a browser sends a CORS preflight OPTIONS request
+ scope = {
+ "type": "http",
+ "method": "OPTIONS",
+ "path": "/items",
+ "query_string": b"",
+ "headers": [
+ (b"origin", b"http://localhost:3000"),
+ (b"access-control-request-method", b"POST"),
+ ],
+ }
+
+ receive = make_asgi_receive()
+ captured: dict[str, Any] = {"status_code": None, "headers": []}
+
+ async def send(message: dict[str, Any]) -> None:
+ await asyncio.sleep(0)
+ if message["type"] == "http.response.start":
+ captured["status_code"] = message["status"]
+ captured["headers"].extend(message.get("headers", []))
+
+ await app(scope, receive, send)
+
+ # THEN it returns 204 with CORS headers (not 500 or 404)
+ assert captured["status_code"] == 204
+
+ header_names = [name.lower() for name, _ in captured["headers"]]
+ assert b"access-control-allow-origin" in header_names
+ assert b"access-control-allow-methods" in header_names
+
+
+@pytest.mark.asyncio
+async def test_cors_options_preflight_with_exception_handler_does_not_return_500():
+ # GIVEN an app with CORSConfig and a generic exception handler that returns 500
+ import json
+
+ from aws_lambda_powertools.event_handler.api_gateway import CORSConfig
+
+ app = HttpResolverLocal(cors=CORSConfig(allow_origin="*"))
+
+ @app.post("/items")
+ def create_item():
+ return {"ok": True}
+
+ @app.exception_handler(Exception)
+ def handle_server_error(ex: Exception):
+ return Response(
+ status_code=500,
+ content_type="application/json",
+ body=json.dumps({"error": "internal"}),
+ )
+
+ # WHEN a browser sends a CORS preflight OPTIONS request
+ scope = {
+ "type": "http",
+ "method": "OPTIONS",
+ "path": "/items",
+ "query_string": b"",
+ "headers": [
+ (b"origin", b"http://localhost:3000"),
+ (b"access-control-request-method", b"POST"),
+ ],
+ }
+
+ receive = make_asgi_receive()
+ captured: dict[str, Any] = {"status_code": None, "headers": []}
+
+ async def send(message: dict[str, Any]) -> None:
+ await asyncio.sleep(0)
+ if message["type"] == "http.response.start":
+ captured["status_code"] = message["status"]
+ captured["headers"].extend(message.get("headers", []))
+
+ await app(scope, receive, send)
+
+ # THEN the OPTIONS request returns 204, not 500
+ assert captured["status_code"] == 204
+ header_names = [name.lower() for name, _ in captured["headers"]]
+ assert b"access-control-allow-origin" in header_names
+
+
+@pytest.mark.asyncio
+async def test_no_cors_options_returns_404():
+ # GIVEN an app WITHOUT CORSConfig
+ app = HttpResolverLocal()
+
+ @app.post("/items")
+ def create_item():
+ return {"ok": True}
+
+ # WHEN a browser sends an OPTIONS request (no CORS configured)
+ scope = {
+ "type": "http",
+ "method": "OPTIONS",
+ "path": "/items",
+ "query_string": b"",
+ "headers": [],
+ }
+
+ receive = make_asgi_receive()
+ send, captured = make_asgi_send()
+
+ await app(scope, receive, send)
+
+ # THEN it returns 404 (no CORS config, no special handling)
+ assert captured["status_code"] == 404
+
+
+@pytest.mark.asyncio
+async def test_cors_options_includes_allowed_methods_header():
+ # GIVEN an app with CORSConfig and multiple routes
+ from aws_lambda_powertools.event_handler.api_gateway import CORSConfig
+
+ app = HttpResolverLocal(cors=CORSConfig(allow_origin="https://example.com"))
+
+ @app.get("/resource")
+ def get_resource():
+ return {"method": "GET"}
+
+ @app.post("/resource")
+ def post_resource():
+ return {"method": "POST"}
+
+ # WHEN an OPTIONS preflight is sent
+ scope = {
+ "type": "http",
+ "method": "OPTIONS",
+ "path": "/resource",
+ "query_string": b"",
+ "headers": [
+ (b"origin", b"https://example.com"),
+ (b"access-control-request-method", b"GET"),
+ ],
+ }
+
+ receive = make_asgi_receive()
+ captured: dict[str, Any] = {"status_code": None, "headers": []}
+
+ async def send(message: dict[str, Any]) -> None:
+ await asyncio.sleep(0)
+ if message["type"] == "http.response.start":
+ captured["status_code"] = message["status"]
+ captured["headers"].extend(message.get("headers", []))
+
+ await app(scope, receive, send)
+
+ # THEN 204 is returned with Access-Control-Allow-Methods header
+ assert captured["status_code"] == 204
+ allow_methods_headers = [v for name, v in captured["headers"] if name.lower() == b"access-control-allow-methods"]
+ assert len(allow_methods_headers) == 1
+
+
+@pytest.mark.asyncio
+async def test_cors_disallowed_header_not_in_allow_headers():
+ # GIVEN an app with CORSConfig that only allows specific headers
+ from aws_lambda_powertools.event_handler.api_gateway import CORSConfig
+
+ app = HttpResolverLocal(cors=CORSConfig(allow_origin="*", allow_headers=["X-Custom-Allowed"]))
+
+ @app.post("/items")
+ def create_item():
+ return {"ok": True}
+
+ # WHEN a preflight requests an unlisted header
+ scope = {
+ "type": "http",
+ "method": "OPTIONS",
+ "path": "/items",
+ "query_string": b"",
+ "headers": [
+ (b"origin", b"http://localhost:3000"),
+ (b"access-control-request-method", b"POST"),
+ (b"access-control-request-headers", b"X-Not-Allowed"),
+ ],
+ }
+
+ receive = make_asgi_receive()
+ captured: dict[str, Any] = {"status_code": None, "headers": []}
+
+ async def send(message: dict[str, Any]) -> None:
+ await asyncio.sleep(0)
+ if message["type"] == "http.response.start":
+ captured["status_code"] = message["status"]
+ captured["headers"].extend(message.get("headers", []))
+
+ await app(scope, receive, send)
+
+ # THEN the server still returns 204 (browser enforces the rejection, not the server)
+ assert captured["status_code"] == 204
+
+ # AND the unlisted header is absent from Access-Control-Allow-Headers
+ allow_headers_value = next(
+ (v.decode() for name, v in captured["headers"] if name.lower() == b"access-control-allow-headers"),
+ "",
+ )
+ assert "X-Not-Allowed" not in allow_headers_value
+ # AND the explicitly allowed header IS present
+ assert "X-Custom-Allowed" in allow_headers_value
diff --git a/tests/functional/idempotency/_boto3/test_idempotency.py b/tests/functional/idempotency/_boto3/test_idempotency.py
index e5916dba0fa..56b317a9b5a 100644
--- a/tests/functional/idempotency/_boto3/test_idempotency.py
+++ b/tests/functional/idempotency/_boto3/test_idempotency.py
@@ -2,7 +2,7 @@
import dataclasses
import datetime
import warnings
-from typing import Any, Optional
+from typing import Any
from unittest.mock import MagicMock, Mock
import jmespath
@@ -1046,6 +1046,10 @@ def test_is_missing_idempotency_key():
assert BasePersistenceLayer.is_missing_idempotency_key((None, None))
# GIVEN a dict of Nones THEN is_missing_idempotency_key is True
assert BasePersistenceLayer.is_missing_idempotency_key({None: None})
+ # GIVEN a dict with all-None values THEN is_missing_idempotency_key is True
+ assert BasePersistenceLayer.is_missing_idempotency_key({"user": None, "order": None})
+ # GIVEN a dict with a non-None value THEN is_missing_idempotency_key is False
+ assert BasePersistenceLayer.is_missing_idempotency_key({"user": "abc"}) is False
# GIVEN True THEN is_missing_idempotency_key is False
assert BasePersistenceLayer.is_missing_idempotency_key(True) is False
@@ -1114,6 +1118,19 @@ def test_raise_on_no_idempotency_key(
assert "No data found to create a hashed idempotency_key" in str(excinfo.value)
+def test_raise_on_no_idempotency_key_for_dict_jmespath(persistence_store: DynamoDBPersistenceLayer):
+ # GIVEN a dict multi-select expression whose values are missing
+ idempotency_config = IdempotencyConfig(
+ event_key_jmespath="{user: headers.user_id, order: body.order_id}",
+ raise_on_no_idempotency_key=True,
+ )
+ persistence_store.configure(idempotency_config)
+
+ # WHEN extracting the idempotency key THEN raise IdempotencyKeyError
+ with pytest.raises(IdempotencyKeyError, match="No data found to create a hashed idempotency_key"):
+ persistence_store._get_hashed_idempotency_key({"headers": {}, "body": {}})
+
+
@pytest.mark.parametrize(
"idempotency_config",
[
@@ -2086,7 +2103,7 @@ class PaymentOutput:
config=config,
output_serializer=output_serializer,
)
- def collect_payment(payment: PaymentInput) -> Optional[PaymentOutput]:
+ def collect_payment(payment: PaymentInput) -> PaymentOutput | None:
return PaymentOutput(**dataclasses.asdict(payment))
# WHEN
diff --git a/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py b/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py
index f8e3debbc30..b5decebafbe 100644
--- a/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py
+++ b/tests/functional/idempotency/_pydantic/test_idempotency_with_pydantic.py
@@ -1,5 +1,3 @@
-from typing import Optional
-
import pytest
from pydantic import BaseModel
@@ -252,7 +250,7 @@ class PaymentOutput(BaseModel):
config=config,
output_serializer=output_serializer,
)
- def collect_payment(payment: PaymentInput) -> Optional[PaymentOutput]:
+ def collect_payment(payment: PaymentInput) -> PaymentOutput | None:
return PaymentOutput(**payment.dict())
# WHEN
diff --git a/tests/functional/idempotency/_redis/test_redis_layer.py b/tests/functional/idempotency/_redis/test_redis_layer.py
index 22c3b9a6d83..6adb97a64a4 100644
--- a/tests/functional/idempotency/_redis/test_redis_layer.py
+++ b/tests/functional/idempotency/_redis/test_redis_layer.py
@@ -3,6 +3,7 @@
import datetime
import json
import time as t
+from threading import Event, Lock as ThreadLock, Thread
from unittest import mock
import pytest
@@ -26,6 +27,7 @@
STATUS_CONSTANTS,
DataRecord,
)
+from aws_lambda_powertools.utilities.idempotency.persistence.cache import CachePersistenceLayer
from aws_lambda_powertools.utilities.idempotency.persistence.redis import (
RedisCachePersistenceLayer,
)
@@ -198,6 +200,16 @@ def valid_record():
)
+@pytest.fixture
+def in_progress_record_missing_expiry():
+ return DataRecord(
+ idempotency_key="test_orphan_key",
+ status=STATUS_CONSTANTS["INPROGRESS"],
+ expiry_timestamp=int(datetime.datetime.now().timestamp()) + 60,
+ in_progress_expiry_timestamp=None,
+ )
+
+
@mock.patch("aws_lambda_powertools.utilities.idempotency.persistence.redis.redis", MockRedis())
def test_redis_connection_standalone():
# when RedisCachePersistenceLayer is init with the following params
@@ -303,6 +315,73 @@ def test_redis_orphan_record_lock(orphan_record, valid_record):
)
+@mock.patch("aws_lambda_powertools.utilities.idempotency.persistence.redis.redis", MockRedis())
+def test_redis_in_progress_record_missing_expiry_is_not_treated_as_orphan(in_progress_record_missing_expiry):
+ layer = RedisCachePersistenceLayer(host="host")
+ layer._put_in_progress_record(in_progress_record_missing_expiry)
+
+ contender = DataRecord(
+ idempotency_key=in_progress_record_missing_expiry.idempotency_key,
+ status=STATUS_CONSTANTS["INPROGRESS"],
+ expiry_timestamp=in_progress_record_missing_expiry.expiry_timestamp + 60,
+ in_progress_expiry_timestamp=None,
+ )
+
+ with pytest.raises(IdempotencyItemAlreadyExistsError):
+ layer._put_in_progress_record(contender)
+
+ stored_record = layer._get_record(in_progress_record_missing_expiry.idempotency_key)
+ assert stored_record.status == STATUS_CONSTANTS["INPROGRESS"]
+ assert stored_record.expiry_timestamp == in_progress_record_missing_expiry.expiry_timestamp
+
+
+@pytest.mark.filterwarnings("ignore:Couldn't determine the remaining time left")
+def test_idempotent_function_blocks_concurrent_invocation_without_lambda_context():
+ layer = CachePersistenceLayer(client=MockRedis(host="localhost"))
+ first_invocation_started = Event()
+ release_first_invocation = Event()
+ execution_lock = ThreadLock()
+ execution_count = 0
+ first_result = []
+ first_errors = []
+
+ @idempotent_function(data_keyword_argument="record", persistence_store=layer)
+ def process(record):
+ nonlocal execution_count
+ with execution_lock:
+ execution_count += 1
+ current_execution = execution_count
+
+ if current_execution == 1:
+ first_invocation_started.set()
+ if not release_first_invocation.wait(timeout=5):
+ raise TimeoutError("Timed out waiting to release the first invocation")
+
+ return {"execution": current_execution}
+
+ def invoke_first():
+ try:
+ first_result.append(process(record={"id": "same"}))
+ except Exception as exc:
+ first_errors.append(exc)
+
+ first_invocation = Thread(target=invoke_first)
+ first_invocation.start()
+ assert first_invocation_started.wait(timeout=2)
+
+ try:
+ with pytest.raises(IdempotencyAlreadyInProgressError):
+ process(record={"id": "same"})
+ finally:
+ release_first_invocation.set()
+ first_invocation.join(timeout=5)
+
+ assert not first_invocation.is_alive()
+ assert first_errors == []
+ assert first_result == [{"execution": 1}]
+ assert execution_count == 1
+
+
@mock.patch("aws_lambda_powertools.utilities.idempotency.persistence.redis.redis", MockRedis())
def test_redis_error_in_progress(valid_record):
layer = RedisCachePersistenceLayer(host="host", mode="standalone")
diff --git a/tests/functional/idempotency/utils.py b/tests/functional/idempotency/utils.py
index 2e1ee4ab821..c6b3ee9b1a0 100644
--- a/tests/functional/idempotency/utils.py
+++ b/tests/functional/idempotency/utils.py
@@ -1,6 +1,6 @@
import hashlib
import json
-from typing import Any, Dict, Optional
+from typing import Any, Dict
from botocore import stub
from pytest import FixtureRequest
@@ -88,7 +88,7 @@ def build_idempotency_put_item_response_stub(
expiration: int,
status: str,
request: FixtureRequest,
- validation_data: Optional[Any],
+ validation_data: Any | None,
):
response = {
"Item": {
diff --git a/tests/functional/validator/_fastjsonschema/test_validator.py b/tests/functional/validator/_fastjsonschema/test_validator.py
index d29efd09cae..e14bc5e01c1 100644
--- a/tests/functional/validator/_fastjsonschema/test_validator.py
+++ b/tests/functional/validator/_fastjsonschema/test_validator.py
@@ -77,12 +77,13 @@ def test_validate_accept_schema_custom_format(
)
-@pytest.mark.parametrize("invalid_format", [None, False, {}, [], object])
+@pytest.mark.parametrize("invalid_format", [object, 123, 1.5, True])
def test_validate_invalid_custom_format(
eventbridge_schema_registry_cloudtrail_v2_s3,
eventbridge_cloudtrail_s3_head_object_event,
invalid_format,
):
+ # formats must be a mapping; anything we can't look a format name up in fails to compile
with pytest.raises(exceptions.InvalidSchemaFormatError):
validate(
event=eventbridge_cloudtrail_s3_head_object_event,
diff --git a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt
index 397c11ba436..c168cb36ead 100644
--- a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt
+++ b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1024/requirements.txt
@@ -1,3 +1,3 @@
requests>=2.32.0
aws-lambda-powertools[tracer]
-aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4
+aws-encryption-sdk>=4.0.5,<5.0.0
diff --git a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt
index 397c11ba436..c168cb36ead 100644
--- a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt
+++ b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_128/requirements.txt
@@ -1,3 +1,3 @@
requests>=2.32.0
aws-lambda-powertools[tracer]
-aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4
+aws-encryption-sdk>=4.0.5,<5.0.0
diff --git a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt
index 397c11ba436..c168cb36ead 100644
--- a/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt
+++ b/tests/performance/data_masking/load_test_data_masking/pt-load-test-stack/function_1769/requirements.txt
@@ -1,3 +1,3 @@
requests>=2.32.0
aws-lambda-powertools[tracer]
-aws-encryption-sdk>=3.3.1,!=4.0.0,!=4.0.1,!=4.0.2,!=4.0.3,!=4.0.4
+aws-encryption-sdk>=4.0.5,<5.0.0
diff --git a/tests/unit/circuit_breaker/__init__.py b/tests/unit/circuit_breaker/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/unit/circuit_breaker/test_config_and_states.py b/tests/unit/circuit_breaker/test_config_and_states.py
new file mode 100644
index 00000000000..03700dc91d3
--- /dev/null
+++ b/tests/unit/circuit_breaker/test_config_and_states.py
@@ -0,0 +1,138 @@
+from __future__ import annotations
+
+import dataclasses
+
+import pytest
+
+from aws_lambda_powertools.utilities.circuit_breaker.config import CircuitBreakerConfig
+from aws_lambda_powertools.utilities.circuit_breaker.exceptions import (
+ CircuitBreakerConfigError,
+ CircuitBreakerOpenError,
+)
+from aws_lambda_powertools.utilities.circuit_breaker.persistence.record import CircuitStateRecord
+from aws_lambda_powertools.utilities.circuit_breaker.states import CircuitInfo, CircuitState
+
+
+def test_circuit_state_serializes_to_plain_string():
+ assert str(CircuitState.OPEN) == "OPEN"
+ assert CircuitState.OPEN == "OPEN"
+
+
+def test_circuit_info_is_immutable():
+ info = CircuitInfo(name="payment", state=CircuitState.OPEN, failure_count=5, opened_at=123)
+ with pytest.raises(dataclasses.FrozenInstanceError):
+ info.name = "other" # type: ignore[misc]
+
+
+def test_config_defaults():
+ config = CircuitBreakerConfig()
+ assert config.failure_threshold == 5
+ assert config.recovery_timeout == 30
+ assert config.success_threshold == 3
+ assert config.local_cache_max_age == 5
+ assert config.handled_exceptions is None
+ assert config.ignored_exceptions is None
+
+
+def test_config_rejects_both_exception_lists():
+ with pytest.raises(CircuitBreakerConfigError, match="mutually exclusive"):
+ CircuitBreakerConfig(handled_exceptions=(TimeoutError,), ignored_exceptions=(ValueError,))
+
+
+@pytest.mark.parametrize("field", ["failure_threshold", "recovery_timeout", "success_threshold"])
+def test_config_rejects_non_positive_thresholds(field):
+ with pytest.raises(CircuitBreakerConfigError, match="positive integer"):
+ CircuitBreakerConfig(**{field: 0})
+
+
+def test_config_allows_zero_cache_age():
+ assert CircuitBreakerConfig(local_cache_max_age=0).local_cache_max_age == 0
+
+
+def test_config_rejects_negative_cache_age():
+ with pytest.raises(CircuitBreakerConfigError, match="non-negative"):
+ CircuitBreakerConfig(local_cache_max_age=-1)
+
+
+def test_counts_as_failure_default_any_exception():
+ config = CircuitBreakerConfig()
+ assert config.counts_as_failure(ValueError()) is True
+ assert config.counts_as_failure(TimeoutError()) is True
+
+
+def test_counts_as_failure_allowlist():
+ config = CircuitBreakerConfig(handled_exceptions=(TimeoutError, ConnectionError))
+ assert config.counts_as_failure(TimeoutError()) is True
+ assert config.counts_as_failure(ValueError()) is False
+
+
+def test_counts_as_failure_denylist():
+ config = CircuitBreakerConfig(ignored_exceptions=(ValueError,))
+ assert config.counts_as_failure(ValueError()) is False
+ assert config.counts_as_failure(KeyError()) is True
+
+
+def test_config_normalizes_handled_exceptions_list_to_tuple():
+ config = CircuitBreakerConfig(handled_exceptions=[TimeoutError, ConnectionError])
+ assert config.handled_exceptions == (TimeoutError, ConnectionError)
+ # The reported bug: a list must not break counts_as_failure when the circuit evaluates a failure.
+ assert config.counts_as_failure(TimeoutError()) is True
+ assert config.counts_as_failure(ValueError()) is False
+
+
+def test_config_normalizes_single_exception_type_to_tuple():
+ config = CircuitBreakerConfig(handled_exceptions=ValueError)
+ assert config.handled_exceptions == (ValueError,)
+ assert config.counts_as_failure(ValueError()) is True
+
+
+def test_config_normalizes_ignored_exceptions_list_to_tuple():
+ config = CircuitBreakerConfig(ignored_exceptions=[ValueError])
+ assert config.ignored_exceptions == (ValueError,)
+ assert config.counts_as_failure(ValueError()) is False
+ assert config.counts_as_failure(KeyError()) is True
+
+
+def test_config_normalizes_iterator_of_exceptions():
+ config = CircuitBreakerConfig(handled_exceptions=iter((TimeoutError, KeyError)))
+ assert config.handled_exceptions == (TimeoutError, KeyError)
+
+
+@pytest.mark.parametrize("field", ["handled_exceptions", "ignored_exceptions"])
+def test_config_rejects_non_exception_type_in_list(field):
+ with pytest.raises(CircuitBreakerConfigError, match="only exception types"):
+ CircuitBreakerConfig(**{field: ["not-an-exception"]})
+
+
+@pytest.mark.parametrize("field", ["handled_exceptions", "ignored_exceptions"])
+@pytest.mark.parametrize("value", [5, "ValueError"])
+def test_config_rejects_non_iterable_or_str_exceptions(field, value):
+ with pytest.raises(CircuitBreakerConfigError, match="iterable of exception types"):
+ CircuitBreakerConfig(**{field: value})
+
+
+@pytest.mark.parametrize("field", ["handled_exceptions", "ignored_exceptions"])
+def test_config_rejects_empty_exceptions(field):
+ with pytest.raises(CircuitBreakerConfigError, match="at least one exception type"):
+ CircuitBreakerConfig(**{field: []})
+
+
+def test_open_error_carries_circuit_info():
+ info = CircuitInfo(name="payment", state=CircuitState.OPEN, failure_count=5, opened_at=123)
+ error = CircuitBreakerOpenError("open", circuit=info)
+ assert error.circuit is info
+
+
+def test_record_to_circuit_info_strips_internal_fields():
+ record = CircuitStateRecord(
+ name="payment",
+ state=CircuitState.OPEN,
+ failure_count=5,
+ opened_at=123,
+ half_open_owner="env-abc",
+ expiry_timestamp=999,
+ )
+ info = record.to_circuit_info()
+ assert info == CircuitInfo(name="payment", state=CircuitState.OPEN, failure_count=5, opened_at=123)
+ assert not hasattr(info, "half_open_owner")
+ assert not hasattr(info, "expiry_timestamp")
diff --git a/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py b/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py
index e055c894604..2ff81a21bb8 100644
--- a/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py
+++ b/tests/unit/data_classes/required_dependencies/test_bedrock_agent_function_event.py
@@ -32,7 +32,7 @@ def test_bedrock_agent_function_event():
raw_parameters = raw_event["parameters"]
assert len(parameters) == len(raw_parameters)
- for param, raw_param in zip(parameters, raw_parameters):
+ for param, raw_param in zip(parameters, raw_parameters, strict=True):
assert param.name == raw_param["name"]
assert param.type == raw_param["type"]
assert param.value == raw_param["value"]
diff --git a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py
index 6dfc0c82485..e581cacae32 100644
--- a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py
+++ b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py
@@ -17,4 +17,4 @@ def test_event_bridge_event():
assert parsed_event.source == raw_event["source"]
assert parsed_event.detail_type == raw_event["detail-type"]
assert parsed_event.detail == raw_event["detail"]
- assert parsed_event.replay_name == "replay_archive"
+ assert parsed_event.replay_name is None
diff --git a/tests/unit/parser/_pydantic/schemas.py b/tests/unit/parser/_pydantic/schemas.py
index 0713924c486..2565d649ee9 100644
--- a/tests/unit/parser/_pydantic/schemas.py
+++ b/tests/unit/parser/_pydantic/schemas.py
@@ -1,4 +1,4 @@
-from typing import List, Optional
+from typing import List
from pydantic import BaseModel
@@ -21,8 +21,8 @@ class MyDynamoBusiness(BaseModel):
class MyDynamoScheme(DynamoDBStreamChangedRecordModel):
- NewImage: Optional[MyDynamoBusiness] = None
- OldImage: Optional[MyDynamoBusiness] = None
+ NewImage: MyDynamoBusiness | None = None
+ OldImage: MyDynamoBusiness | None = None
class MyDynamoDBStreamRecordModel(DynamoDBStreamRecordModel):
diff --git a/tests/unit/parser/_pydantic/test_dynamodb.py b/tests/unit/parser/_pydantic/test_dynamodb.py
index 13ee5610e6d..f21f6d717c3 100644
--- a/tests/unit/parser/_pydantic/test_dynamodb.py
+++ b/tests/unit/parser/_pydantic/test_dynamodb.py
@@ -1,3 +1,5 @@
+from typing import Any
+
import pytest
from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse
@@ -86,8 +88,26 @@ def test_validate_event_does_not_conform_with_model():
parse(event=raw_event, model=MyDynamoBusiness, envelope=envelopes.DynamoDBStreamEnvelope)
-def test_dynamo_db_stream_lambda_invocation_event():
+@pytest.mark.parametrize(
+ "response_context",
+ [
+ pytest.param(
+ {"statusCode": 200, "executedVersion": "$LATEST"},
+ id="without function error",
+ ),
+ pytest.param(
+ {"statusCode": 200, "executedVersion": "$LATEST", "functionError": None},
+ id="with null function error",
+ ),
+ pytest.param(
+ {"statusCode": 200, "executedVersion": "$LATEST", "functionError": "Unhandled"},
+ id="with function error",
+ ),
+ ],
+)
+def test_dynamo_db_stream_lambda_invocation_event(response_context: dict[str, Any]):
raw_event = load_event("dynamoStreamLambdaInvocationEvent.json")
+ raw_event["responseContext"] = response_context
parsed_event: DynamoDBStreamLambdaOnFailureDestinationModel = parse(
event=raw_event,
model=DynamoDBStreamLambdaOnFailureDestinationModel,
@@ -111,6 +131,8 @@ def test_dynamo_db_stream_lambda_invocation_event():
)
assert parsed_event.ddb_stream_batch_info.stream_arn == raw_event["DDBStreamBatchInfo"]["streamArn"]
assert parsed_event.request_context.model_dump(by_alias=True) == raw_event["requestContext"]
- assert parsed_event.response_context.model_dump(by_alias=True) == raw_event["responseContext"]
+ assert parsed_event.response_context.status_code == response_context["statusCode"]
+ assert parsed_event.response_context.executed_version == response_context["executedVersion"]
+ assert parsed_event.response_context.function_error == response_context.get("functionError")
assert parsed_event.timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") == raw_event["timestamp"]
assert parsed_event.version == raw_event["version"]
diff --git a/tests/unit/parser/_pydantic/test_eventbridge.py b/tests/unit/parser/_pydantic/test_eventbridge.py
index 585406e7095..86ebc5bc204 100644
--- a/tests/unit/parser/_pydantic/test_eventbridge.py
+++ b/tests/unit/parser/_pydantic/test_eventbridge.py
@@ -45,7 +45,7 @@ def test_handle_eventbridge_trigger_event_no_envelope():
assert parsed_event.resources == raw_event["resources"]
assert parsed_event.source == raw_event["source"]
assert parsed_event.detail_type == raw_event["detail-type"]
- assert parsed_event.replay_name == raw_event["replay-name"]
+ assert parsed_event.replay_name is None
def test_handle_invalid_event_with_eventbridge_envelope():