diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index bec0e43..850654f 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -23,4 +23,4 @@ assignees: '' #### Desktop (please complete the following information): - **OS**: [e.g. MacOS 10.15.7, Windows 10] - **Package Version** [e.g. 0.0.1 or commit ID] -- **Python Version** [e.g. python 3.9.16] +- **Python Version** [e.g. python 3.12.2] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a3a97f..2b71187 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,11 +2,11 @@ name: Build and Test on: pull_request: - branches: [ main ] + branches: [ main, release/* ] paths-ignore: - '**/_version.py' push: - branches: [ main ] + branches: [ main, release/* ] tags-ignore: - 'v*' paths-ignore: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3dbbf1f..4e8b3bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -142,4 +142,19 @@ jobs: name: python-package-distributions path: dist/ - name: Publish distribution to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 \ No newline at end of file + uses: pypa/gh-action-pypi-publish@release/v1 + + create-github-release: + name: Create GitHub Release + needs: [bump, publish-to-pypi] + if: ${{ github.event.inputs.dry-run == 'false' }} + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.bump.outputs.VERSION_TAG }} + name: ${{ needs.bump.outputs.VERSION_TAG }} + generate_release_notes: true diff --git a/Makefile b/Makefile index 53b2fd5..baec5ad 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ install-release: .uv ## Installs package dependencies uv sync --frozen --group release -rebuild-lockfile: .uv ## Rebuilds the lockfile +upgrade-lockfile: .uv ## Upgrade lockfile to latest compatible versions (uv lock --upgrade) uv lock --upgrade link-packages: ## Link local packages to virtualenv @@ -107,7 +107,7 @@ unlink-packages: ## Unlink local packages from virtualenv make install; \ fi -.PHONY: .uv install install-release install rebuild-lockfile link-packages unlink-packages +.PHONY: .uv install install-release install upgrade-lockfile link-packages unlink-packages ####################### ##@ Formatting Commands diff --git a/docs/developer/index.md b/docs/developer/index.md index cef2daf..e7b32c1 100644 --- a/docs/developer/index.md +++ b/docs/developer/index.md @@ -75,17 +75,14 @@ class MyCustomHandler(LambdaHandler): ### Handler with Request/Response Models ```python -from dataclasses import dataclass from aibs_informatics_aws_lambda.common.handler import LambdaHandler -from aibs_informatics_core.models import SchemaModel +from aibs_informatics_core.models.base import PydanticBaseModel -@dataclass -class MyRequest(SchemaModel): +class MyRequest(PydanticBaseModel): input_path: str output_path: str -@dataclass -class MyResponse(SchemaModel): +class MyResponse(PydanticBaseModel): status: str files_processed: int diff --git a/docs/index.md b/docs/index.md index 5e5d1fa..8671622 100644 --- a/docs/index.md +++ b/docs/index.md @@ -62,16 +62,13 @@ pip install aibs-informatics-aws-lambda ### Basic Usage ```python -from dataclasses import dataclass -from aibs_informatics_core.models.base import SchemaModel +from aibs_informatics_core.models.base import PydanticBaseModel from aibs_informatics_aws_lambda.common.handler import LambdaHandler -@dataclass -class MyRequest(SchemaModel): +class MyRequest(PydanticBaseModel): name: str -@dataclass -class MyResponse(SchemaModel): +class MyResponse(PydanticBaseModel): message: str class MyHandler(LambdaHandler[MyRequest, MyResponse]): diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md index bcc16c5..11f7dd3 100644 --- a/docs/user-guide/getting-started.md +++ b/docs/user-guide/getting-started.md @@ -23,16 +23,13 @@ uv add aibs-informatics-aws-lambda The `LambdaHandler` class provides a base class for creating strongly typed lambda functions with features like serialization/deserialization, logging, and metrics. ```python -from dataclasses import dataclass -from aibs_informatics_core.models.base import SchemaModel +from aibs_informatics_core.models.base import PydanticBaseModel from aibs_informatics_aws_lambda.common.handler import LambdaHandler -@dataclass -class MyRequest(SchemaModel): +class MyRequest(PydanticBaseModel): name: str -@dataclass -class MyResponse(SchemaModel): +class MyResponse(PydanticBaseModel): message: str class MyHandler(LambdaHandler[MyRequest, MyResponse]): @@ -49,15 +46,13 @@ For API Gateway integrations, use `ApiLambdaHandler`: ```python from dataclasses import dataclass -from aibs_informatics_core.models.base import SchemaModel +from aibs_informatics_core.models.base import PydanticBaseModel from aibs_informatics_aws_lambda.common.api.handler import ApiLambdaHandler -@dataclass -class UserRequest(SchemaModel): +class UserRequest(PydanticBaseModel): user_id: str -@dataclass -class UserResponse(SchemaModel): +class UserResponse(PydanticBaseModel): name: str email: str diff --git a/pyproject.toml b/pyproject.toml index 4b7efe2..829d9fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,13 +13,13 @@ authors = [{ name = "AIBS Informatics Group", email = "marmot@alleninstitute.onm maintainers = [{ name = "AIBS Informatics Group", email = "marmot@alleninstitute.onmicrosoft.com"}] description = "Utility library for building validated and typed AWS Lambda functions" readme = { file = "README.md", content-type = "text/markdown" } -requires-python = ">=3.9" +requires-python = ">=3.11" dynamic = [ "version", ] dependencies = [ - "aibs-informatics-aws-utils>=0.0.12,<1", - "aibs-informatics-core>=0.2.6,<1", + "aibs-informatics-aws-utils~=1.0", + "aibs-informatics-core>=1.0.3,<2", "aws-lambda-powertools ~= 2.35", "pydantic >= 2.0.3, < 3", "aws-lambda-typing", diff --git a/src/aibs_informatics_aws_lambda/common/api/handler.py b/src/aibs_informatics_aws_lambda/common/api/handler.py index cc9359d..07736fd 100644 --- a/src/aibs_informatics_aws_lambda/common/api/handler.py +++ b/src/aibs_informatics_aws_lambda/common/api/handler.py @@ -9,9 +9,10 @@ ] import logging +from collections.abc import Callable from dataclasses import dataclass, field from datetime import datetime -from typing import Any, Callable, Dict, Generic, Optional, TypeVar, Union, cast +from typing import Any, Generic, Optional, TypeVar, Union, cast from aibs_informatics_core.models.api.http_parameters import HTTPParameters from aibs_informatics_core.models.api.route import ApiRoute @@ -78,7 +79,7 @@ def handle(self, request: MyRequest) -> MyResponse: ``` """ - _current_event: Optional[BaseProxyEvent] = field(default=None, repr=False) + _current_event: BaseProxyEvent | None = field(default=None, repr=False) def __post_init__(self): super().__post_init__() @@ -153,8 +154,8 @@ def add_to_router( cls, router: BaseRouter, *args, - logger: Optional[Logger] = None, - metrics: Optional[Union[EphemeralMetrics, Metrics]] = None, + logger: Logger | None = None, + metrics: EphemeralMetrics | Metrics | None = None, **kwargs, ) -> Callable: """Register this handler with an API Gateway router. @@ -216,7 +217,7 @@ def gateway_handler(logger=logger, metrics=metrics, **route_parameters) -> Any: @classmethod def _parse_event( - cls, event: BaseProxyEvent, route_parameters: Dict[str, Any], logger: logging.Logger + cls, event: BaseProxyEvent, route_parameters: dict[str, Any], logger: logging.Logger ) -> API_REQUEST: """Parse an API Gateway event into a request object. diff --git a/src/aibs_informatics_aws_lambda/common/api/resolver.py b/src/aibs_informatics_aws_lambda/common/api/resolver.py index 89b4f01..2e8d056 100644 --- a/src/aibs_informatics_aws_lambda/common/api/resolver.py +++ b/src/aibs_informatics_aws_lambda/common/api/resolver.py @@ -8,11 +8,12 @@ "ApiResolverBuilder", ] import json +from collections.abc import Callable from dataclasses import dataclass, field from datetime import datetime from traceback import format_exc from types import ModuleType -from typing import Callable, ClassVar, List, Optional, Union +from typing import ClassVar, Union from aibs_informatics_core.collections import PostInitMixin from aibs_informatics_core.utils.json import JSON, JSONObject @@ -205,8 +206,8 @@ def get_lambda_handler(self, *args, **kwargs) -> LambdaHandlerType: def add_handlers( self, target_module: ModuleType, - router: Optional[BaseRouter] = None, - prefix: Optional[str] = None, + router: BaseRouter | None = None, + prefix: str | None = None, ): """Dynamically add all API Lambda handlers from a module. @@ -239,8 +240,8 @@ def add_handlers( def add_handlers_to_router( router: BaseRouter, target_module: ModuleType, - metrics: Optional[Union[EphemeralMetrics, Metrics]] = None, - logger: Optional[Logger] = None, + metrics: EphemeralMetrics | Metrics | None = None, + logger: Logger | None = None, ): """Add all API handlers from a module to a router. @@ -261,7 +262,7 @@ def add_handlers_to_router( api_handler_class.add_to_router(router, logger=logger, metrics=metrics) -def get_target_handler_classes(target_module: ModuleType) -> List[ApiLambdaHandler]: +def get_target_handler_classes(target_module: ModuleType) -> list[ApiLambdaHandler]: """Get all ApiLambdaHandler subclasses in a module. Recursively loads all modules from the target package and returns @@ -287,7 +288,7 @@ def get_target_handler_classes(target_module: ModuleType) -> List[ApiLambdaHandl *list(loaded_modules.keys()), ] - target_api_handler_classes: List[ApiLambdaHandler] = [ + target_api_handler_classes: list[ApiLambdaHandler] = [ api_handler_class for api_handler_class in get_all_subclasses(ApiLambdaHandler, True) # type: ignore[type-abstract] if (getattr(api_handler_class, "__module__") in target_module_paths) diff --git a/src/aibs_informatics_aws_lambda/common/handler.py b/src/aibs_informatics_aws_lambda/common/handler.py index 092e9bf..755944b 100644 --- a/src/aibs_informatics_aws_lambda/common/handler.py +++ b/src/aibs_informatics_aws_lambda/common/handler.py @@ -1,11 +1,12 @@ import json import logging +from collections.abc import Callable from dataclasses import dataclass -from typing import Callable, Generic, Literal, Optional, TypeVar, Union, cast +from typing import Generic, Literal, Optional, TypeAlias, TypeVar, cast from aibs_informatics_aws_utils.s3 import download_to_json_object, upload_json from aibs_informatics_core.executors.base import BaseExecutor -from aibs_informatics_core.models.aws.s3 import S3URI +from aibs_informatics_core.models.aws.s3 import S3Path from aibs_informatics_core.models.base import ModelProtocol from aibs_informatics_core.utils.json import JSON from aws_lambda_powertools.utilities.batch import ( @@ -24,8 +25,9 @@ from aibs_informatics_aws_lambda.common.logging import LoggingMixins from aibs_informatics_aws_lambda.common.metrics import MetricsMixins -LambdaEvent = Union[JSON] # type: ignore # https://github.com/python/mypy/issues/7866 +LambdaEvent: TypeAlias = JSON LambdaHandlerType = Callable[[LambdaEvent, LambdaContext], Optional[JSON]] + logger = logging.getLogger(__name__) REQUEST = TypeVar("REQUEST", bound=ModelProtocol) @@ -58,12 +60,10 @@ class LambdaHandler( Example: ```python - @dataclass - class MyRequest(SchemaModel): + class MyRequest(PydanticBaseModel): name: str - @dataclass - class MyResponse(SchemaModel): + class MyResponse(PydanticBaseModel): message: str class MyHandler(LambdaHandler[MyRequest, MyResponse]): @@ -79,11 +79,11 @@ def __post_init__(self): super().__post_init__() @classmethod - def load_input__remote(cls, remote_path: S3URI) -> JSON: + def load_input__remote(cls, remote_path: S3Path) -> JSON: """Load input data from a remote S3 location. Args: - remote_path (S3URI): The S3 URI to download the input from. + remote_path (S3Path): The S3 URI to download the input from. Returns: The JSON content from the S3 object. @@ -91,12 +91,12 @@ def load_input__remote(cls, remote_path: S3URI) -> JSON: return download_to_json_object(remote_path) @classmethod - def write_output__remote(cls, output: JSON, remote_path: S3URI) -> None: + def write_output__remote(cls, output: JSON, remote_path: S3Path) -> None: """Write output data to a remote S3 location. Args: output (JSON): The JSON content to upload. - remote_path (S3URI): The S3 URI to upload the output to. + remote_path (S3Path): The S3 URI to upload the output to. """ return upload_json(output, remote_path) @@ -132,7 +132,7 @@ def get_handler(cls, *args, **kwargs) -> LambdaHandlerType: logger = cls.get_logger(service=cls.service_name(), add_to_root=False) @logger.inject_lambda_context(log_event=True) - def handler(event: LambdaEvent, context: LambdaContext) -> Optional[JSON]: + def handler(event: LambdaEvent, context: LambdaContext) -> JSON | None: lambda_handler = cls(*args, **kwargs) # type: ignore[call-arg] logger.info(f"Instantiated {lambda_handler}.") lambda_handler.log = logger @@ -155,6 +155,7 @@ def handler(event: LambdaEvent, context: LambdaContext) -> Optional[JSON]: return None + handler._handler_class = cls # type: ignore[attr-defined] return handler @classmethod @@ -229,7 +230,7 @@ def get_sqs_batch_handler( logger = cls.get_logger(cls.service_name()) # Create a record handler for each record in batch. - def record_handler(record: SQSRecord) -> Optional[JSON]: + def record_handler(record: SQSRecord) -> JSON | None: if not cls.should_process_sqs_record(record): logger.info(f"SQS record {record} elected not to be processed.") return None @@ -315,7 +316,7 @@ def get_dynamodb_stream_handler(cls, *args, **kwargs) -> LambdaHandlerType: logger = cls.get_logger(cls.service_name()) # Create a record handler for each record in batch. - def record_handler(record: DynamoDBRecord) -> Optional[JSON]: + def record_handler(record: DynamoDBRecord) -> JSON | None: if not cls.should_process_dynamodb_record(record): logger.info(f"DynamoDB record {record} will not be processed.") return None diff --git a/src/aibs_informatics_aws_lambda/common/logging.py b/src/aibs_informatics_aws_lambda/common/logging.py index 6f2e24f..181b459 100644 --- a/src/aibs_informatics_aws_lambda/common/logging.py +++ b/src/aibs_informatics_aws_lambda/common/logging.py @@ -5,7 +5,6 @@ """ import logging -from typing import Optional, Union from aibs_informatics_core.utils.logging import get_all_handlers from aws_lambda_powertools.logging import Logger @@ -73,7 +72,7 @@ def logger(self, value: Logger): self._logger = value @classmethod - def get_logger(cls, service: Optional[str] = None, add_to_root: bool = False) -> Logger: + def get_logger(cls, service: str | None = None, add_to_root: bool = False) -> Logger: """Create a new Logger instance. Args: @@ -95,7 +94,7 @@ def add_logger_to_root(self): def get_service_logger( - service: Optional[str] = None, child: bool = False, add_to_root: bool = False + service: str | None = None, child: bool = False, add_to_root: bool = False ) -> Logger: """Create a service logger with optional root logger integration. @@ -114,7 +113,7 @@ def get_service_logger( def add_handler_to_logger( - source_logger: Logger, target_logger: Union[str, logging.Logger, None] = None + source_logger: Logger, target_logger: str | logging.Logger | None = None ): """Add a source logger's handler to a target logger. diff --git a/src/aibs_informatics_aws_lambda/common/metrics.py b/src/aibs_informatics_aws_lambda/common/metrics.py index fbb1b76..b107ff8 100644 --- a/src/aibs_informatics_aws_lambda/common/metrics.py +++ b/src/aibs_informatics_aws_lambda/common/metrics.py @@ -5,7 +5,6 @@ """ from datetime import datetime -from typing import Optional, Union from aws_lambda_powertools.metrics import EphemeralMetrics, Metrics, MetricUnit @@ -17,10 +16,10 @@ def add_duration_metric( - start: Optional[datetime] = None, - end: Optional[datetime] = None, + start: datetime | None = None, + end: datetime | None = None, name: str = "", - metrics: Optional[Union[EphemeralMetrics, Metrics]] = None, + metrics: EphemeralMetrics | Metrics | None = None, ): """Add a duration metric to the metrics collector. @@ -44,7 +43,7 @@ def add_duration_metric( ) -def add_success_metric(name: str = "", metrics: Optional[Union[EphemeralMetrics, Metrics]] = None): +def add_success_metric(name: str = "", metrics: EphemeralMetrics | Metrics | None = None): """Record a successful operation metric. Adds metrics indicating success (1) and failure (0) counts. @@ -60,7 +59,7 @@ def add_success_metric(name: str = "", metrics: Optional[Union[EphemeralMetrics, metrics.add_metric(name=f"{name}Failure", unit=MetricUnit.Count, value=0) -def add_failure_metric(name: str = "", metrics: Optional[Union[EphemeralMetrics, Metrics]] = None): +def add_failure_metric(name: str = "", metrics: EphemeralMetrics | Metrics | None = None): """Record a failed operation metric. Adds metrics indicating success (0) and failure (1) counts. @@ -93,7 +92,7 @@ def add_count_metric(self, name: str, value: float): self.add_metric(name=name, unit=MetricUnit.Count, value=value) def add_duration_metric( - self, start: Optional[datetime] = None, end: Optional[datetime] = None, name: str = "" + self, start: datetime | None = None, end: datetime | None = None, name: str = "" ): """Add a duration metric. @@ -154,8 +153,8 @@ def metrics(self, value: EnhancedMetrics): @classmethod def get_metrics( cls, - service: Optional[str] = None, - namespace: Optional[str] = None, + service: str | None = None, + namespace: str | None = None, **additional_dimensions: str, ) -> EnhancedMetrics: """Create a new EnhancedMetrics instance. diff --git a/src/aibs_informatics_aws_lambda/common/models.py b/src/aibs_informatics_aws_lambda/common/models.py index f1687da..32afef2 100644 --- a/src/aibs_informatics_aws_lambda/common/models.py +++ b/src/aibs_informatics_aws_lambda/common/models.py @@ -5,9 +5,8 @@ import inspect from dataclasses import dataclass, field -from typing import cast +from typing import Annotated, cast -import marshmallow as mm from aibs_informatics_aws_utils.constants.lambda_ import ( AWS_LAMBDA_FUNCTION_ARN_KEY, AWS_LAMBDA_FUNCTION_MEMORY_SIZE_KEY, @@ -19,12 +18,13 @@ DEFAULT_AWS_LAMBDA_FUNCTION_NAME, ) from aibs_informatics_aws_utils.core import get_account_id, get_region -from aibs_informatics_core.models.base import DictField, SchemaModel, custom_field +from aibs_informatics_core.models.base import PydanticBaseModel from aibs_informatics_core.utils.modules import as_module_type, get_qualified_name from aibs_informatics_core.utils.os_operations import get_env_var from aws_lambda_powertools.utilities.typing import LambdaContext from aws_lambda_powertools.utilities.typing.lambda_client_context import LambdaClientContext from aws_lambda_powertools.utilities.typing.lambda_cognito_identity import LambdaCognitoIdentity +from pydantic import BeforeValidator, PlainSerializer from aibs_informatics_aws_lambda.common.handler import ( LambdaEvent, @@ -50,8 +50,9 @@ class DefaultLambdaContext(LambdaContext): """ _function_name: str = field( - default_factory=lambda: get_env_var(AWS_LAMBDA_FUNCTION_NAME_KEY) - or DEFAULT_AWS_LAMBDA_FUNCTION_NAME + default_factory=lambda: ( + get_env_var(AWS_LAMBDA_FUNCTION_NAME_KEY) or DEFAULT_AWS_LAMBDA_FUNCTION_NAME + ) ) _function_version: str = field( default_factory=lambda: get_env_var(AWS_LAMBDA_FUNCTION_VERSION_KEY, default_value="1.0") @@ -90,16 +91,41 @@ def __post_init__(self): def serialize_handler(handler: LambdaHandlerType) -> str: """Serialize a Lambda handler to its qualified name. + For closures (e.g., from ``LambdaHandler.get_handler()``), the function's + ``__qualname__`` points to the closure definition site rather than the + module-level variable that holds it. This searches ``sys.modules`` for a + global variable that references the exact handler object, so that + constructor arguments passed to ``get_handler()`` are preserved on + round-trip. + Args: handler (LambdaHandlerType): The Lambda handler function or class. Returns: The fully qualified module path of the handler. """ + # For closures, try to find a module-level variable referencing this handler + if "" in getattr(handler, "__qualname__", ""): + import sys + + for module_name, module in sys.modules.items(): + if module is None: + continue + try: + module_dict = vars(module) + except TypeError: + continue + for attr_name, attr_value in module_dict.items(): + if attr_value is handler: + return f"{module_name}.{attr_name}" + # Fall back to the originating class if the variable wasn't found + handler_class = getattr(handler, "_handler_class", None) + if handler_class is not None: + return get_qualified_name(handler_class) return get_qualified_name(handler) -def deserialize_handler(handler: str) -> LambdaHandlerType: +def deserialize_handler(handler: str | LambdaHandlerType) -> LambdaHandlerType: """Deserialize a handler from its qualified name. Loads a handler from its fully qualified module path. Supports both @@ -120,6 +146,13 @@ def deserialize_handler(handler: str) -> LambdaHandlerType: response = handler(event, context) ``` """ + if not isinstance(handler, str): + if not callable(handler): + raise ValueError( + f"Invalid handler type: expected a callable or fully qualified handler path " + f"string, got {type(handler).__name__}." + ) + return cast(LambdaHandlerType, handler) handler_components = handler.split(".") handler_module = as_module_type(".".join(handler_components[:-1])) @@ -138,8 +171,7 @@ def deserialize_handler(handler: str) -> LambdaHandlerType: ) -@dataclass -class LambdaHandlerRequest(SchemaModel): +class LambdaHandlerRequest(PydanticBaseModel): """Request model for dynamic Lambda handler invocation. Contains the handler reference and event payload for routing @@ -150,9 +182,9 @@ class LambdaHandlerRequest(SchemaModel): event: The event payload to pass to the handler. """ - handler: LambdaHandlerType = custom_field( - mm_field=mm.fields.Function( - lambda obj: serialize_handler(obj.handler), deserialize_handler - ) - ) - event: LambdaEvent = custom_field(mm_field=DictField()) + handler: Annotated[ + LambdaHandlerType, + BeforeValidator(deserialize_handler), + PlainSerializer(lambda handler: serialize_handler(handler)), + ] + event: LambdaEvent diff --git a/src/aibs_informatics_aws_lambda/handlers/batch/create.py b/src/aibs_informatics_aws_lambda/handlers/batch/create.py index 1f3abaa..4df6769 100644 --- a/src/aibs_informatics_aws_lambda/handlers/batch/create.py +++ b/src/aibs_informatics_aws_lambda/handlers/batch/create.py @@ -6,7 +6,7 @@ import re from dataclasses import dataclass -from typing import ClassVar, Optional +from typing import ClassVar from aibs_informatics_aws_utils.batch import ( BatchJobBuilder, @@ -64,7 +64,7 @@ def repo_name(self) -> str: return self.get_match_groups()[1] @property - def tag(self) -> Optional[str]: + def tag(self) -> str | None: """Get the image tag if specified. Returns: @@ -73,7 +73,7 @@ def tag(self) -> Optional[str]: return self.get_match_groups()[2] @property - def sha256(self) -> Optional[str]: + def sha256(self) -> str | None: """Get the SHA256 digest if specified. Returns: diff --git a/src/aibs_informatics_aws_lambda/handlers/batch/model.py b/src/aibs_informatics_aws_lambda/handlers/batch/model.py index a1a7c60..cb05dfb 100644 --- a/src/aibs_informatics_aws_lambda/handlers/batch/model.py +++ b/src/aibs_informatics_aws_lambda/handlers/batch/model.py @@ -4,17 +4,13 @@ managing AWS Batch job definitions and submissions. """ -from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any from aibs_informatics_core.models.aws.batch import ResourceRequirements from aibs_informatics_core.models.base import ( - DictField, - ListField, - SchemaModel, - UnionField, - custom_field, + PydanticBaseModel, ) +from pydantic import Field if TYPE_CHECKING: # pragma: no cover from mypy_boto3_batch.type_defs import ( @@ -30,8 +26,7 @@ VolumeTypeDef = dict -@dataclass -class CreateDefinitionAndPrepareArgsRequest(SchemaModel): +class CreateDefinitionAndPrepareArgsRequest(PydanticBaseModel): """Request for creating a batch job definition and preparing submission args. Attributes: @@ -50,33 +45,24 @@ class CreateDefinitionAndPrepareArgsRequest(SchemaModel): privileged: Whether to run in privileged mode. """ - image: str = custom_field() - job_definition_name: str = custom_field() - job_queue_name: str = custom_field() - job_role_arn: Optional[str] = custom_field(default=None) - job_name: Optional[str] = custom_field(default=None) - command: List[str] = custom_field(default_factory=list) - environment: Dict[str, str] = custom_field(default_factory=dict) - job_definition_tags: Dict[str, str] = custom_field(default_factory=dict) - resource_requirements: Union[List[ResourceRequirementTypeDef], ResourceRequirements] = ( - custom_field( - default_factory=list, - mm_field=UnionField( - [ - (list, ListField(DictField)), - (ResourceRequirements, ResourceRequirements.as_mm_field()), - ] - ), - ) + image: str + job_definition_name: str + job_queue_name: str + job_role_arn: str | None = None + job_name: str | None = None + command: list[str] = Field(default_factory=list) + environment: dict[str, str] = Field(default_factory=dict) + job_definition_tags: dict[str, str] = Field(default_factory=dict) + resource_requirements: list[ResourceRequirementTypeDef] | ResourceRequirements = Field( + default_factory=list, ) - mount_points: List[MountPointTypeDef] = custom_field(default_factory=list) - volumes: List[VolumeTypeDef] = custom_field(default_factory=list) - retry_strategy: Optional[RetryStrategyTypeDef] = custom_field(default=None) - privileged: bool = custom_field(default=False) + mount_points: list[MountPointTypeDef] = Field(default_factory=list) + volumes: list[VolumeTypeDef] = Field(default_factory=list) + retry_strategy: RetryStrategyTypeDef | None = None + privileged: bool = Field(default=False) -@dataclass -class CreateDefinitionAndPrepareArgsResponse(SchemaModel): +class CreateDefinitionAndPrepareArgsResponse(PydanticBaseModel): """Response from creating a batch job definition. Contains the prepared arguments for submitting the batch job. @@ -89,8 +75,8 @@ class CreateDefinitionAndPrepareArgsResponse(SchemaModel): container_overrides: Container override settings. """ - job_name: str = custom_field() - job_definition_arn: Optional[str] = custom_field() - job_queue_arn: str = custom_field() - parameters: Dict[str, Any] = custom_field() - container_overrides: Dict[str, Any] = custom_field() + job_name: str + job_definition_arn: str | None + job_queue_arn: str + parameters: dict[str, Any] + container_overrides: dict[str, Any] diff --git a/src/aibs_informatics_aws_lambda/handlers/data_sync/file_system.py b/src/aibs_informatics_aws_lambda/handlers/data_sync/file_system.py index 63b1e01..cf12659 100644 --- a/src/aibs_informatics_aws_lambda/handlers/data_sync/file_system.py +++ b/src/aibs_informatics_aws_lambda/handlers/data_sync/file_system.py @@ -8,12 +8,12 @@ import logging from datetime import timedelta from pathlib import Path -from typing import List, TypeVar +from typing import TypeVar from aibs_informatics_aws_utils.data_sync.file_system import BaseFileSystem, Node, get_file_system from aibs_informatics_aws_utils.efs import detect_mount_points, get_local_path from aibs_informatics_core.models.aws.efs import EFSPath -from aibs_informatics_core.models.aws.s3 import S3URI +from aibs_informatics_core.models.aws.s3 import S3Path from aibs_informatics_core.utils.file_operations import ( get_path_size_bytes, remove_path, @@ -81,7 +81,7 @@ def handle(self, request: ListDataPathsRequest) -> ListDataPathsResponse: Response containing the list of matching paths. """ root = get_file_system(request.path) - paths: List[DataPath] = sorted([n.path for n in root.node.list_nodes()]) + paths: list[DataPath] = sorted([n.path for n in root.node.list_nodes()]) if request.include_patterns or request.exclude_patterns: new_paths = [] @@ -123,9 +123,9 @@ def handle(self, request: OutdatedDataPathScannerRequest) -> OutdatedDataPathSca """ fs = get_file_system(request.path) - stale_nodes: List[Node] = [] + stale_nodes: list[Node] = [] days_since_last_accessed = timedelta(days=request.days_since_last_accessed) - unvisited_nodes: List[Node] = [fs.node] + unvisited_nodes: list[Node] = [fs.node] self.logger.info( f"Checking for nodes older than {request.days_since_last_accessed} days. " @@ -151,7 +151,7 @@ def handle(self, request: OutdatedDataPathScannerRequest) -> OutdatedDataPathSca # many files and allows us to maintain a minimum desired EFS throughput performance. # For more details see: https://docs.aws.amazon.com/efs/latest/ug/performance.html current_efs_size_bytes = fs.node.size_bytes - paths_to_delete: List[str] = [] + paths_to_delete: list[str] = [] # Sort so newest nodes are first, nodes are considered starting from the list end (oldest) nodes_to_delete = sorted(stale_nodes, key=lambda n: n.last_modified, reverse=True) @@ -187,12 +187,12 @@ def handle(self, request: RemoveDataPathsRequest) -> RemoveDataPathsResponse: size_bytes_removed = 0 paths_removed = [] for path in request.paths: - if isinstance(path, S3URI): - # # TODO: add support for S3URI when more guardrails are in place + if isinstance(path, S3Path): + # # TODO: add support for S3Path when more guardrails are in place # path_stats = get_s3_path_stats(path) # delete_s3_path(path) # size_bytes_removed += path_stats.size_bytes - self.logger.warning(f"Skipping S3URI path deletion ({path}). Not supported yet.") + self.logger.warning(f"Skipping S3Path path deletion ({path}). Not supported yet.") else: if isinstance(path, EFSPath): self.logger.info(f"Converting EFSPath ({path}) to local path") @@ -209,4 +209,6 @@ def handle(self, request: RemoveDataPathsRequest) -> RemoveDataPathsResponse: paths_removed.append(path) except FileNotFoundError as e: self.logger.warning(f"File at {path} does not exist anymore. Reason: {e}") - return RemoveDataPathsResponse(size_bytes_removed, paths_removed) + return RemoveDataPathsResponse( + size_bytes_removed=size_bytes_removed, paths_removed=paths_removed + ) diff --git a/src/aibs_informatics_aws_lambda/handlers/data_sync/model.py b/src/aibs_informatics_aws_lambda/handlers/data_sync/model.py index b0a6057..bbe7a2d 100644 --- a/src/aibs_informatics_aws_lambda/handlers/data_sync/model.py +++ b/src/aibs_informatics_aws_lambda/handlers/data_sync/model.py @@ -5,47 +5,27 @@ """ import re -from dataclasses import dataclass from datetime import datetime from functools import cached_property from pathlib import Path from re import Pattern -from typing import Dict, List, Optional, Union +from typing import TypeAlias from aibs_informatics_aws_utils.data_sync.file_system import PathStats from aibs_informatics_core.models.aws.efs import EFSPath from aibs_informatics_core.models.aws.s3 import S3Path from aibs_informatics_core.models.base import ( - CustomAwareDateTime, - DictField, - FloatField, - IntegerField, - ListField, - PathField, - SchemaModel, - StringField, - UnionField, - custom_field, + PydanticBaseModel, ) from aibs_informatics_core.utils.time import get_current_time +from pydantic import Field -DataPath = Union[S3Path, EFSPath, Path, str] +# Order matters for this union - S3Path and EFSPath have custom validation logic that would +# allow them to be parsed from a string +DataPath: TypeAlias = S3Path | EFSPath | Path | str -def DataPathField(*args, **kwargs): - return UnionField( - [ - (S3Path, S3Path.as_mm_field()), - ((EFSPath, str), EFSPath.as_mm_field()), - ((Path, str), PathField()), - ], - *args, - **kwargs, - ) - - -@dataclass -class WithDataPath(SchemaModel): +class WithDataPath(PydanticBaseModel): """Base class for models that contain a data path. Provides convenience properties for accessing the path as different types. @@ -54,10 +34,10 @@ class WithDataPath(SchemaModel): path: The data path (S3, EFS, or local). """ - path: DataPath = custom_field(mm_field=DataPathField()) + path: DataPath = Field(union_mode="left_to_right") @property - def efs_path(self) -> Optional[EFSPath]: + def efs_path(self) -> EFSPath | None: """Get the path as an EFS path if applicable. Returns: @@ -68,8 +48,8 @@ def efs_path(self) -> Optional[EFSPath]: return None @property - def s3_uri(self) -> Optional[S3Path]: - """Get the path as an S3 URI if applicable. + def s3_path(self) -> S3Path | None: + """Get the path as an S3 path if applicable. Returns: The S3 path or None if not an S3 path. @@ -79,7 +59,7 @@ def s3_uri(self) -> Optional[S3Path]: return None @property - def local_path(self) -> Optional[Path]: + def local_path(self) -> Path | None: """Get the path as a local path if applicable. Returns: @@ -90,7 +70,6 @@ def local_path(self) -> Optional[Path]: return None -@dataclass class ListDataPathsRequest(WithDataPath): """Request for listing files under a data path. @@ -104,54 +83,45 @@ class ListDataPathsRequest(WithDataPath): Exclude patterns take precedence over include patterns. """ - include: Optional[Union[str, List[str]]] = custom_field( - default=None, - mm_field=UnionField([(str, StringField()), (list, ListField(StringField()))]), - ) - exclude: Optional[Union[str, List[str]]] = custom_field( - default=None, - mm_field=UnionField([(str, StringField()), (list, ListField(StringField()))]), - ) + include: str | list[str] | None = None + exclude: str | list[str] | None = None @cached_property - def include_patterns(self) -> Optional[List[Pattern]]: + def include_patterns(self) -> list[Pattern] | None: return self._get_patterns(self.include) @cached_property - def exclude_patterns(self) -> Optional[List[Pattern]]: + def exclude_patterns(self) -> list[Pattern] | None: return self._get_patterns(self.exclude) @staticmethod - def _get_patterns(value: Optional[Union[str, List[str]]]) -> Optional[List[Pattern]]: + def _get_patterns(value: str | list[str] | None) -> list[Pattern] | None: if not value: return None return [re.compile(p) for p in ([value] if isinstance(value, str) else value)] -@dataclass -class ListDataPathsResponse(SchemaModel): +class ListDataPathsResponse(PydanticBaseModel): """Response containing listed data paths. Attributes: paths: List of data paths found. """ - paths: List[DataPath] = custom_field(default_factory=list, mm_field=ListField(DataPathField())) + paths: list[DataPath] = Field(default_factory=list) -@dataclass -class RemoveDataPathsRequest(SchemaModel): +class RemoveDataPathsRequest(PydanticBaseModel): """Request for removing data paths. Attributes: paths: List of data paths to remove. """ - paths: List[DataPath] = custom_field(default_factory=list, mm_field=ListField(DataPathField())) + paths: list[DataPath] = Field(default_factory=list) -@dataclass -class RemoveDataPathsResponse(SchemaModel): +class RemoveDataPathsResponse(PydanticBaseModel): """Response from removing data paths. Attributes: @@ -159,13 +129,10 @@ class RemoveDataPathsResponse(SchemaModel): paths_removed: List of paths that were removed. """ - size_bytes_removed: int = custom_field() - paths_removed: List[DataPath] = custom_field( - default_factory=list, mm_field=ListField(DataPathField()) - ) + size_bytes_removed: int + paths_removed: list[DataPath] = Field(default_factory=list) -@dataclass class OutdatedDataPathScannerRequest(WithDataPath): """Request for scanning outdated data paths. @@ -180,27 +147,23 @@ class OutdatedDataPathScannerRequest(WithDataPath): current_time: Reference time for calculating age. """ - days_since_last_accessed: float = custom_field(default=0, mm_field=FloatField()) - max_depth: Optional[int] = custom_field(default=None, mm_field=IntegerField()) - min_depth: Optional[int] = custom_field(default=None, mm_field=IntegerField()) - min_size_bytes_allowed: int = custom_field(default=0, mm_field=IntegerField()) - current_time: datetime = custom_field( - default_factory=get_current_time, mm_field=CustomAwareDateTime() - ) + days_since_last_accessed: float = 0.0 + max_depth: int | None = None + min_depth: int | None = None + min_size_bytes_allowed: int = 0 + current_time: datetime = Field(default_factory=get_current_time) -@dataclass -class OutdatedDataPathScannerResponse(SchemaModel): +class OutdatedDataPathScannerResponse(PydanticBaseModel): """Response containing outdated data paths. Attributes: paths: List of paths identified as outdated. """ - paths: List[DataPath] = custom_field(default_factory=list, mm_field=ListField(DataPathField())) + paths: list[DataPath] = Field(default_factory=list) -@dataclass class GetDataPathStatsRequest(WithDataPath): """Request for getting statistics about a data path. @@ -211,7 +174,6 @@ class GetDataPathStatsRequest(WithDataPath): pass -@dataclass class GetDataPathStatsResponse(WithDataPath): """Response containing data path statistics. @@ -221,7 +183,5 @@ class GetDataPathStatsResponse(WithDataPath): children: Statistics for child paths keyed by name. """ - path_stats: PathStats = custom_field(mm_field=PathStats.as_mm_field()) - children: Dict[str, PathStats] = custom_field( - mm_field=DictField(keys=StringField(), values=PathStats.as_mm_field()) - ) + path_stats: PathStats + children: dict[str, PathStats] = Field(default_factory=dict) diff --git a/src/aibs_informatics_aws_lambda/handlers/data_sync/operations.py b/src/aibs_informatics_aws_lambda/handlers/data_sync/operations.py index 72264b7..55898f2 100644 --- a/src/aibs_informatics_aws_lambda/handlers/data_sync/operations.py +++ b/src/aibs_informatics_aws_lambda/handlers/data_sync/operations.py @@ -6,7 +6,7 @@ import json from pathlib import Path -from typing import List, Optional, Union, cast +from typing import cast from aibs_informatics_aws_utils.data_sync import ( DataSyncOperations, @@ -15,7 +15,7 @@ S3FileSystem, ) from aibs_informatics_aws_utils.s3 import SCRATCH_EXTRA_ARGS, download_to_json, upload_json -from aibs_informatics_core.models.aws.s3 import S3URI, S3Key +from aibs_informatics_core.models.aws.s3 import S3Key, S3Path from aibs_informatics_core.models.data_sync import ( BatchDataSyncRequest, BatchDataSyncResponse, @@ -40,9 +40,9 @@ def get_s3_scratch_key( - filename: Optional[str] = None, - content: Optional[JSON] = None, - unique_id: Optional[UniqueID] = None, + filename: str | None = None, + content: JSON | None = None, + unique_id: UniqueID | None = None, ) -> S3Key: """Generates a scratch file s3 key @@ -91,7 +91,7 @@ def handle(self, request: GetJSONFromFileRequest) -> GetJSONFromFileResponse: path = request.path self.logger.info(f"Fetching content from {path}") - if isinstance(path, S3URI): + if isinstance(path, S3Path): self.logger.info("Downloading from S3") content = download_to_json(s3_path=path) else: @@ -110,7 +110,7 @@ class PutJSONToFileHandler(LambdaHandler[PutJSONToFileRequest, PutJSONToFileResp If no path is provided, generates a scratch S3 path. """ - def handle(self, request: PutJSONToFileRequest) -> Optional[PutJSONToFileResponse]: + def handle(self, request: PutJSONToFileRequest) -> PutJSONToFileResponse | None: """Write JSON content to the specified path. Args: @@ -131,7 +131,7 @@ def handle(self, request: PutJSONToFileRequest) -> Optional[PutJSONToFileRespons "No path provided and Could not infer bucket " f"name from {DEFAULT_BUCKET_NAME_ENV_VAR} environment variable" ) - path = S3URI.build( + path = S3Path.build( bucket_name=bucket_name, key=get_s3_scratch_key( content=content, @@ -141,7 +141,7 @@ def handle(self, request: PutJSONToFileRequest) -> Optional[PutJSONToFileRespons self.logger.info(f"Writing content to {path}") self.logger.info(f"Content to write: {content}") - if isinstance(path, S3URI): + if isinstance(path, S3Path): self.logger.info("Uploading to S3") upload_json(content, s3_path=path, extra_args=SCRATCH_EXTRA_ARGS) else: @@ -190,14 +190,14 @@ def handle(self, request: BatchDataSyncRequest) -> BatchDataSyncResponse: Raises: Exception: If a sync fails and allow_partial_failure is False. """ - self.logger.info(f"Received {len(request.requests)} requests to transfer") - if isinstance(request.requests, S3URI): + if isinstance(request.requests, S3Path): self.logger.info(f"Request is stored at {request.requests}... fetching content.") _ = download_to_json(request.requests) assert isinstance(_, list) batch_requests = [DataSyncRequest.from_dict(__) for __ in _] else: batch_requests = request.requests + self.logger.info(f"Received {len(batch_requests)} requests to transfer") batch_result = BatchDataSyncResult() response = BatchDataSyncResponse(result=batch_result, failed_requests=[]) @@ -259,8 +259,8 @@ def handle(self, request: PrepareBatchDataSyncRequest) -> PrepareBatchDataSyncRe Response containing prepared batch requests. """ self.logger.info("Preparing S3 Batch Sync Requests") - root: Union[S3FileSystem, LocalFileSystem] - if isinstance(request.source_path, S3URI): + root: S3FileSystem | LocalFileSystem + if isinstance(request.source_path, S3Path): root = S3FileSystem.from_path(request.source_path) else: root = LocalFileSystem.from_path(request.source_path) @@ -273,12 +273,12 @@ def handle(self, request: PrepareBatchDataSyncRequest) -> PrepareBatchDataSyncRe self.logger.info(f"Partitioning batch size bytes limit: {batch_size_bytes_limit}") nodes = root.partition(size_bytes_limit=batch_size_bytes_limit) - batch_data_sync_requests: List[BatchDataSyncRequest] = [] + batch_data_sync_requests: list[BatchDataSyncRequest] = [] node_batches = self.build_node_batches(nodes, batch_size_bytes_limit) self.logger.info(f"Batched {len(nodes)} nodes into {len(node_batches)} batches") for node_batch in node_batches: - data_sync_requests: List[DataSyncRequest] = [] + data_sync_requests: list[DataSyncRequest] = [] for node in sorted(node_batch): data_sync_requests.append( DataSyncRequest( @@ -316,20 +316,18 @@ def handle(self, request: PrepareBatchDataSyncRequest) -> PrepareBatchDataSyncRe return PrepareBatchDataSyncResponse(requests=batch_data_sync_requests) @classmethod - def build_source_path( - cls, request: PrepareBatchDataSyncRequest, node: Node - ) -> Union[S3URI, Path]: - if isinstance(request.source_path, S3URI): - return S3URI.build(bucket_name=request.source_path.bucket, key=node.path) + def build_source_path(cls, request: PrepareBatchDataSyncRequest, node: Node) -> S3Path | Path: + if isinstance(request.source_path, S3Path): + return S3Path.build(bucket_name=request.source_path.bucket, key=node.path) else: return Path(node.path) @classmethod def build_destination_path( cls, request: PrepareBatchDataSyncRequest, node: Node - ) -> Union[S3URI, Path]: + ) -> S3Path | Path: source_path = request.source_path - source_prefix = source_path.key if isinstance(source_path, S3URI) else f"{source_path}" + source_prefix = source_path.key if isinstance(source_path, S3Path) else f"{source_path}" relative_path = removeprefix(node.path, prefix=source_prefix).lstrip("/") # NOTE: This is because Path instances omit the file separator. @@ -337,8 +335,8 @@ def build_destination_path( # We should figure out a cleaner solution but this will have to do. if node.has_children(): relative_path += "/" - if isinstance(request.destination_path, S3URI): - return S3URI.build( + if isinstance(request.destination_path, S3Path): + return S3Path.build( bucket_name=request.destination_path.bucket, key=request.destination_path.key + relative_path, ) @@ -347,8 +345,8 @@ def build_destination_path( @classmethod def build_node_batches( - cls, nodes: List[Node], batch_size_bytes_limit: int - ) -> List[List[Node]]: + cls, nodes: list[Node], batch_size_bytes_limit: int + ) -> list[list[Node]]: """Batch nodes based on threshold This is a version of the classic "Bin Packing" problem. @@ -375,7 +373,7 @@ def build_node_batches( # Step 2: Group nodes in order to maximize the data synced per request # (bin packing problem) - node_batches: List[List[Node]] = [] + node_batches: list[list[Node]] = [] # (Optimize) Convert all nodes that are larger than the threshold into single requests. while unbatched_nodes and unbatched_nodes[0].size_bytes > batch_size_bytes_limit: diff --git a/src/aibs_informatics_aws_lambda/handlers/demand/context_manager.py b/src/aibs_informatics_aws_lambda/handlers/demand/context_manager.py index a9764ce..35d5f9f 100644 --- a/src/aibs_informatics_aws_lambda/handlers/demand/context_manager.py +++ b/src/aibs_informatics_aws_lambda/handlers/demand/context_manager.py @@ -11,7 +11,7 @@ from copy import deepcopy from dataclasses import dataclass, field from pathlib import Path -from typing import TYPE_CHECKING, Dict, List, Optional, Union +from typing import TYPE_CHECKING from aibs_informatics_aws_utils.batch import ( BatchJobBuilder, @@ -34,7 +34,7 @@ from aibs_informatics_aws_utils.efs.paths import get_efs_path from aibs_informatics_core.env import EnvBase from aibs_informatics_core.models.aws.efs import EFSPath -from aibs_informatics_core.models.aws.s3 import S3URI +from aibs_informatics_core.models.aws.s3 import S3Path from aibs_informatics_core.models.data_sync import PrepareBatchDataSyncRequest from aibs_informatics_core.models.demand_execution import DemandExecution from aibs_informatics_core.models.demand_execution.resolvables import Resolvable, Uploadable @@ -127,7 +127,7 @@ def mount_path(self) -> Path: return self.mount_point_config.mount_point @classmethod - def build(cls, access_point: str, mount_path: Union[Path, str], read_only: bool = False): + def build(cls, access_point: str, mount_path: Path | str, read_only: bool = False): """Build a BatchEFSConfiguration from an access point. Args: @@ -180,7 +180,7 @@ class DemandExecutionContextManager: demand_execution: DemandExecution scratch_vol_configuration: BatchEFSConfiguration shared_vol_configuration: BatchEFSConfiguration - tmp_vol_configuration: Optional[BatchEFSConfiguration] = None + tmp_vol_configuration: BatchEFSConfiguration | None = None configuration: ContextManagerConfiguration = field(default_factory=ContextManagerConfiguration) env_base: EnvBase = field(default_factory=EnvBase.from_env) @@ -280,7 +280,7 @@ def efs_shared_path(self) -> EFSPath: return get_efs_path(self.container_shared_path, mount_points=self.efs_mount_points) @property - def efs_mount_points(self) -> List[MountPointConfiguration]: + def efs_mount_points(self) -> list[MountPointConfiguration]: """Returns a list of mount points for the EFS volumes used by the aws batch job Returns: @@ -329,7 +329,7 @@ def batch_job_queue_name(self) -> str: return get_batch_job_queue_name(self.demand_execution) @property - def pre_execution_data_sync_requests(self) -> List[PrepareBatchDataSyncRequest]: + def pre_execution_data_sync_requests(self) -> list[PrepareBatchDataSyncRequest]: """Generate data sync requests for pre-execution input staging. Creates requests to sync input data from S3 to EFS before @@ -350,7 +350,7 @@ def pre_execution_data_sync_requests(self) -> List[PrepareBatchDataSyncRequest]: temporary_request_payload_path = temporary_request_payload_root / f"input_{i}/" requests.append( PrepareBatchDataSyncRequest( - source_path=S3URI(param.remote_value), + source_path=S3Path(param.remote_value), destination_path=get_efs_path( local_path=Path(param.value), raise_if_unresolved=True, @@ -370,7 +370,7 @@ def pre_execution_data_sync_requests(self) -> List[PrepareBatchDataSyncRequest]: return requests @property - def post_execution_data_sync_requests(self) -> List[PrepareBatchDataSyncRequest]: + def post_execution_data_sync_requests(self) -> list[PrepareBatchDataSyncRequest]: """Generate data sync requests for post-execution output upload. Creates requests to sync output data from EFS to S3 after @@ -392,7 +392,7 @@ def post_execution_data_sync_requests(self) -> List[PrepareBatchDataSyncRequest] requests.append( PrepareBatchDataSyncRequest( source_path=get_efs_path(Path(param.value), True, self.efs_mount_points), - destination_path=S3URI(param.remote_value), + destination_path=S3Path(param.remote_value), retain_source_data=False, require_lock=False, batch_size_bytes_limit=75 * BYTES_PER_GIBIBYTE, # 75 GiB max @@ -407,7 +407,7 @@ def post_execution_data_sync_requests(self) -> List[PrepareBatchDataSyncRequest] return requests @property - def post_execution_remove_data_paths_requests(self) -> List[RemoveDataPathsRequest]: + def post_execution_remove_data_paths_requests(self) -> list[RemoveDataPathsRequest]: """Generates remove data paths requests for post-execution data sync Returns: @@ -429,7 +429,7 @@ def from_demand_execution( cls, demand_execution: DemandExecution, env_base: EnvBase, - configuration: Optional[ContextManagerConfiguration] = None, + configuration: ContextManagerConfiguration | None = None, ): """Create a context manager from a demand execution. @@ -580,7 +580,7 @@ def get_batch_efs_configuration( env_base: EnvBase, container_path: str, access_point_name: str, - file_system_name: Optional[str] = None, + file_system_name: str | None = None, read_only: bool = False, ) -> BatchEFSConfiguration: """Get a BatchEFSConfiguration by resolving resources from AWS. @@ -634,7 +634,7 @@ def generate_batch_job_builder( # noqa: C901 tmp_path: EFSPath, scratch_mount_point: MountPointConfiguration, shared_mount_point: MountPointConfiguration, - tmp_mount_point: Optional[MountPointConfiguration] = None, + tmp_mount_point: MountPointConfiguration | None = None, env_file_write_mode: EnvFileWriteMode = EnvFileWriteMode.ALWAYS, ) -> BatchJobBuilder: """Generate a BatchJobBuilder for the demand execution. @@ -678,7 +678,7 @@ def generate_batch_job_builder( # noqa: C901 WORKING_DIR_VAR = "WORKING_DIR" TMPDIR_VAR = "TMPDIR" - environment: Dict[str, str] = { + environment: dict[str, str] = { EXECUTION_ID_VAR: demand_execution.execution_id, WORKING_DIR_VAR: f"{container_working_path}", TMPDIR_VAR: f"{container_tmp_path}", @@ -770,7 +770,7 @@ def generate_batch_job_builder( # noqa: C901 # Step 1:, split environment variables based on reference are referenced in the command writable_environment = environment.copy() - required_environment: Dict[str, str] = {} + required_environment: dict[str, str] = {} for arg in command + [_ for c in pre_commands for _ in c]: for match in re.findall(r"\$\{?([\w]+)\}?", arg): if match in writable_environment: diff --git a/src/aibs_informatics_aws_lambda/handlers/demand/model.py b/src/aibs_informatics_aws_lambda/handlers/demand/model.py index dcd276d..caacf30 100644 --- a/src/aibs_informatics_aws_lambda/handlers/demand/model.py +++ b/src/aibs_informatics_aws_lambda/handlers/demand/model.py @@ -4,27 +4,19 @@ execution scaffolding and management. """ -from dataclasses import dataclass from enum import Enum -from typing import List, Optional, Union from aibs_informatics_core.models.aws.s3 import S3Path -from aibs_informatics_core.models.base import ( - EnumField, - ListField, - SchemaModel, - UnionField, - custom_field, -) +from aibs_informatics_core.models.base import PydanticBaseModel from aibs_informatics_core.models.data_sync import DataSyncRequest, PrepareBatchDataSyncRequest from aibs_informatics_core.models.demand_execution import DemandExecution +from pydantic import Field from aibs_informatics_aws_lambda.handlers.batch.model import CreateDefinitionAndPrepareArgsRequest from aibs_informatics_aws_lambda.handlers.data_sync.model import RemoveDataPathsRequest -@dataclass -class FileSystemConfiguration(SchemaModel): +class FileSystemConfiguration(PydanticBaseModel): """Configuration for an EFS file system mount. Attributes: @@ -33,13 +25,12 @@ class FileSystemConfiguration(SchemaModel): container_path: Optional custom container mount path. """ - file_system: Optional[str] = None - access_point: Optional[str] = None - container_path: Optional[str] = None + file_system: str | None = None + access_point: str | None = None + container_path: str | None = None -@dataclass -class DemandFileSystemConfigurations(SchemaModel): +class DemandFileSystemConfigurations(PydanticBaseModel): """Collection of file system configurations for demand execution. Attributes: @@ -48,15 +39,9 @@ class DemandFileSystemConfigurations(SchemaModel): tmp: Optional configuration for a dedicated tmp volume. """ - shared: FileSystemConfiguration = custom_field( - mm_field=FileSystemConfiguration.as_mm_field(), default_factory=FileSystemConfiguration - ) - scratch: FileSystemConfiguration = custom_field( - mm_field=FileSystemConfiguration.as_mm_field(), default_factory=FileSystemConfiguration - ) - tmp: Optional[FileSystemConfiguration] = custom_field( - mm_field=FileSystemConfiguration.as_mm_field(), default=None - ) + shared: FileSystemConfiguration = Field(default_factory=FileSystemConfiguration) + scratch: FileSystemConfiguration = Field(default_factory=FileSystemConfiguration) + tmp: FileSystemConfiguration | None = None class EnvFileWriteMode(str, Enum): @@ -77,8 +62,7 @@ class EnvFileWriteMode(str, Enum): IF_REQUIRED = "IF_REQUIRED" -@dataclass -class DataSyncConfiguration(SchemaModel): +class DataSyncConfiguration(PydanticBaseModel): """Configuration for data synchronization behavior. Controls how data is synced between S3 and EFS for demand executions. @@ -92,15 +76,12 @@ class DataSyncConfiguration(SchemaModel): If False, also verify checksums. """ - temporary_request_payload_path: Optional[S3Path] = custom_field( - default=None, mm_field=S3Path.as_mm_field() - ) - force: bool = custom_field(default=False) - size_only: bool = custom_field(default=True) + temporary_request_payload_path: S3Path | None = None + force: bool = False + size_only: bool = True -@dataclass -class ContextManagerConfiguration(SchemaModel): +class ContextManagerConfiguration(PydanticBaseModel): """Configuration for demand execution context management. Controls behavior of input/output handling, cleanup, and environment @@ -116,22 +97,19 @@ class ContextManagerConfiguration(SchemaModel): output_data_sync_configuration: Configuration for output data sync. """ - isolate_inputs: bool = custom_field(default=True) - cleanup_inputs: bool = custom_field(default=True) - cleanup_working_dir: bool = custom_field(default=True) - env_file_write_mode: EnvFileWriteMode = custom_field( - mm_field=EnumField(EnvFileWriteMode), default=EnvFileWriteMode.ALWAYS - ) - input_data_sync_configuration: DataSyncConfiguration = custom_field( - default_factory=DataSyncConfiguration, mm_field=DataSyncConfiguration.as_mm_field() + isolate_inputs: bool = True + cleanup_inputs: bool = True + cleanup_working_dir: bool = True + env_file_write_mode: EnvFileWriteMode = EnvFileWriteMode.ALWAYS + input_data_sync_configuration: DataSyncConfiguration = Field( + default_factory=DataSyncConfiguration ) - output_data_sync_configuration: DataSyncConfiguration = custom_field( - default_factory=DataSyncConfiguration, mm_field=DataSyncConfiguration.as_mm_field() + output_data_sync_configuration: DataSyncConfiguration = Field( + default_factory=DataSyncConfiguration ) -@dataclass -class PrepareDemandScaffoldingRequest(SchemaModel): +class PrepareDemandScaffoldingRequest(PydanticBaseModel): """Request for preparing demand execution scaffolding. Attributes: @@ -140,19 +118,16 @@ class PrepareDemandScaffoldingRequest(SchemaModel): context_manager_configuration: Execution context settings. """ - demand_execution: DemandExecution = custom_field(mm_field=DemandExecution.as_mm_field()) - file_system_configurations: DemandFileSystemConfigurations = custom_field( - mm_field=DemandFileSystemConfigurations.as_mm_field(), - default_factory=DemandFileSystemConfigurations, + demand_execution: DemandExecution + file_system_configurations: DemandFileSystemConfigurations = Field( + default_factory=DemandFileSystemConfigurations ) - context_manager_configuration: ContextManagerConfiguration = custom_field( - mm_field=ContextManagerConfiguration.as_mm_field(), - default_factory=ContextManagerConfiguration, + context_manager_configuration: ContextManagerConfiguration = Field( + default_factory=ContextManagerConfiguration ) -@dataclass -class DemandExecutionSetupConfigs(SchemaModel): +class DemandExecutionSetupConfigs(PydanticBaseModel): """Setup configurations generated for a demand execution. Contains the data sync requests and batch job configuration @@ -163,26 +138,16 @@ class DemandExecutionSetupConfigs(SchemaModel): batch_create_request: Request to create the batch job. """ - data_sync_requests: List[Union[DataSyncRequest, PrepareBatchDataSyncRequest]] = custom_field( - mm_field=UnionField( - [ - # NOTE: PrepareBatchDataSyncRequest is a subclass of DataSyncRequest - # but it has extra fields. If DataSyncRequest is first, it will ignore - # the extra fields in PrepareBatchDataSyncRequest. - # Therefore, we need to put PrepareBatchDataSyncRequest first. - # TODO: Consider dropping DataSyncRequest and only use PrepareBatchDataSyncRequest - (list, ListField(PrepareBatchDataSyncRequest.as_mm_field())), - (list, ListField(DataSyncRequest.as_mm_field())), - ] - ) - ) - batch_create_request: CreateDefinitionAndPrepareArgsRequest = custom_field( - mm_field=CreateDefinitionAndPrepareArgsRequest.as_mm_field() - ) + # NOTE: PrepareBatchDataSyncRequest is a subclass of DataSyncRequest + # but it has extra fields. If DataSyncRequest is first, it will ignore + # the extra fields in PrepareBatchDataSyncRequest. + # Therefore, we need to put PrepareBatchDataSyncRequest first. + # TODO: Consider dropping DataSyncRequest and only use PrepareBatchDataSyncRequest + data_sync_requests: list[PrepareBatchDataSyncRequest | DataSyncRequest] + batch_create_request: CreateDefinitionAndPrepareArgsRequest -@dataclass -class DemandExecutionCleanupConfigs(SchemaModel): +class DemandExecutionCleanupConfigs(PydanticBaseModel): """Cleanup configurations generated for a demand execution. Contains the data sync requests and path removal requests @@ -193,26 +158,16 @@ class DemandExecutionCleanupConfigs(SchemaModel): remove_data_paths_requests: Requests to remove temporary data. """ - data_sync_requests: List[Union[DataSyncRequest, PrepareBatchDataSyncRequest]] = custom_field( - mm_field=UnionField( - [ - # NOTE: PrepareBatchDataSyncRequest is a subclass of DataSyncRequest - # but it has extra fields. If DataSyncRequest is first, it will ignore - # the extra fields in PrepareBatchDataSyncRequest. - # Therefore, we need to put PrepareBatchDataSyncRequest first. - # TODO: Consider dropping DataSyncRequest and only use PrepareBatchDataSyncRequest - (list, ListField(PrepareBatchDataSyncRequest.as_mm_field())), - (list, ListField(DataSyncRequest.as_mm_field())), - ] - ) - ) - remove_data_paths_requests: List[RemoveDataPathsRequest] = custom_field( - mm_field=ListField(RemoveDataPathsRequest.as_mm_field()), default_factory=list - ) + # NOTE: PrepareBatchDataSyncRequest is a subclass of DataSyncRequest + # but it has extra fields. If DataSyncRequest is first, it will ignore + # the extra fields in PrepareBatchDataSyncRequest. + # Therefore, we need to put PrepareBatchDataSyncRequest first. + # TODO: Consider dropping DataSyncRequest and only use PrepareBatchDataSyncRequest + data_sync_requests: list[PrepareBatchDataSyncRequest | DataSyncRequest] + remove_data_paths_requests: list[RemoveDataPathsRequest] = Field(default_factory=list) -@dataclass -class PrepareDemandScaffoldingResponse(SchemaModel): +class PrepareDemandScaffoldingResponse(PydanticBaseModel): """Response from preparing demand execution scaffolding. Attributes: @@ -221,10 +176,6 @@ class PrepareDemandScaffoldingResponse(SchemaModel): cleanup_configs: Configurations for post-execution cleanup. """ - demand_execution: DemandExecution = custom_field(mm_field=DemandExecution.as_mm_field()) - setup_configs: DemandExecutionSetupConfigs = custom_field( - mm_field=DemandExecutionSetupConfigs.as_mm_field() - ) - cleanup_configs: DemandExecutionCleanupConfigs = custom_field( - mm_field=DemandExecutionCleanupConfigs.as_mm_field() - ) + demand_execution: DemandExecution + setup_configs: DemandExecutionSetupConfigs + cleanup_configs: DemandExecutionCleanupConfigs diff --git a/src/aibs_informatics_aws_lambda/handlers/demand/scaffolding.py b/src/aibs_informatics_aws_lambda/handlers/demand/scaffolding.py index 126e8e0..52792f0 100644 --- a/src/aibs_informatics_aws_lambda/handlers/demand/scaffolding.py +++ b/src/aibs_informatics_aws_lambda/handlers/demand/scaffolding.py @@ -6,7 +6,6 @@ from dataclasses import dataclass from pathlib import Path -from typing import Optional, Union from aibs_informatics_aws_utils.batch import build_retry_strategy from aibs_informatics_aws_utils.constants.efs import ( @@ -165,9 +164,9 @@ def setup_file_system(self, context_manager: DemandExecutionContextManager): def construct_batch_efs_configuration( env_base: EnvBase, - container_path: Union[Path, str], - file_system: Optional[str], - access_point: Optional[str], + container_path: Path | str, + file_system: str | None, + access_point: str | None, read_only: bool = False, ) -> BatchEFSConfiguration: """Construct a BatchEFSConfiguration for a volume. diff --git a/src/aibs_informatics_aws_lambda/handlers/notifications/model.py b/src/aibs_informatics_aws_lambda/handlers/notifications/model.py index 2ebcf10..733485b 100644 --- a/src/aibs_informatics_aws_lambda/handlers/notifications/model.py +++ b/src/aibs_informatics_aws_lambda/handlers/notifications/model.py @@ -10,18 +10,11 @@ "NotificationResponse", ] -from dataclasses import dataclass -from enum import Enum -from typing import Any, Dict, List, Union - -from aibs_informatics_core.models.base import ( - EnumField, - ListField, - SchemaModel, - StringField, - UnionField, - custom_field, -) +from enum import StrEnum +from typing import Any + +from aibs_informatics_core.models.base import PydanticBaseModel +from pydantic import model_validator from aibs_informatics_aws_lambda.handlers.notifications.notifiers.model import ( NotifierResult, @@ -33,7 +26,7 @@ """Alternative field names accepted for the message content.""" -class NotificationContentType(str, Enum): +class NotificationContentType(StrEnum): """Content types for notification messages. Attributes: @@ -47,8 +40,7 @@ class NotificationContentType(str, Enum): JSON = "json" -@dataclass -class NotificationContent(SchemaModel): +class NotificationContent(PydanticBaseModel): """Content of a notification message. Attributes: @@ -57,14 +49,15 @@ class NotificationContent(SchemaModel): content_type: The format of the message content. """ - subject: str = custom_field(mm_field=StringField()) - message: str = custom_field(mm_field=StringField()) - content_type: NotificationContentType = custom_field( - mm_field=EnumField(NotificationContentType), default=NotificationContentType.PLAIN_TEXT - ) + subject: str + message: str + content_type: NotificationContentType = NotificationContentType.PLAIN_TEXT + @model_validator(mode="before") @classmethod - def _parse_fields(cls, data: Dict[str, Any]) -> Dict[str, Any]: + def _parse_fields(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data for key_alias in MESSAGE_KEY_ALIASES: if key_alias in data and "message" not in data: data["message"] = data[key_alias] @@ -72,8 +65,7 @@ def _parse_fields(cls, data: Dict[str, Any]) -> Dict[str, Any]: return data -@dataclass -class NotificationRequest(SchemaModel): +class NotificationRequest(PydanticBaseModel): """Request model for sending notifications. Attributes: @@ -81,20 +73,15 @@ class NotificationRequest(SchemaModel): targets: List of delivery targets (SES or SNS). """ - content: NotificationContent = custom_field(mm_field=NotificationContent.as_mm_field()) - targets: List[Union[SESEmailTarget, SNSTopicTarget]] = custom_field( - mm_field=ListField( - UnionField([(_, _.as_mm_field()) for _ in [SESEmailTarget, SNSTopicTarget]]), # type: ignore[list-item, misc] - ), - ) + content: NotificationContent + targets: list[SESEmailTarget | SNSTopicTarget] -@dataclass -class NotificationResponse(SchemaModel): +class NotificationResponse(PydanticBaseModel): """Response model for notification delivery. Attributes: results: List of results for each notification target. """ - results: List[NotifierResult] = custom_field(mm_field=ListField(NotifierResult.as_mm_field())) + results: list[NotifierResult] diff --git a/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/base.py b/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/base.py index 49f8dcd..e558c0d 100644 --- a/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/base.py +++ b/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/base.py @@ -6,7 +6,7 @@ from abc import abstractmethod from dataclasses import dataclass -from typing import Any, Dict, Generic, Type, Union +from typing import Any, Generic from aibs_informatics_core.utils.logging import get_logger @@ -41,7 +41,7 @@ def notify(self, content: NotificationContent, target: MyTarget) -> NotifierResu """ @classmethod - def notifier_target_class(cls) -> Type[NOTIFIER_TARGET]: + def notifier_target_class(cls) -> type[NOTIFIER_TARGET]: """Get the target class type for this notifier. Returns: @@ -63,7 +63,7 @@ def notify(self, content: NotificationContent, target: NOTIFIER_TARGET) -> Notif raise NotImplementedError("Please implement `notify` method") # pragma: no cover @classmethod - def parse_target(cls, target: Union[Dict[str, Any], NOTIFIER_TARGET]) -> NOTIFIER_TARGET: + def parse_target(cls, target: dict[str, Any] | NOTIFIER_TARGET) -> NOTIFIER_TARGET: """Parse a target from a dictionary or validate an existing target. Args: diff --git a/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/model.py b/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/model.py index 09157e1..a795c3b 100644 --- a/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/model.py +++ b/src/aibs_informatics_aws_lambda/handlers/notifications/notifiers/model.py @@ -3,24 +3,14 @@ Defines the target, content, and result models for notification delivery. """ -from dataclasses import dataclass from enum import Enum -from typing import Any, Dict, List, TypeVar, Union +from typing import Any, TypeVar -import marshmallow as mm +from aibs_informatics_core.exceptions import ValidationError from aibs_informatics_core.models.aws.sns import SNSTopicArn -from aibs_informatics_core.models.base import ( - BooleanField, - CustomStringField, - EnumField, - ListField, - RawField, - SchemaModel, - StringField, - custom_field, -) +from aibs_informatics_core.models.base import PydanticBaseModel from aibs_informatics_core.models.email_address import EmailAddress -from aibs_informatics_core.utils.json import JSON +from pydantic import JsonValue, model_validator NOTIFIER_TARGET = TypeVar("NOTIFIER_TARGET", bound="NotifierTarget") """Type variable for notifier target types.""" @@ -44,8 +34,7 @@ class NotificationContentType(str, Enum): JSON = "json" -@dataclass -class NotificationContent(SchemaModel): +class NotificationContent(PydanticBaseModel): """Content of a notification message. Attributes: @@ -54,15 +43,13 @@ class NotificationContent(SchemaModel): content_type: The format of the message content. """ - subject: str = custom_field(mm_field=StringField()) - message: str = custom_field(mm_field=StringField()) - content_type: NotificationContentType = custom_field( - mm_field=EnumField(NotificationContentType), default=NotificationContentType.PLAIN_TEXT - ) + subject: str + message: str + content_type: NotificationContentType = NotificationContentType.PLAIN_TEXT + @model_validator(mode="before") @classmethod - @mm.pre_load - def _parse_fields(cls, data: Dict[str, Any], **kwargs) -> Dict[str, Any]: + def _parse_fields(cls, data: dict[str, Any]) -> dict[str, Any]: for key_alias in MESSAGE_KEY_ALIASES: if key_alias in data and "message" not in data: data["message"] = data[key_alias] @@ -90,8 +77,7 @@ class NotifierType(str, Enum): # ---------------------------------------------------------- -@dataclass -class NotifierTarget(SchemaModel): +class NotifierTarget(PydanticBaseModel): """Base class for notification delivery targets. Subclasses define specific target types like email or SNS topics. @@ -100,7 +86,6 @@ class NotifierTarget(SchemaModel): pass -@dataclass class SESEmailTarget(NotifierTarget): """Email delivery target for SES notifications. @@ -108,13 +93,14 @@ class SESEmailTarget(NotifierTarget): recipients: List of email addresses to send to. """ - recipients: List[EmailAddress] = custom_field( - mm_field=ListField(CustomStringField(EmailAddress)) - ) + recipients: list[EmailAddress] + @model_validator(mode="before") @classmethod - @mm.pre_load - def _parse_recipient_fields(cls, data: Dict[str, Any], **kwargs) -> Dict[str, Any]: + def _parse_recipient_fields(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + recipients = [] for key_alias in ["recipients", "recipient", "addresses", "address"]: @@ -124,12 +110,11 @@ def _parse_recipient_fields(cls, data: Dict[str, Any], **kwargs) -> Dict[str, An elif isinstance(value_list, list): recipients.extend(value_list) else: - raise mm.ValidationError("Invalid recipient type") + raise ValidationError("Invalid recipient type") data["recipients"] = sorted(set(recipients)) return data -@dataclass class SNSTopicTarget(NotifierTarget): """SNS topic delivery target for notifications. @@ -137,7 +122,7 @@ class SNSTopicTarget(NotifierTarget): topic: The ARN of the SNS topic to publish to. """ - topic: SNSTopicArn = custom_field(mm_field=CustomStringField(SNSTopicArn)) + topic: SNSTopicArn # ---------------------------------------------------------- @@ -145,8 +130,7 @@ class SNSTopicTarget(NotifierTarget): # ---------------------------------------------------------- -@dataclass -class NotifierResult(SchemaModel): +class NotifierResult(PydanticBaseModel): """Result of a notification delivery attempt. Attributes: @@ -155,15 +139,6 @@ class NotifierResult(SchemaModel): response: The raw response from the delivery service. """ - target: Union[dict, NotifierTarget] = custom_field(mm_field=RawField()) - success: bool = custom_field(mm_field=BooleanField()) - response: JSON = custom_field(mm_field=RawField()) - - @classmethod - @mm.post_dump - def _serialize_target(cls, data: Dict[str, Any], **kwargs) -> Dict[str, Any]: - target = data.pop("target") - if isinstance(target, NotifierTarget): - target = target.to_dict() - data["target"] = target - return data + target: SESEmailTarget | SNSTopicTarget | dict + success: bool + response: JsonValue diff --git a/src/aibs_informatics_aws_lambda/handlers/notifications/router.py b/src/aibs_informatics_aws_lambda/handlers/notifications/router.py index 8e5e92c..df56e10 100644 --- a/src/aibs_informatics_aws_lambda/handlers/notifications/router.py +++ b/src/aibs_informatics_aws_lambda/handlers/notifications/router.py @@ -5,7 +5,6 @@ """ from dataclasses import dataclass, field -from typing import List from aibs_informatics_aws_lambda.common.handler import LambdaHandler from aibs_informatics_aws_lambda.handlers.notifications.model import ( @@ -39,7 +38,7 @@ class NotificationRouter(LambdaHandler[NotificationRequest, NotificationResponse ``` """ - notifiers: List[Notifier] = field(default_factory=list) + notifiers: list[Notifier] = field(default_factory=list) def __post_init__(self): """Initialize the handler with default notifiers if none provided.""" @@ -59,7 +58,7 @@ def handle(self, request: NotificationRequest) -> NotificationResponse: Returns: Response containing results for each target. """ - results: List[NotifierResult] = [] + results: list[NotifierResult] = [] for target in request.targets: for notifier in self.notifiers: try: diff --git a/src/aibs_informatics_aws_lambda/main.py b/src/aibs_informatics_aws_lambda/main.py index 3a01a1b..dcfe061 100644 --- a/src/aibs_informatics_aws_lambda/main.py +++ b/src/aibs_informatics_aws_lambda/main.py @@ -1,7 +1,7 @@ import argparse import json import os -from typing import Optional, Sequence +from collections.abc import Sequence from aibs_informatics_aws_utils.constants.lambda_ import ( AWS_LAMBDA_EVENT_PAYLOAD_KEY, @@ -10,7 +10,7 @@ AWS_LAMBDA_FUNCTION_HANDLER_STANDARD_KEY, ) from aibs_informatics_aws_utils.s3 import download_to_json_object, upload_json -from aibs_informatics_core.models.aws.s3 import S3URI +from aibs_informatics_core.models.aws.s3 import S3Path from aibs_informatics_core.utils.json import JSON, load_json_object from aibs_informatics_core.utils.os_operations import get_env_var from aws_lambda_powertools.utilities.typing import LambdaContext @@ -27,7 +27,7 @@ @logger.inject_lambda_context(log_event=True) -def handle(event: LambdaEvent, context: LambdaContext) -> Optional[JSON]: +def handle(event: LambdaEvent, context: LambdaContext) -> JSON | None: """Route and execute a Lambda handler function invocation. This function acts as a router that deserializes the incoming event, @@ -56,7 +56,7 @@ def handle(event: LambdaEvent, context: LambdaContext) -> Optional[JSON]: return response -def handle_cli(args: Optional[Sequence[str]] = None): +def handle_cli(args: Sequence[str] | None = None): """Execute a Lambda handler from the command line interface. Parses command line arguments to determine the handler to invoke, @@ -132,9 +132,9 @@ def handle_cli(args: Optional[Sequence[str]] = None): if parsed_args.payload is None: raise ValueError("Payload could not be resolved by argument or environment variable") - if S3URI.is_valid(parsed_args.payload): + if S3Path.is_valid(parsed_args.payload): logger.info("Payload is an S3 path. downloading to JSON") - event = download_to_json_object(S3URI(parsed_args.payload)) + event = download_to_json_object(S3Path(parsed_args.payload)) else: event = load_json_object(parsed_args.payload) @@ -146,9 +146,9 @@ def handle_cli(args: Optional[Sequence[str]] = None): if response_location: response = response or {} logger.info(f"Response location specified: {response_location}") - if S3URI.is_valid(response_location): + if S3Path.is_valid(response_location): logger.info("Uploading result to S3") - upload_json(response, S3URI(response_location)) + upload_json(response, S3Path(response_location)) elif not os.path.isdir(response_location) and os.access( os.path.dirname(response_location), os.W_OK ): diff --git a/test/aibs_informatics_aws_lambda/base.py b/test/aibs_informatics_aws_lambda/base.py index 3da9d2f..e6ec985 100644 --- a/test/aibs_informatics_aws_lambda/base.py +++ b/test/aibs_informatics_aws_lambda/base.py @@ -1,5 +1,6 @@ from abc import abstractmethod -from typing import Callable, Optional, Type +from collections.abc import Callable +from typing import Optional from aibs_informatics_core.env import ENV_BASE_KEY from aibs_informatics_core.utils.json import JSON @@ -60,8 +61,8 @@ def assertHandles( self, handler: LambdaHandlerType, event: LambdaEvent, - response: Optional[JSON] = None, - context: Optional[LambdaContext] = None, + response: JSON | None = None, + context: LambdaContext | None = None, ): actual = handler(event, context or self.context) if response is None: @@ -77,8 +78,8 @@ def assertLambdaRaises( self, handler: LambdaHandlerType, event: LambdaEvent, - exception: Type[Exception], - context: Optional[LambdaContext] = None, + exception: type[Exception], + context: LambdaContext | None = None, ): with self.assertRaises(exception): handler(event, context or self.context) diff --git a/test/aibs_informatics_aws_lambda/common/api/base.py b/test/aibs_informatics_aws_lambda/common/api/base.py index 7f70152..d961083 100644 --- a/test/aibs_informatics_aws_lambda/common/api/base.py +++ b/test/aibs_informatics_aws_lambda/common/api/base.py @@ -1,8 +1,7 @@ -from dataclasses import dataclass -from typing import List, Literal +from typing import Literal from aibs_informatics_core.models.api.route import ApiRoute -from aibs_informatics_core.models.base import SchemaModel +from aibs_informatics_core.models.base import PydanticBaseModel from aibs_informatics_aws_lambda.common.api.handler import ApiLambdaHandler @@ -11,15 +10,13 @@ # ------------------------------ -@dataclass -class HealthCheckRequest(SchemaModel): +class HealthCheckRequest(PydanticBaseModel): """Can be used as a No-op""" raise_exception: bool = False -@dataclass -class HealthCheckResponse(SchemaModel): +class HealthCheckResponse(PydanticBaseModel): status: Literal["OK"] = "OK" @@ -29,7 +26,7 @@ def route_rule(cls) -> str: return "/health" @classmethod - def route_method(cls) -> List[str]: + def route_method(cls) -> list[str]: return ["GET"] @@ -47,16 +44,14 @@ def handle(self, request: HealthCheckRequest) -> HealthCheckResponse: # ------------------------------ -@dataclass -class GetRequest(SchemaModel): +class GetRequest(PydanticBaseModel): """Can be used as a Getter""" id: str -@dataclass -class GetResponse(SchemaModel): - values: List[str] +class GetResponse(PydanticBaseModel): + values: list[str] class GetRoute(ApiRoute[GetRequest, GetResponse]): @@ -65,7 +60,7 @@ def route_rule(cls) -> str: return "/get" @classmethod - def route_method(cls) -> List[str]: + def route_method(cls) -> list[str]: return ["GET"] diff --git a/test/aibs_informatics_aws_lambda/common/api/test_resolver.py b/test/aibs_informatics_aws_lambda/common/api/test_resolver.py index c2b7a80..c5c6933 100644 --- a/test/aibs_informatics_aws_lambda/common/api/test_resolver.py +++ b/test/aibs_informatics_aws_lambda/common/api/test_resolver.py @@ -1,5 +1,3 @@ -from typing import Optional - from aws_lambda_powertools.event_handler.api_gateway import Router from aws_lambda_powertools.shared.constants import METRICS_NAMESPACE_ENV from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent @@ -139,7 +137,7 @@ def create_event( self, path: str, method: str, - query_string_parameters: Optional[str] = None, + query_string_parameters: str | None = None, body: str = '"{}"', ): return { diff --git a/test/aibs_informatics_aws_lambda/common/test_handler.py b/test/aibs_informatics_aws_lambda/common/test_handler.py index 5696d4d..2f001ab 100644 --- a/test/aibs_informatics_aws_lambda/common/test_handler.py +++ b/test/aibs_informatics_aws_lambda/common/test_handler.py @@ -1,7 +1,5 @@ -from dataclasses import dataclass - from aibs_informatics_core.env import ENV_BASE_KEY -from aibs_informatics_core.models.base import IntegerField, SchemaModel, custom_field +from aibs_informatics_core.models.base import PydanticBaseModel from aws_lambda_powertools.utilities.data_classes.dynamo_db_stream_event import ( DynamoDBRecordEventName, ) @@ -11,25 +9,22 @@ from test.aibs_informatics_aws_lambda.base import LambdaHandlerTestCase, LambdaHandlerType -@dataclass -class NoResponse(SchemaModel): +class NoResponse(PydanticBaseModel): pass -@dataclass -class CounterRequest(SchemaModel): - count: int = custom_field(mm_field=IntegerField()) +class CounterRequest(PydanticBaseModel): + count: int -@dataclass -class CounterResponse(SchemaModel): - count: int = custom_field(mm_field=IntegerField()) +class CounterResponse(PydanticBaseModel): + count: int class CounterHandler_ReqResp(LambdaHandler[CounterRequest, CounterResponse]): def handle(self, request: CounterRequest) -> CounterResponse: self.log.info(f"Hey look the count is {request.count}") - response = CounterResponse(request.count + 1) + response = CounterResponse(count=request.count + 1) self.log.info(f"Hey look the count is now {response.count}") return response @@ -86,7 +81,7 @@ def get_handler(self) -> LambdaHandlerType: return handler def test__handler__handles_valid_request_and_returns_no_response(self): - self.assertHandles(self.get_handler(), CounterRequest(1).to_dict(), None) + self.assertHandles(self.get_handler(), CounterRequest(count=1).to_dict(), None) def test__handler__handles_invalid_request_and_raises_error(self): with self.assertRaises(Exception): @@ -110,8 +105,8 @@ def test__props__work(self): def test__handler__handles_valid_request_and_returns_response(self): self.assertHandles( self.get_handler(), - CounterRequest(1).to_dict(), - CounterResponse(2).to_dict(), + CounterRequest(count=1).to_dict(), + CounterResponse(count=2).to_dict(), ) def test__handler__handles_invalid_request_and_raises_error(self): @@ -122,8 +117,8 @@ def test__sqs_handler__handles_stuffs(self): handler = CounterHandler_ReqResp.get_sqs_batch_handler() event = { "Records": [ - {"body": CounterRequest(1).to_json()}, - {"body": CounterRequest(0).to_json()}, + {"body": CounterRequest(count=1).to_json()}, + {"body": CounterRequest(count=0).to_json()}, ] } self.assertHandles(handler, event, {"batchItemFailures": []}) @@ -143,7 +138,7 @@ def test__dynamo_handler__handles_stuffs(self): "dynamodb": { "NewImage": { k: type_serializer.serialize(v) - for k, v in CounterRequest(1).to_dict().items() + for k, v in CounterRequest(count=1).to_dict().items() }, }, "eventName": "INSERT", @@ -154,7 +149,7 @@ def test__dynamo_handler__handles_stuffs(self): "dynamodb": { "NewImage": { k: type_serializer.serialize(v) - for k, v in CounterRequest(1).to_dict().items() + for k, v in CounterRequest(count=1).to_dict().items() }, }, "eventName": "MODIFY", diff --git a/test/aibs_informatics_aws_lambda/common/test_models.py b/test/aibs_informatics_aws_lambda/common/test_models.py index 6a07f27..55d9ac4 100644 --- a/test/aibs_informatics_aws_lambda/common/test_models.py +++ b/test/aibs_informatics_aws_lambda/common/test_models.py @@ -1,5 +1,3 @@ -from typing import Optional - from aibs_informatics_core.utils.json import JSON from aws_lambda_powertools.utilities.typing import LambdaContext from pytest import mark, param, raises @@ -10,7 +8,7 @@ from test.base import does_not_raise -def mock_handler(event: LambdaEvent, context: LambdaContext) -> Optional[JSON]: +def mock_handler(event: LambdaEvent, context: LambdaContext) -> JSON | None: if isinstance(event, dict): if event.get("fail", False): raise ValueError("something went wrong") @@ -30,13 +28,13 @@ def mock_handler(event: LambdaEvent, context: LambdaContext) -> Optional[JSON]: "handler": "test.aibs_informatics_aws_lambda.common.test_models.mock_handler", "event": {}, }, - LambdaHandlerRequest(mock_handler, {}), + LambdaHandlerRequest(handler=mock_handler, event={}), does_not_raise(), id="simple", ), ], ) -def test__get_qualified_name(value, expected: Optional[LambdaHandlerRequest], raise_expectation): +def test__get_qualified_name(value, expected: LambdaHandlerRequest | None, raise_expectation): with raise_expectation: actual = LambdaHandlerRequest.from_dict(value) @@ -67,3 +65,75 @@ def test__deserialize_handler__handles_class(): def test__deserialize_handler__handles_class_instance(): with raises(ValueError): deserialize_handler("test.aibs_informatics_aws_lambda.common.test_models.DUMMY_VARIABLE") + + +def test__deserialize_handler__handles_callable_passthrough(): + actual = deserialize_handler(mock_handler) + assert actual is mock_handler + + +def test__deserialize_handler__raises_for_non_callable(): + with raises(ValueError, match="expected a callable"): + deserialize_handler(42) # type: ignore[arg-type] + + +# --- PlainSerializer tests (to_dict / serialization) --- + + +def test__serialize_handler__function_to_qualified_name(): + request = LambdaHandlerRequest(handler=mock_handler, event={}) + result = request.to_dict() + assert result["handler"] == "test.aibs_informatics_aws_lambda.common.test_models.mock_handler" + + +counter_handler = CounterHandler_ReqResp.get_handler() + + +def test__serialize_handler__class_handler_to_qualified_name(): + request = LambdaHandlerRequest(handler=counter_handler, event={}) + result = request.to_dict() + # The serialized handler should resolve to the module-level variable + assert ( + result["handler"] == "test.aibs_informatics_aws_lambda.common.test_models.counter_handler" + ) + + +def test__serialize_handler__preserves_event(): + event_data = {"key": "value", "nested": {"a": 1}} + request = LambdaHandlerRequest(handler=mock_handler, event=event_data) + result = request.to_dict() + assert result["event"] == event_data + + +def test__serialize_handler__roundtrip_function(): + """Deserialize from dict, serialize back, and verify consistency.""" + original = { + "handler": "test.aibs_informatics_aws_lambda.common.test_models.mock_handler", + "event": {"foo": "bar"}, + } + request = LambdaHandlerRequest.from_dict(original) + serialized = request.to_dict() + assert serialized["handler"] == original["handler"] + assert serialized["event"] == original["event"] + + # Deserialize again from the serialized output + request2 = LambdaHandlerRequest.from_dict(serialized) + assert request2.handler.__name__ == request.handler.__name__ + assert request2.event == request.event + + +def test__serialize_handler__roundtrip_class(): + """Deserialize a class handler from dict, serialize back, and verify consistency.""" + original = { + "handler": "test.aibs_informatics_aws_lambda.common.test_handler.CounterHandler_ReqResp", + "event": {"count": 5}, + } + request = LambdaHandlerRequest.from_dict(original) + serialized = request.to_dict() + assert isinstance(serialized["handler"], str) + assert serialized["event"] == original["event"] + + # Roundtrip: re-deserialize should produce equivalent handler + request2 = LambdaHandlerRequest.from_dict(serialized) + assert request2.handler.__name__ == request.handler.__name__ + assert request2.event == request.event diff --git a/test/aibs_informatics_aws_lambda/handlers/data_sync/test_file_system.py b/test/aibs_informatics_aws_lambda/handlers/data_sync/test_file_system.py index e633c09..dff2f5c 100644 --- a/test/aibs_informatics_aws_lambda/handlers/data_sync/test_file_system.py +++ b/test/aibs_informatics_aws_lambda/handlers/data_sync/test_file_system.py @@ -1,7 +1,6 @@ from datetime import timedelta from pathlib import Path from time import sleep -from typing import Tuple, Union from aibs_informatics_aws_utils.data_sync.file_system import LocalFileSystem, PathStats @@ -26,7 +25,7 @@ class BaseFileSystemHandlerTestCase(LambdaHandlerTestCase): - def add_files_to_file_system(self, root: Path, *paths: Tuple[Union[Path, str], int]) -> Path: + def add_files_to_file_system(self, root: Path, *paths: tuple[Path | str, int]) -> Path: full_paths = [(root / p, sz) for p, sz in paths] for path, sz in full_paths: diff --git a/test/aibs_informatics_aws_lambda/handlers/data_sync/test_model.py b/test/aibs_informatics_aws_lambda/handlers/data_sync/test_model.py index 41bbcff..970f32a 100644 --- a/test/aibs_informatics_aws_lambda/handlers/data_sync/test_model.py +++ b/test/aibs_informatics_aws_lambda/handlers/data_sync/test_model.py @@ -7,10 +7,10 @@ def test_with_data_path_efs(): - efs_path = EFSPath("fs-123456789:/efs") + efs_path = EFSPath("fs-123456789:/efs/path") with_data_path_efs = WithDataPath(path=efs_path) assert with_data_path_efs.efs_path == efs_path - assert with_data_path_efs.s3_uri is None + assert with_data_path_efs.s3_path is None assert with_data_path_efs.local_path is None @@ -18,7 +18,7 @@ def test_with_data_path_s3(): s3_path = S3Path("s3://bucket/key") with_data_path_s3 = WithDataPath(path=s3_path) assert with_data_path_s3.efs_path is None - assert with_data_path_s3.s3_uri == s3_path + assert with_data_path_s3.s3_path == s3_path assert with_data_path_s3.local_path is None @@ -26,7 +26,7 @@ def test_with_data_path_local(): local_path = Path("/local/path") with_data_path_local = WithDataPath(path=local_path) assert with_data_path_local.efs_path is None - assert with_data_path_local.s3_uri is None + assert with_data_path_local.s3_path is None assert with_data_path_local.local_path == local_path diff --git a/test/aibs_informatics_aws_lambda/handlers/data_sync/test_operations.py b/test/aibs_informatics_aws_lambda/handlers/data_sync/test_operations.py index b925050..ae7cf50 100644 --- a/test/aibs_informatics_aws_lambda/handlers/data_sync/test_operations.py +++ b/test/aibs_informatics_aws_lambda/handlers/data_sync/test_operations.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import Tuple, Union from unittest import mock from aibs_informatics_aws_utils.data_sync.file_system import Node @@ -391,7 +390,7 @@ def test__build__build_destination_path__s3_to_s3__single_folder(self): actual = PrepareBatchDataSyncHandler.build_destination_path(request, node) self.assertEqual(expected, actual) - def setUpLocalFS(self, *paths: Tuple[Union[Path, str], int]) -> Path: + def setUpLocalFS(self, *paths: tuple[Path | str, int]) -> Path: root_file_system = self.tmp_path() for relative_path, size in paths: full_path = root_file_system / relative_path @@ -608,7 +607,7 @@ def test__handle__requests_stored_in_s3(self): self.mock_sync_operations.assert_called() self.assertEqual(self.mock_sync_operations.call_count, 1) - def setUpLocalFS(self, *paths: Tuple[Union[Path, str], int]) -> Path: + def setUpLocalFS(self, *paths: tuple[Path | str, int]) -> Path: root_file_system = self.tmp_path() for relative_path, size in paths: full_path = root_file_system / relative_path @@ -697,7 +696,7 @@ def setUpLocalFS(self, *paths: Tuple[Union[Path, str], int]) -> Path: def test__PrepareBatchDataSyncHandler_build_destination_path( request_obj: PrepareBatchDataSyncRequest, node: Node, - expected: Union[Path, S3Path], + expected: Path | S3Path, ): actual = PrepareBatchDataSyncHandler.build_destination_path(request_obj, node) diff --git a/test/aibs_informatics_aws_lambda/handlers/demand/test_context_manager.py b/test/aibs_informatics_aws_lambda/handlers/demand/test_context_manager.py index 6851bdf..db709fa 100644 --- a/test/aibs_informatics_aws_lambda/handlers/demand/test_context_manager.py +++ b/test/aibs_informatics_aws_lambda/handlers/demand/test_context_manager.py @@ -1,6 +1,5 @@ from datetime import datetime from pathlib import Path -from typing import Dict, Optional, Union import boto3 from aibs_informatics_aws_utils.constants.efs import ( @@ -16,7 +15,7 @@ from aibs_informatics_aws_utils.efs import MountPointConfiguration, detect_mount_points from aibs_informatics_core.env import EnvBase from aibs_informatics_core.models.aws.efs import EFSPath -from aibs_informatics_core.models.aws.s3 import S3URI +from aibs_informatics_core.models.aws.s3 import S3Path from aibs_informatics_core.models.demand_execution import ( DemandExecution, DemandExecutionMetadata, @@ -49,8 +48,8 @@ DEMAND_ID = UniqueID.create() ANOTHER_DEMAND_ID = UniqueID.create() -S3_URI = S3URI.build(bucket_name="bucket", key="key") -ANOTHER_S3_URI = S3URI.build(bucket_name="bucket", key="another_key") +S3_URI = S3Path.build(bucket_name="bucket", key="key") +ANOTHER_S3_URI = S3Path.build(bucket_name="bucket", key="another_key") EXECUTION_IMAGE = "051791135335.dkr.ecr.us-west-2.amazonaws.com/test_image:latest" @@ -61,13 +60,13 @@ def get_any_demand_execution( - execution_id: Optional[str] = None, - execution_type: Optional[str] = None, - execution_image: Optional[str] = None, - execution_parameters: Optional[DemandExecutionParameters] = None, - execution_metadata: Optional[DemandExecutionMetadata] = None, - execution_resource_requirements: Optional[DemandResourceRequirements] = None, - execution_platform: Optional[ExecutionPlatform] = None, + execution_id: str | None = None, + execution_type: str | None = None, + execution_image: str | None = None, + execution_parameters: DemandExecutionParameters | None = None, + execution_metadata: DemandExecutionMetadata | None = None, + execution_resource_requirements: DemandResourceRequirements | None = None, + execution_platform: ExecutionPlatform | None = None, ) -> DemandExecution: return DemandExecution( execution_id=execution_id or DEMAND_ID, @@ -97,7 +96,7 @@ def get_or_create_file_system_fixture(efs): _cache = {} def get_or_create_file_system( - file_system_name: Optional[str] = None, tags: Optional[Dict[str, str]] = None + file_system_name: str | None = None, tags: dict[str, str] | None = None ) -> str: file_system_name = file_system_name or "test_file_system" if file_system_name not in _cache: @@ -118,7 +117,7 @@ def create_access_point( file_system_id: str, access_point_name: str, path: str, - tags: Optional[Dict[str, str]] = None, + tags: dict[str, str] | None = None, ): tags_list = [{"Key": k, "Value": v} for k, v in (tags or {}).items()] tags_list.insert(0, {"Key": "Name", "Value": access_point_name}) @@ -272,7 +271,7 @@ def test__generate_batch_job_builder__simple(get_or_create_file_system, create_a "C": "c", "D": f"d @ {ANOTHER_S3_URI}-out", }, - output_s3_prefix=S3URI.build("bucket", key="outs/"), + output_s3_prefix=S3Path.build("bucket", key="outs/"), ), ) @@ -375,7 +374,7 @@ def efs_client(self): return boto3.client("efs") def create_file_system( - self, file_system_name: Optional[str] = None, tags: Optional[Dict[str, str]] = None + self, file_system_name: str | None = None, tags: dict[str, str] | None = None ): file_system_name = file_system_name or "fs" if file_system_name not in self._file_store_name_id_map: @@ -391,10 +390,10 @@ def create_file_system( def create_access_point( self, access_point_name: str, - access_point_path: Union[Path, str] = Path("/"), - file_system_id: Optional[str] = None, - file_system_name: Optional[str] = None, - tags: Optional[Dict[str, str]] = None, + access_point_path: Path | str = Path("/"), + file_system_id: str | None = None, + file_system_name: str | None = None, + tags: dict[str, str] | None = None, ): file_system_id = file_system_id or self.create_file_system(file_system_name) access_point_path = Path(access_point_path) @@ -687,7 +686,7 @@ def test__pre_execution_data_sync_requests__single_input_generates_list__with_da cleanup_inputs=False, cleanup_working_dir=False, input_data_sync_configuration=DataSyncConfiguration( - temporary_request_payload_path=S3URI("s3://bucket/override_prefix") + temporary_request_payload_path=S3Path("s3://bucket/override_prefix") ), ), ) @@ -752,7 +751,7 @@ def test__post_execution_data_sync_requests__single_output_generates_list__with_ self.env_base, ContextManagerConfiguration( output_data_sync_configuration=DataSyncConfiguration( - temporary_request_payload_path=S3URI("s3://bucket/override_prefix") + temporary_request_payload_path=S3Path("s3://bucket/override_prefix") ) ), ) diff --git a/test/aibs_informatics_aws_lambda/handlers/demand/test_scaffolding.py b/test/aibs_informatics_aws_lambda/handlers/demand/test_scaffolding.py index 3b18eb6..df0ee04 100644 --- a/test/aibs_informatics_aws_lambda/handlers/demand/test_scaffolding.py +++ b/test/aibs_informatics_aws_lambda/handlers/demand/test_scaffolding.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Any, Dict +from typing import Any from unittest import mock from aibs_informatics_aws_utils.efs import MountPointConfiguration @@ -168,8 +168,8 @@ def test__construct_batch_efs_configuration__works(self) -> None: "aibs_informatics_aws_lambda.handlers.demand.scaffolding.construct_batch_efs_configuration" ) def test__handle__simple_case(self, mock_construct_batch_efs_configuration) -> None: - mock_construct_batch_efs_configuration.side_effect = ( - lambda *args, **kwargs: BatchEFSConfiguration( + mock_construct_batch_efs_configuration.side_effect = lambda *args, **kwargs: ( + BatchEFSConfiguration( mount_point_config=MountPointConfiguration( file_system=self.get_file_system("fs-123456789012"), access_point=self.get_access_point("fsap-123456789012", "fs-123456789012"), @@ -271,8 +271,8 @@ def test__handle__simple_case(self, mock_construct_batch_efs_configuration) -> N "aibs_informatics_aws_lambda.handlers.demand.scaffolding.construct_batch_efs_configuration" ) def test__handle__file_system_overrides(self, mock_construct_batch_efs_configuration) -> None: - mock_construct_batch_efs_configuration.side_effect = ( - lambda *args, **kwargs: BatchEFSConfiguration( + mock_construct_batch_efs_configuration.side_effect = lambda *args, **kwargs: ( + BatchEFSConfiguration( mount_point_config=MountPointConfiguration( file_system=self.get_file_system("fs-123456789012"), access_point=self.get_access_point("fsap-123456789012", "fs-123456789012"), @@ -370,7 +370,7 @@ def test__handle__file_system_overrides(self, mock_construct_batch_efs_configura ), ] - def get_file_system(self, file_system_id: str) -> Dict[str, Any]: + def get_file_system(self, file_system_id: str) -> dict[str, Any]: return { "FileSystemId": file_system_id, # ID of the EFS file system "CreationToken": "string", # Unique string to ensure idempotent creation @@ -386,7 +386,7 @@ def get_file_system(self, file_system_id: str) -> Dict[str, Any]: def get_access_point( self, access_point_id: str, file_system_id: str, **tags - ) -> Dict[str, Any]: + ) -> dict[str, Any]: return { "AccessPointId": access_point_id, # ID of the EFS access point "ClientToken": "string", # Unique string to ensure idempotent creation diff --git a/test/aibs_informatics_aws_lambda/handlers/notifications/notifiers/test_models.py b/test/aibs_informatics_aws_lambda/handlers/notifications/notifiers/test_models.py index f1a375e..1b8860a 100644 --- a/test/aibs_informatics_aws_lambda/handlers/notifications/notifiers/test_models.py +++ b/test/aibs_informatics_aws_lambda/handlers/notifications/notifiers/test_models.py @@ -3,6 +3,7 @@ from aibs_informatics_aws_lambda.handlers.notifications.notifiers.model import ( NotificationContent, + NotifierResult, SESEmailTarget, ) from test.base import does_not_raise @@ -69,3 +70,64 @@ def test__NotificationContent__from_dict(value, expected, raise_expectation): if expected: assert actual == expected + + +@mark.parametrize( + "value,expected,raise_expectation", + [ + param( + { + "target": {"recipients": [ADDR1]}, + "success": True, + "response": {"message_id": "123"}, + }, + NotifierResult( + target=SESEmailTarget(recipients=[EmailAddress(ADDR1)]), + success=True, + response={"message_id": "123"}, + ), + does_not_raise(), + id="simple", + ), + param( + { + "target": {"recipients": [ADDR1, ADDR2], "recipient": ADDR3}, + "success": True, + "response": {"message_id": "123"}, + }, + NotifierResult( + target=SESEmailTarget( + recipients=[ + EmailAddress(ADDR1), + EmailAddress(ADDR2), + EmailAddress(ADDR3), + ] + ), + success=True, + response={"message_id": "123"}, + ), + does_not_raise(), + id="handles aliases", + ), + param( + { + "target": {"random_field": "value"}, + "success": True, + "response": {"message_id": "123"}, + }, + NotifierResult( + target={"random_field": "value"}, + success=True, + response={"message_id": "123"}, + ), + does_not_raise(), + id="handles unknown fields", + ), + ], +) +def test__NotifierResult__from_dict(value, expected, raise_expectation): + with raise_expectation: + actual = NotifierResult.from_dict(value) + + if expected: + assert actual == expected diff --git a/test/aibs_informatics_aws_lambda/test_main.py b/test/aibs_informatics_aws_lambda/test_main.py index cabddb0..aeca027 100644 --- a/test/aibs_informatics_aws_lambda/test_main.py +++ b/test/aibs_informatics_aws_lambda/test_main.py @@ -1,5 +1,3 @@ -from typing import Optional - from aibs_informatics_core.env import EnvBase from aibs_informatics_core.utils.json import JSON from aws_lambda_powertools.utilities.typing import LambdaContext @@ -15,7 +13,7 @@ from test.base import BaseTest -def mock_handler(event: LambdaEvent, context: LambdaContext) -> Optional[JSON]: +def mock_handler(event: LambdaEvent, context: LambdaContext) -> JSON | None: if isinstance(event, dict): if event.get("fail", False): raise ValueError("something went wrong") @@ -37,8 +35,9 @@ def setUp(self) -> None: def test__handle__succeeds(self): event = {"response": False} - response = handle( - LambdaHandlerRequest(mock_handler, event).to_dict(), DefaultLambdaContext() + handle( + LambdaHandlerRequest(handler=mock_handler, event=event).to_dict(), + DefaultLambdaContext(), ) def test__handle_cli__succeeds__resolves_args_from_env__no_response(self): diff --git a/test/base.py b/test/base.py index 3a265d8..d20a56b 100644 --- a/test/base.py +++ b/test/base.py @@ -5,7 +5,6 @@ ] from contextlib import nullcontext as does_not_raise -from typing import Optional from aibs_informatics_core.env import ENV_BASE_KEY, EnvBase, EnvType from aibs_informatics_test_resources import BaseTest as _BaseTest @@ -14,7 +13,7 @@ class BaseTest(_BaseTest): - maxDiff: Optional[int] = None + maxDiff: int | None = None @property def env_base(self) -> EnvBase: @@ -26,7 +25,7 @@ def env_base(self) -> EnvBase: def env_base(self, env_base: EnvBase): self._env_base = env_base - def set_env_base_env_var(self, env_base: Optional[EnvBase] = None): + def set_env_base_env_var(self, env_base: EnvBase | None = None): self.set_env_vars((ENV_BASE_KEY, env_base or self.env_base)) def set_aws_credentials(self): @@ -58,13 +57,13 @@ def DEFAULT_SECRET_KEY(self) -> str: def DEFAULT_ACCESS_KEY(self) -> str: return "A" * 20 - def set_region(self, region: Optional[str] = None): + def set_region(self, region: str | None = None): self.set_env_vars( ("AWS_REGION", region or self.DEFAULT_REGION), ("AWS_DEFAULT_REGION", region or self.DEFAULT_REGION), ) - def set_credentials(self, access_key: Optional[str] = None, secret_key: Optional[str] = None): + def set_credentials(self, access_key: str | None = None, secret_key: str | None = None): self.set_env_vars( ("AWS_ACCESS_KEY_ID", access_key or self.DEFAULT_ACCESS_KEY), ("AWS_SECRET_ACCESS_KEY", secret_key or self.DEFAULT_SECRET_KEY), @@ -72,7 +71,7 @@ def set_credentials(self, access_key: Optional[str] = None, secret_key: Optional ("AWS_SESSION_TOKEN", "testing"), ) - def set_account_id(self, account_id: Optional[str] = None): + def set_account_id(self, account_id: str | None = None): self.set_env_vars(("AWS_ACCOUNT_ID", account_id or self.ACCOUNT_ID)) def set_aws_credentials(self): diff --git a/uv.lock b/uv.lock index d6ae5be..37485a6 100644 --- a/uv.lock +++ b/uv.lock @@ -1,10 +1,6 @@ version = 1 revision = 3 -requires-python = ">=3.9" -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version < '3.10'", -] +requires-python = ">=3.11" [[package]] name = "aibs-informatics-aws-lambda" @@ -21,8 +17,7 @@ dependencies = [ dev = [ { name = "aibs-informatics-test-resources", extra = ["all"] }, { name = "boto3-stubs", extra = ["athena", "batch", "ecs", "essential", "sns", "stepfunctions"] }, - { name = "griffe-pydantic", version = "1.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "griffe-pydantic", version = "1.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "griffe-pydantic" }, { name = "mkdocs" }, { name = "mkdocs-material" }, { name = "mkdocstrings", extra = ["python"] }, @@ -32,8 +27,7 @@ docker = [ { name = "awslambdaric" }, ] docs = [ - { name = "griffe-pydantic", version = "1.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "griffe-pydantic", version = "1.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "griffe-pydantic" }, { name = "mkdocs" }, { name = "mkdocs-material" }, { name = "mkdocstrings", extra = ["python"] }, @@ -46,8 +40,8 @@ release = [ [package.metadata] requires-dist = [ - { name = "aibs-informatics-aws-utils", specifier = ">=0.0.12,<1" }, - { name = "aibs-informatics-core", specifier = ">=0.2.6,<1" }, + { name = "aibs-informatics-aws-utils", specifier = "~=1.0" }, + { name = "aibs-informatics-core", specifier = ">=1.0.3,<2" }, { name = "aws-lambda-powertools", specifier = "~=2.35" }, { name = "aws-lambda-typing" }, { name = "pydantic", specifier = ">=2.0.3,<3" }, @@ -78,39 +72,36 @@ release = [ [[package]] name = "aibs-informatics-aws-utils" -version = "0.3.0" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aibs-informatics-core" }, { name = "boto3" }, - { name = "tenacity", version = "9.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "tenacity", version = "9.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "tenacity" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/5f/095a1e1254e6555d7a3bfad4c61315a8748e7445c368ce1d22cb201ea299/aibs_informatics_aws_utils-0.3.0.tar.gz", hash = "sha256:40b89fac5b8704d08a09930511dc79e4ad8c78769086c9be3e830d7013972979", size = 84728, upload-time = "2026-03-17T22:11:26.192Z" } +sdist = { url = "https://files.pythonhosted.org/packages/34/b8/cc8d193d7f573d1a59d8eaedf488811a3466cb71bd8b557176656e5fc397/aibs_informatics_aws_utils-1.0.0.tar.gz", hash = "sha256:95e5887f42caed51d0361ab5b34070614f10025c99e21d5d766c003fcf17ec19", size = 84691, upload-time = "2026-03-19T21:04:53.234Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/ee/8027066c384890b575933e68f205826a62eba990323b7f55173c367c6f2d/aibs_informatics_aws_utils-0.3.0-py3-none-any.whl", hash = "sha256:846f1960e5c360771e187682d3fc4e0ed7a3d32ab52c539f15ec49508bf9df1b", size = 97855, upload-time = "2026-03-17T22:11:24.638Z" }, + { url = "https://files.pythonhosted.org/packages/74/b9/ef29b26a47a6d2c25b74db943bf32e2fd38ac5a9b63eaf63e5cf8b0e744a/aibs_informatics_aws_utils-1.0.0-py3-none-any.whl", hash = "sha256:30c3fbb6a61c067c39e185ff7b8bf71df7df89de3de324885df0001bcb6a1113", size = 97846, upload-time = "2026-03-19T21:04:51.817Z" }, ] [[package]] name = "aibs-informatics-core" -version = "0.4.2" +version = "1.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "dataclasses-json" }, - { name = "marshmallow" }, { name = "pathlib-abc" }, { name = "pydantic" }, { name = "python-dateutil" }, { name = "pytz" }, { name = "pyyaml" }, { name = "requests" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "stringcase" }, + { name = "typing-extensions" }, { name = "typing-inspect" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/6c/365beea1a3b47f11fce4f46b7f266e97f0c4c7014458f59481b2308cd4f0/aibs_informatics_core-0.4.2.tar.gz", hash = "sha256:6d4214916159d88d28cb60f34e7006a93d2f92899717c35ab276389736661024", size = 75868, upload-time = "2026-03-05T19:43:19.473Z" } +sdist = { url = "https://files.pythonhosted.org/packages/37/f6/72b06934f1a44539abb83c9130a31657d3a0bd93e0ddcc5d2d3b7a419a88/aibs_informatics_core-1.0.3.tar.gz", hash = "sha256:d377d5233e4ec1b9823f4ac36286e3fd3bd22f595c89ef52500c0a14ad1a95f6", size = 73087, upload-time = "2026-03-20T19:03:44.163Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/cb/c5b2fdce716c519303930c18f17be5b626d130f3d6c86e61d856a1956348/aibs_informatics_core-0.4.2-py3-none-any.whl", hash = "sha256:b4f3cb7b9039acbbc358d58726bec264ecee4ec52952b335359bae15f7b8a11b", size = 97028, upload-time = "2026-03-05T19:43:18.223Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f3/0dd2b2e061583a22c7dd387f0a7ba00691938b1777af94490646959d4d6a/aibs_informatics_core-1.0.3-py3-none-any.whl", hash = "sha256:10ceaeb9844fe1fa80211d2dc7d3762f9035f331f86f79252470b74b0698fc04", size = 91563, upload-time = "2026-03-20T19:03:42.704Z" }, ] [[package]] @@ -118,8 +109,7 @@ name = "aibs-informatics-test-resources" version = "0.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, - { name = "coverage", version = "7.13.5", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, + { name = "coverage", extra = ["toml"] }, { name = "pytest" }, { name = "pytest-cov" }, ] @@ -150,7 +140,6 @@ name = "anyio" version = "4.12.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] @@ -191,8 +180,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/98/cf/0493b0098ce2b1bcf30aaee72dcac43cd778e9cb45fe26626be5a75d8b91/awslambdaric-4.0.0.tar.gz", hash = "sha256:779d0721e60239233aec572fe336d147d1c3c4e405f7e56be7548b4dfececb35", size = 4502786, upload-time = "2026-02-20T16:00:19.615Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/3e/bfd2ba4a2f45a7fe26aa1e82fee4011c1693c1e036090edbf511c4d859bd/awslambdaric-4.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fb7c5b44db06cc6303c1851c992b99969ead5fe57e4427dfa766d54fdce2dc19", size = 345020, upload-time = "2026-02-20T16:00:06.152Z" }, - { url = "https://files.pythonhosted.org/packages/3d/1b/641234c781501599fea85d8026c4de10af99a76e81cde54ff7875a4829f1/awslambdaric-4.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ac494ef80e9552abfeda0cdab8483bb306514821c6809e5c20a9e958b79deb3", size = 347356, upload-time = "2026-02-20T16:01:03.817Z" }, { url = "https://files.pythonhosted.org/packages/5e/62/28d3ae6b1d79f3bee09a2b0421d16a0fcad4f8971b047000044dfb0120ee/awslambdaric-4.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f3fbc37f75f1ea7d1f3dd0a3f4aff9b373a989ed98dd9c7d9be0347a0b20b99", size = 345925, upload-time = "2026-02-20T16:00:07.685Z" }, { url = "https://files.pythonhosted.org/packages/f1/08/f780c2943fa42e5efde9d897bae6bf9037594075ee380182ab810eae68af/awslambdaric-4.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:52be7a5c8a03671cc77fea9cb41eca3c90acf6b1e2f4106f1f8871213fae0f4f", size = 348325, upload-time = "2026-02-20T16:01:05.065Z" }, { url = "https://files.pythonhosted.org/packages/9a/e7/298f32de8b28ec8eda85509ab3477dfcf5668734b7033d9767ba1b370bcc/awslambdaric-4.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:55d157823685708204f325dd8c561176d70718ad95d7a5ac85f18d6f3de20a77", size = 345452, upload-time = "2026-02-20T16:00:08.967Z" }, @@ -205,8 +192,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/85/706cbd24866149ed8fe2aab6b12201e2ec0c198b4a7584435e844a234a7b/awslambdaric-4.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:64c161247f3c6957a271d8be46d85742eaab9804d76c235afc61de7942bc801e", size = 348232, upload-time = "2026-02-20T16:01:10.738Z" }, { url = "https://files.pythonhosted.org/packages/67/0d/882c91a2e13655b86fd3ae955887a0464c83e8d579fced1c6b1c36f39f93/awslambdaric-4.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ae135112ae2b29b1beaee9289383ec15f3286cd0fee6047414362da3bece0faf", size = 347350, upload-time = "2026-02-20T16:00:15.336Z" }, { url = "https://files.pythonhosted.org/packages/91/6a/0a99b7912e458f2bfcbc312053c2fe3c08600a77d6f1e12f25869663c62b/awslambdaric-4.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0fcfd06b622f08316386ca23bfae7aa85189343a77548ca9124124a4e0625f20", size = 349622, upload-time = "2026-02-20T16:01:12.415Z" }, - { url = "https://files.pythonhosted.org/packages/50/a6/ce4d37258bf85c8b984533656b0432b7ca23177a96a190558b40e5ffdefb/awslambdaric-4.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:531ee2931465e078eeea1b7b91749064f07ceaef9161e9ebc9feaf24fcabe01b", size = 344829, upload-time = "2026-02-20T16:00:16.618Z" }, - { url = "https://files.pythonhosted.org/packages/be/dd/fcc0f0e235f820a73b1ac9d71c1ed5edd2997da6ae8b7c6bc960ff329bc8/awslambdaric-4.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc72ac23ef76c89db0ab7919a97ab235c8b2735714b40d1932cc3ecb876a9fe9", size = 347129, upload-time = "2026-02-20T16:01:13.737Z" }, { url = "https://files.pythonhosted.org/packages/a9/30/d8a2bf0eac750cca046b8da597c0457f92374145abc4b1cc423080452bc7/awslambdaric-4.0.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2567e2120595cf6ebcc0b5b218066954df657b1fd85bff6aad3e7e0a542ce399", size = 267612, upload-time = "2026-02-20T16:00:18.105Z" }, { url = "https://files.pythonhosted.org/packages/fb/d0/cebd4bb2c6097d9dc42d3054e82136337f5b7551e7cc1819363cb48b352e/awslambdaric-4.0.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3a5bd1b99dd982c9bcd12b9f1b6b2a6d2265de92e6cd24c61d752c7ddf64ba13", size = 271431, upload-time = "2026-02-20T16:01:14.973Z" }, ] @@ -239,59 +224,47 @@ name = "black" version = "23.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click" }, { name = "mypy-extensions" }, { name = "packaging" }, { name = "pathspec" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "platformdirs", version = "4.9.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "platformdirs" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ef/21/c2d38c7c98a089fd0f7e1a8be16c07f141ed57339b3082737de90db0ca59/black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05", size = 615416, upload-time = "2023-11-08T05:41:30.844Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/75/3a/e165fdb926e88acfface56a3a4267b20cc08015a141d75247d4f00c62509/black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911", size = 1559813, upload-time = "2023-11-08T05:47:43.258Z" }, - { url = "https://files.pythonhosted.org/packages/b9/7d/527c9ae32ef45c3828daf5854dcffcb324da77a37ee2d379ef79d24612ee/black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f", size = 1400610, upload-time = "2023-11-08T05:46:22.876Z" }, - { url = "https://files.pythonhosted.org/packages/75/1a/d0cfb2ae52ebfe7eeeb4b23090bff5ad9e071015c0373da9790f0e4a790b/black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394", size = 1704149, upload-time = "2023-11-08T05:43:45.403Z" }, - { url = "https://files.pythonhosted.org/packages/ce/59/b0c04cd9ddccb19660ba92c6ebb559face8533b12f04003b912c5c38f5db/black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f", size = 1331495, upload-time = "2023-11-08T05:44:14.356Z" }, { url = "https://files.pythonhosted.org/packages/3b/d8/ea841502c79d85675e56c40d77de59aae44e311f17b463815d6a9659608c/black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479", size = 1540054, upload-time = "2023-11-08T05:48:25.366Z" }, { url = "https://files.pythonhosted.org/packages/4e/09/75c374a20c458230ed8288d1e68ba38ecf508e948b8bf8980e8b0fd4c3b1/black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244", size = 1384800, upload-time = "2023-11-08T05:47:05.858Z" }, { url = "https://files.pythonhosted.org/packages/46/0a/964b242c01b8dbadec60afd2f1d3e08ad574315d34a33a692e96f121a32b/black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221", size = 1683129, upload-time = "2023-11-08T05:44:44.873Z" }, { url = "https://files.pythonhosted.org/packages/37/0b/2cf6d012a3cdb3f76d5c4e0c311b39f311a265d7dda315800ae34fb639c6/black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5", size = 1339007, upload-time = "2023-11-08T05:45:18.414Z" }, - { url = "https://files.pythonhosted.org/packages/ec/ba/c10c1f4048bc9eb26f68b230144e5f18f3b8cf6223738ceb14aabd3ec13b/black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055", size = 1559453, upload-time = "2023-11-08T05:51:01.773Z" }, - { url = "https://files.pythonhosted.org/packages/c0/54/8b5090ef893cabfc6c261625e944aa03669639f52f2ee7e2e25273be32e5/black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4", size = 1400058, upload-time = "2023-11-08T05:50:53.804Z" }, - { url = "https://files.pythonhosted.org/packages/42/8d/b47852614eca99e1178c7598f033fffc8e5a4687549b749216ebe0f24b6f/black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06", size = 1701974, upload-time = "2023-11-08T05:44:14.926Z" }, - { url = "https://files.pythonhosted.org/packages/9a/14/5aabe44a3f8058f02d595a68755150e2cda89103a1f73e7406fb730887dd/black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07", size = 1331013, upload-time = "2023-11-08T05:45:36.45Z" }, { url = "https://files.pythonhosted.org/packages/be/fb/8a670d2a246a351d7662e785d85a636c1c60b5800d175421cdfcb2a59b1d/black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e", size = 191996, upload-time = "2023-11-08T05:41:28.288Z" }, ] [[package]] name = "boto3" -version = "1.42.70" +version = "1.42.71" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/7c/d7a533916d1afc9e17f8594203a85799d42f7c5751464fbdb25ead8db9d2/boto3-1.42.70.tar.gz", hash = "sha256:d060b0d83d2832e403671b9a895e73c3b025df8bb5896d89e401b0678705aac4", size = 112808, upload-time = "2026-03-17T19:43:22.445Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/39/774ff22347856ebbe9da350045ad5851aa0524ee6e4832fdc98b27981801/boto3-1.42.71.tar.gz", hash = "sha256:500edd2699a3f479053bbfb407b06c231d1ff1e574f7c90d269d605a6a1f8160", size = 112773, upload-time = "2026-03-18T19:44:37.551Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/a1/128e3676fb9b4fd965a93554e5e07045975ee6bd6e9fdb536cdffa32e99e/boto3-1.42.70-py3-none-any.whl", hash = "sha256:18a108c4d5df89a200b3949de0d39c0879b100c455e3229ea38275dd392db0f4", size = 140554, upload-time = "2026-03-17T19:43:20.406Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b6/b0b93090cfc3fdbdb21a0b18961508678a2b36a42e2b3a90994ac34e102c/boto3-1.42.71-py3-none-any.whl", hash = "sha256:a89fae01c4bc948671e99440ddc0f10bc73cc72d83218656057f730df0898eab", size = 140553, upload-time = "2026-03-18T19:44:35.317Z" }, ] [[package]] name = "boto3-stubs" -version = "1.42.70" +version = "1.42.71" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore-stubs" }, { name = "types-s3transfer" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1b/df/58083ab60ea3dd57d2755e260b4bef4d5a121812e7627a93d4356be5e519/boto3_stubs-1.42.70.tar.gz", hash = "sha256:9e36a01c08169906be846105c14e2dd8907bef5a6b04151dffaab5aff13895b9", size = 101355, upload-time = "2026-03-17T20:05:24.247Z" } +sdist = { url = "https://files.pythonhosted.org/packages/99/0c/e0dee45b6f8fd1afd192ad0c68d9b03c2ddee99171d173cb4274df304623/boto3_stubs-1.42.71.tar.gz", hash = "sha256:7ece30dbfe719556e84d88872833d34e2ea81e8fa5dfbf581e6eec80fbf400e3", size = 101368, upload-time = "2026-03-18T19:54:12.629Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/cb/95e477bf3a20f292c8768c33204b882ec636c00d3d217f481961f5afa700/boto3_stubs-1.42.70-py3-none-any.whl", hash = "sha256:823dc17af74427a2220f9da3007285145a21b44bbf149af7ed01eb7697fd5cac", size = 70011, upload-time = "2026-03-17T20:05:16.998Z" }, + { url = "https://files.pythonhosted.org/packages/45/fc/d488a1a1b8473a533c3962227385f4735a75a570baea0f31c3fd5f2d144d/boto3_stubs-1.42.71-py3-none-any.whl", hash = "sha256:6cc9f1e168abf42b66dd31a2d6abaf5b4ac898ea3e122aaba6caa570b416d641", size = 70011, upload-time = "2026-03-18T19:54:08.863Z" }, ] [package.optional-dependencies] @@ -322,17 +295,16 @@ stepfunctions = [ [[package]] name = "botocore" -version = "1.42.70" +version = "1.42.71" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, - { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/54/b80e1fcee4f732e0e9314bbb8679be9d5690caa1566c4a4cd14e9724d2dd/botocore-1.42.70.tar.gz", hash = "sha256:9ee17553b7febd1a0c1253b3b62ab5d79607eb6163c8fb943470a8893c31d4fa", size = 14997068, upload-time = "2026-03-17T19:43:10.678Z" } +sdist = { url = "https://files.pythonhosted.org/packages/37/65/a76ced7e1c7f61880ec474e301cb63c27fd47c09ae0b7e4ccaa3cd3b04c6/botocore-1.42.71.tar.gz", hash = "sha256:6b3796c76edeb78afee325a54e23508bbd57624faea1e4aeb8f6e9c1e1e79a0f", size = 14998263, upload-time = "2026-03-18T19:44:25.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/51/08f32aea872253173f513ba68122f4300966290677c8e59887b4ffd5d957/botocore-1.42.70-py3-none-any.whl", hash = "sha256:54ed9d25f05f810efd22b0dfda0bb9178df3ad8952b2e4359e05156c9321bd3c", size = 14671393, upload-time = "2026-03-17T19:43:06.777Z" }, + { url = "https://files.pythonhosted.org/packages/86/b3/b970b62963b2391d10cd29402d3338bf49730e083aa9b2a688c8bf76af08/botocore-1.42.71-py3-none-any.whl", hash = "sha256:e6b7c611eeacbfa6a5a08cd56889b7a63eced48e99f8db9b270eeaf2c0b62796", size = 14671820, upload-time = "2026-03-18T19:44:20.997Z" }, ] [[package]] @@ -362,10 +334,8 @@ version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "os_name == 'nt'" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10.2'" }, { name = "packaging" }, { name = "pyproject-hooks" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/18/94eaffda7b329535d91f00fe605ab1f1e5cd68b2074d03f255c7d250687d/build-1.4.0.tar.gz", hash = "sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936", size = 50054, upload-time = "2026-01-08T16:41:47.696Z" } wheels = [ @@ -377,12 +347,10 @@ name = "bump-my-version" version = "1.2.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click" }, { name = "httpx" }, { name = "pydantic" }, - { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pydantic-settings", version = "2.13.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic-settings" }, { name = "questionary" }, { name = "rich" }, { name = "rich-click" }, @@ -408,23 +376,10 @@ name = "cffi" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser", version = "2.23", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' and implementation_name != 'PyPy'" }, - { name = "pycparser", version = "3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and implementation_name != 'PyPy'" }, + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" }, - { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, - { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, - { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, - { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, - { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, - { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, - { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, - { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, - { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, - { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, @@ -484,18 +439,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, - { url = "https://files.pythonhosted.org/packages/c0/cc/08ed5a43f2996a16b462f64a7055c6e962803534924b9b2f1371d8c00b7b/cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf", size = 184288, upload-time = "2025-09-08T23:23:48.404Z" }, - { url = "https://files.pythonhosted.org/packages/3d/de/38d9726324e127f727b4ecc376bc85e505bfe61ef130eaf3f290c6847dd4/cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7", size = 180509, upload-time = "2025-09-08T23:23:49.73Z" }, - { url = "https://files.pythonhosted.org/packages/9b/13/c92e36358fbcc39cf0962e83223c9522154ee8630e1df7c0b3a39a8124e2/cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", size = 208813, upload-time = "2025-09-08T23:23:51.263Z" }, - { url = "https://files.pythonhosted.org/packages/15/12/a7a79bd0df4c3bff744b2d7e52cc1b68d5e7e427b384252c42366dc1ecbc/cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", size = 216498, upload-time = "2025-09-08T23:23:52.494Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ad/5c51c1c7600bdd7ed9a24a203ec255dccdd0ebf4527f7b922a0bde2fb6ed/cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534", size = 203243, upload-time = "2025-09-08T23:23:53.836Z" }, - { url = "https://files.pythonhosted.org/packages/32/f2/81b63e288295928739d715d00952c8c6034cb6c6a516b17d37e0c8be5600/cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f", size = 203158, upload-time = "2025-09-08T23:23:55.169Z" }, - { url = "https://files.pythonhosted.org/packages/1f/74/cc4096ce66f5939042ae094e2e96f53426a979864aa1f96a621ad128be27/cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", size = 216548, upload-time = "2025-09-08T23:23:56.506Z" }, - { url = "https://files.pythonhosted.org/packages/e8/be/f6424d1dc46b1091ffcc8964fa7c0ab0cd36839dd2761b49c90481a6ba1b/cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", size = 218897, upload-time = "2025-09-08T23:23:57.825Z" }, - { url = "https://files.pythonhosted.org/packages/f7/e0/dda537c2309817edf60109e39265f24f24aa7f050767e22c98c53fe7f48b/cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", size = 211249, upload-time = "2025-09-08T23:23:59.139Z" }, - { url = "https://files.pythonhosted.org/packages/2b/e7/7c769804eb75e4c4b35e658dba01de1640a351a9653c3d49ca89d16ccc91/cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322", size = 218041, upload-time = "2025-09-08T23:24:00.496Z" }, - { url = "https://files.pythonhosted.org/packages/aa/d9/6218d78f920dcd7507fc16a766b5ef8f3b913cc7aa938e7fc80b9978d089/cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a", size = 172138, upload-time = "2025-09-08T23:24:01.7Z" }, - { url = "https://files.pythonhosted.org/packages/54/8f/a1e836f82d8e32a97e6b29cc8f641779181ac7363734f12df27db803ebda/cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9", size = 182794, upload-time = "2025-09-08T23:24:02.943Z" }, ] [[package]] @@ -504,22 +447,6 @@ version = "3.4.6" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7b/60/e3bec1881450851b087e301bedc3daa9377a4d45f1c26aa90b0b235e38aa/charset_normalizer-3.4.6.tar.gz", hash = "sha256:1ae6b62897110aa7c79ea2f5dd38d1abca6db663687c0b1ad9aed6f6bae3d9d6", size = 143363, upload-time = "2026-03-15T18:53:25.478Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/8c/2c56124c6dc53a774d435f985b5973bc592f42d437be58c0c92d65ae7296/charset_normalizer-3.4.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2e1d8ca8611099001949d1cdfaefc510cf0f212484fe7c565f735b68c78c3c95", size = 298751, upload-time = "2026-03-15T18:50:00.003Z" }, - { url = "https://files.pythonhosted.org/packages/86/2a/2a7db6b314b966a3bcad8c731c0719c60b931b931de7ae9f34b2839289ee/charset_normalizer-3.4.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e25369dc110d58ddf29b949377a93e0716d72a24f62bad72b2b39f155949c1fd", size = 200027, upload-time = "2026-03-15T18:50:01.702Z" }, - { url = "https://files.pythonhosted.org/packages/68/f2/0fe775c74ae25e2a3b07b01538fc162737b3e3f795bada3bc26f4d4d495c/charset_normalizer-3.4.6-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:259695e2ccc253feb2a016303543d691825e920917e31f894ca1a687982b1de4", size = 220741, upload-time = "2026-03-15T18:50:03.194Z" }, - { url = "https://files.pythonhosted.org/packages/10/98/8085596e41f00b27dd6aa1e68413d1ddda7e605f34dd546833c61fddd709/charset_normalizer-3.4.6-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dda86aba335c902b6149a02a55b38e96287157e609200811837678214ba2b1db", size = 215802, upload-time = "2026-03-15T18:50:05.859Z" }, - { url = "https://files.pythonhosted.org/packages/fd/ce/865e4e09b041bad659d682bbd98b47fb490b8e124f9398c9448065f64fee/charset_normalizer-3.4.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51fb3c322c81d20567019778cb5a4a6f2dc1c200b886bc0d636238e364848c89", size = 207908, upload-time = "2026-03-15T18:50:07.676Z" }, - { url = "https://files.pythonhosted.org/packages/a8/54/8c757f1f7349262898c2f169e0d562b39dcb977503f18fdf0814e923db78/charset_normalizer-3.4.6-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:4482481cb0572180b6fd976a4d5c72a30263e98564da68b86ec91f0fe35e8565", size = 194357, upload-time = "2026-03-15T18:50:09.327Z" }, - { url = "https://files.pythonhosted.org/packages/6f/29/e88f2fac9218907fc7a70722b393d1bbe8334c61fe9c46640dba349b6e66/charset_normalizer-3.4.6-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39f5068d35621da2881271e5c3205125cc456f54e9030d3f723288c873a71bf9", size = 205610, upload-time = "2026-03-15T18:50:10.732Z" }, - { url = "https://files.pythonhosted.org/packages/4c/c5/21d7bb0cb415287178450171d130bed9d664211fdd59731ed2c34267b07d/charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8bea55c4eef25b0b19a0337dc4e3f9a15b00d569c77211fa8cde38684f234fb7", size = 203512, upload-time = "2026-03-15T18:50:12.535Z" }, - { url = "https://files.pythonhosted.org/packages/a4/be/ce52f3c7fdb35cc987ad38a53ebcef52eec498f4fb6c66ecfe62cfe57ba2/charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f0cdaecd4c953bfae0b6bb64910aaaca5a424ad9c72d85cb88417bb9814f7550", size = 195398, upload-time = "2026-03-15T18:50:14.236Z" }, - { url = "https://files.pythonhosted.org/packages/81/a0/3ab5dd39d4859a3555e5dadfc8a9fa7f8352f8c183d1a65c90264517da0e/charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:150b8ce8e830eb7ccb029ec9ca36022f756986aaaa7956aad6d9ec90089338c0", size = 221772, upload-time = "2026-03-15T18:50:15.581Z" }, - { url = "https://files.pythonhosted.org/packages/04/6e/6a4e41a97ba6b2fa87f849c41e4d229449a586be85053c4d90135fe82d26/charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:e68c14b04827dd76dcbd1aeea9e604e3e4b78322d8faf2f8132c7138efa340a8", size = 205759, upload-time = "2026-03-15T18:50:17.047Z" }, - { url = "https://files.pythonhosted.org/packages/db/3b/34a712a5ee64a6957bf355b01dc17b12de457638d436fdb05d01e463cd1c/charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:3778fd7d7cd04ae8f54651f4a7a0bd6e39a0cf20f801720a4c21d80e9b7ad6b0", size = 216938, upload-time = "2026-03-15T18:50:18.44Z" }, - { url = "https://files.pythonhosted.org/packages/cb/05/5bd1e12da9ab18790af05c61aafd01a60f489778179b621ac2a305243c62/charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:dad6e0f2e481fffdcf776d10ebee25e0ef89f16d691f1e5dee4b586375fdc64b", size = 210138, upload-time = "2026-03-15T18:50:19.852Z" }, - { url = "https://files.pythonhosted.org/packages/bd/8e/3cb9e2d998ff6b21c0a1860343cb7b83eba9cdb66b91410e18fc4969d6ab/charset_normalizer-3.4.6-cp310-cp310-win32.whl", hash = "sha256:74a2e659c7ecbc73562e2a15e05039f1e22c75b7c7618b4b574a3ea9118d1557", size = 144137, upload-time = "2026-03-15T18:50:21.505Z" }, - { url = "https://files.pythonhosted.org/packages/d8/8f/78f5489ffadb0db3eb7aff53d31c24531d33eb545f0c6f6567c25f49a5ff/charset_normalizer-3.4.6-cp310-cp310-win_amd64.whl", hash = "sha256:aa9cccf4a44b9b62d8ba8b4dd06c649ba683e4bf04eea606d2e94cfc2d6ff4d6", size = 154244, upload-time = "2026-03-15T18:50:22.81Z" }, - { url = "https://files.pythonhosted.org/packages/e4/74/e472659dffb0cadb2f411282d2d76c60da1fc94076d7fffed4ae8a93ec01/charset_normalizer-3.4.6-cp310-cp310-win_arm64.whl", hash = "sha256:e985a16ff513596f217cee86c21371b8cd011c0f6f056d0920aa2d926c544058", size = 143312, upload-time = "2026-03-15T18:50:24.074Z" }, { url = "https://files.pythonhosted.org/packages/62/28/ff6f234e628a2de61c458be2779cb182bc03f6eec12200d4a525bbfc9741/charset_normalizer-3.4.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:82060f995ab5003a2d6e0f4ad29065b7672b6593c8c63559beefe5b443242c3e", size = 293582, upload-time = "2026-03-15T18:50:25.454Z" }, { url = "https://files.pythonhosted.org/packages/1c/b7/b1a117e5385cbdb3205f6055403c2a2a220c5ea80b8716c324eaf75c5c95/charset_normalizer-3.4.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60c74963d8350241a79cb8feea80e54d518f72c26db618862a8f53e5023deaf9", size = 197240, upload-time = "2026-03-15T18:50:27.196Z" }, { url = "https://files.pythonhosted.org/packages/a1/5f/2574f0f09f3c3bc1b2f992e20bce6546cb1f17e111c5be07308dc5427956/charset_normalizer-3.4.6-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6e4333fb15c83f7d1482a76d45a0818897b3d33f00efd215528ff7c51b8e35d", size = 217363, upload-time = "2026-03-15T18:50:28.601Z" }, @@ -600,49 +527,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/35/1a/05dacadb0978da72ee287b0143097db12f2e7e8d3ffc4647da07a383b0b7/charset_normalizer-3.4.6-cp314-cp314t-win32.whl", hash = "sha256:2a24157fa36980478dd1770b585c0f30d19e18f4fb0c47c13aa568f871718579", size = 155379, upload-time = "2026-03-15T18:52:27.05Z" }, { url = "https://files.pythonhosted.org/packages/5d/7a/d269d834cb3a76291651256f3b9a5945e81d0a49ab9f4a498964e83c0416/charset_normalizer-3.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:cd5e2801c89992ed8c0a3f0293ae83c159a60d9a5d685005383ef4caca77f2c4", size = 169043, upload-time = "2026-03-15T18:52:28.502Z" }, { url = "https://files.pythonhosted.org/packages/23/06/28b29fba521a37a8932c6a84192175c34d49f84a6d4773fa63d05f9aff22/charset_normalizer-3.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:47955475ac79cc504ef2704b192364e51d0d473ad452caedd0002605f780101c", size = 148523, upload-time = "2026-03-15T18:52:29.956Z" }, - { url = "https://files.pythonhosted.org/packages/41/85/580dbaa12ab31041ed7df59f0bebc8893514fc21da6c05c3a1c1707d118f/charset_normalizer-3.4.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31215157227939b4fb3d740cd23fe27be0439afef67b785a1eb78a3ae69cba9e", size = 298620, upload-time = "2026-03-15T18:52:57.332Z" }, - { url = "https://files.pythonhosted.org/packages/67/2c/1e55af3a5e2f52e44396d5c5b731e0ae4f3bb92915ff09a610fb2f4497eb/charset_normalizer-3.4.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecbbd45615a6885fe3240eb9db73b9e62518b611850fdf8ab08bd56de7ad2b17", size = 200106, upload-time = "2026-03-15T18:52:59.2Z" }, - { url = "https://files.pythonhosted.org/packages/10/42/0f2f51a1d16caa45fbf384fd337d4242df1a5b313babee211381d2d39a96/charset_normalizer-3.4.6-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c45a03a4c69820a399f1dda9e1d8fbf3562eda46e7720458180302021b08f778", size = 220539, upload-time = "2026-03-15T18:53:01.019Z" }, - { url = "https://files.pythonhosted.org/packages/1c/0c/4e10996c740eec0f4ae8afbbbfa25f66e8479c4b6ee9cff1ca366a4f6c04/charset_normalizer-3.4.6-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e8aeb10fcbe92767f0fa69ad5a72deca50d0dca07fbde97848997d778a50c9fe", size = 215821, upload-time = "2026-03-15T18:53:02.621Z" }, - { url = "https://files.pythonhosted.org/packages/46/73/205ae7644ebb581a7c6fa9c3751e283606e145f0e6f066003c66aafc9973/charset_normalizer-3.4.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54fae94be3d75f3e573c9a1b5402dc593de19377013c9a0e4285e3d402dd3a2a", size = 207917, upload-time = "2026-03-15T18:53:04.413Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ca/18f7dcf19afdab8097aeb2feb8b3809bb4b6ee356cb720abf5263d79406a/charset_normalizer-3.4.6-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:2f7fdd9b6e6c529d6a2501a2d36b240109e78a8ceaef5687cfcfa2bbe671d297", size = 194513, upload-time = "2026-03-15T18:53:06.025Z" }, - { url = "https://files.pythonhosted.org/packages/e4/6a/e7e3e204c8d79832a091e00b24595af1d5d9800d37dc1f67a6b264cc99a6/charset_normalizer-3.4.6-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1d02209e06550bdaef34af58e041ad71b88e624f5d825519da3a3308e22687", size = 205612, upload-time = "2026-03-15T18:53:07.494Z" }, - { url = "https://files.pythonhosted.org/packages/ff/ae/2169ebcea2851c5460c7a21993a0f87028be3c3e60899cb36251e1135cf5/charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8bc5f0687d796c05b1e28ab0d38a50e6309906ee09375dd3aff6a9c09dd6e8f4", size = 203519, upload-time = "2026-03-15T18:53:09.048Z" }, - { url = "https://files.pythonhosted.org/packages/43/a0/6a49a925b9c225fe35dffeac5c76f68996b814c637e9d7213718f96be109/charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ee4ec14bc1680d6b0afab9aea2ef27e26d2024f18b24a2d7155a52b60da7e833", size = 195411, upload-time = "2026-03-15T18:53:10.542Z" }, - { url = "https://files.pythonhosted.org/packages/47/f7/a26b0a18e52b1a0f11f53c2c400ed062f386ac227a64ae4be4c5a64699be/charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d1a2ee9c1499fc8f86f4521f27a973c914b211ffa87322f4ee33bb35392da2c5", size = 221653, upload-time = "2026-03-15T18:53:12.394Z" }, - { url = "https://files.pythonhosted.org/packages/a7/3a/ed1d3b5bb55e3634bd5c31cedbe4fff79d0e5b8d9a062f663a757a07760d/charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:48696db7f18afb80a068821504296eb0787d9ce239b91ca15059d1d3eaacf13b", size = 205650, upload-time = "2026-03-15T18:53:13.934Z" }, - { url = "https://files.pythonhosted.org/packages/b1/27/c75819eea5ceeefc49bae329327bb91e81adc346e2a9873d9fdb9e77cde6/charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4f41da960b196ea355357285ad1316a00099f22d0929fe168343b99b254729c9", size = 216919, upload-time = "2026-03-15T18:53:15.44Z" }, - { url = "https://files.pythonhosted.org/packages/0f/42/6e91bf8b15f67b7c957091138a36057a083e60703cc27848d5e36ca1eb03/charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:802168e03fba8bbc5ce0d866d589e4b1ca751d06edee69f7f3a19c5a9fe6b597", size = 210101, upload-time = "2026-03-15T18:53:17.045Z" }, - { url = "https://files.pythonhosted.org/packages/99/ff/101af2605e66a7ee59961d7f9e1060df7c92e8ea54208a02ab881422c24e/charset_normalizer-3.4.6-cp39-cp39-win32.whl", hash = "sha256:8761ac29b6c81574724322a554605608a9960769ea83d2c73e396f3df896ad54", size = 144136, upload-time = "2026-03-15T18:53:19.152Z" }, - { url = "https://files.pythonhosted.org/packages/1d/da/de5942dfbf21f28c19e9202267dabf7bc73f195465d020a3a60054520cc5/charset_normalizer-3.4.6-cp39-cp39-win_amd64.whl", hash = "sha256:1cf0a70018692f85172348fe06d3a4b63f94ecb055e13a00c644d368eb82e5b8", size = 154210, upload-time = "2026-03-15T18:53:20.576Z" }, - { url = "https://files.pythonhosted.org/packages/06/df/1b780a25b86d22b1d736f6ac883afd38ffdf30ddc18e5dc0e82211f493f1/charset_normalizer-3.4.6-cp39-cp39-win_arm64.whl", hash = "sha256:3516bbb8d42169de9e61b8520cbeeeb716f12f4ecfe3fd30a9919aa16c806ca8", size = 143225, upload-time = "2026-03-15T18:53:22.072Z" }, { url = "https://files.pythonhosted.org/packages/2a/68/687187c7e26cb24ccbd88e5069f5ef00eba804d36dde11d99aad0838ab45/charset_normalizer-3.4.6-py3-none-any.whl", hash = "sha256:947cf925bc916d90adba35a64c82aace04fa39b46b52d4630ece166655905a69", size = 61455, upload-time = "2026-03-15T18:53:23.833Z" }, ] -[[package]] -name = "click" -version = "8.1.8" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, -] - [[package]] name = "click" version = "8.3.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } wheels = [ @@ -658,148 +551,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] -[[package]] -name = "coverage" -version = "7.10.7" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/51/26/d22c300112504f5f9a9fd2297ce33c35f3d353e4aeb987c8419453b2a7c2/coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239", size = 827704, upload-time = "2025-09-21T20:03:56.815Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/6c/3a3f7a46888e69d18abe3ccc6fe4cb16cccb1e6a2f99698931dafca489e6/coverage-7.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a", size = 217987, upload-time = "2025-09-21T20:00:57.218Z" }, - { url = "https://files.pythonhosted.org/packages/03/94/952d30f180b1a916c11a56f5c22d3535e943aa22430e9e3322447e520e1c/coverage-7.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5", size = 218388, upload-time = "2025-09-21T20:01:00.081Z" }, - { url = "https://files.pythonhosted.org/packages/50/2b/9e0cf8ded1e114bcd8b2fd42792b57f1c4e9e4ea1824cde2af93a67305be/coverage-7.10.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17", size = 245148, upload-time = "2025-09-21T20:01:01.768Z" }, - { url = "https://files.pythonhosted.org/packages/19/20/d0384ac06a6f908783d9b6aa6135e41b093971499ec488e47279f5b846e6/coverage-7.10.7-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b", size = 246958, upload-time = "2025-09-21T20:01:03.355Z" }, - { url = "https://files.pythonhosted.org/packages/60/83/5c283cff3d41285f8eab897651585db908a909c572bdc014bcfaf8a8b6ae/coverage-7.10.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87", size = 248819, upload-time = "2025-09-21T20:01:04.968Z" }, - { url = "https://files.pythonhosted.org/packages/60/22/02eb98fdc5ff79f423e990d877693e5310ae1eab6cb20ae0b0b9ac45b23b/coverage-7.10.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e", size = 245754, upload-time = "2025-09-21T20:01:06.321Z" }, - { url = "https://files.pythonhosted.org/packages/b4/bc/25c83bcf3ad141b32cd7dc45485ef3c01a776ca3aa8ef0a93e77e8b5bc43/coverage-7.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e", size = 246860, upload-time = "2025-09-21T20:01:07.605Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b7/95574702888b58c0928a6e982038c596f9c34d52c5e5107f1eef729399b5/coverage-7.10.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df", size = 244877, upload-time = "2025-09-21T20:01:08.829Z" }, - { url = "https://files.pythonhosted.org/packages/47/b6/40095c185f235e085df0e0b158f6bd68cc6e1d80ba6c7721dc81d97ec318/coverage-7.10.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0", size = 245108, upload-time = "2025-09-21T20:01:10.527Z" }, - { url = "https://files.pythonhosted.org/packages/c8/50/4aea0556da7a4b93ec9168420d170b55e2eb50ae21b25062513d020c6861/coverage-7.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13", size = 245752, upload-time = "2025-09-21T20:01:11.857Z" }, - { url = "https://files.pythonhosted.org/packages/6a/28/ea1a84a60828177ae3b100cb6723838523369a44ec5742313ed7db3da160/coverage-7.10.7-cp310-cp310-win32.whl", hash = "sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b", size = 220497, upload-time = "2025-09-21T20:01:13.459Z" }, - { url = "https://files.pythonhosted.org/packages/fc/1a/a81d46bbeb3c3fd97b9602ebaa411e076219a150489bcc2c025f151bd52d/coverage-7.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807", size = 221392, upload-time = "2025-09-21T20:01:14.722Z" }, - { url = "https://files.pythonhosted.org/packages/d2/5d/c1a17867b0456f2e9ce2d8d4708a4c3a089947d0bec9c66cdf60c9e7739f/coverage-7.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59", size = 218102, upload-time = "2025-09-21T20:01:16.089Z" }, - { url = "https://files.pythonhosted.org/packages/54/f0/514dcf4b4e3698b9a9077f084429681bf3aad2b4a72578f89d7f643eb506/coverage-7.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a", size = 218505, upload-time = "2025-09-21T20:01:17.788Z" }, - { url = "https://files.pythonhosted.org/packages/20/f6/9626b81d17e2a4b25c63ac1b425ff307ecdeef03d67c9a147673ae40dc36/coverage-7.10.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699", size = 248898, upload-time = "2025-09-21T20:01:19.488Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ef/bd8e719c2f7417ba03239052e099b76ea1130ac0cbb183ee1fcaa58aaff3/coverage-7.10.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d", size = 250831, upload-time = "2025-09-21T20:01:20.817Z" }, - { url = "https://files.pythonhosted.org/packages/a5/b6/bf054de41ec948b151ae2b79a55c107f5760979538f5fb80c195f2517718/coverage-7.10.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e", size = 252937, upload-time = "2025-09-21T20:01:22.171Z" }, - { url = "https://files.pythonhosted.org/packages/0f/e5/3860756aa6f9318227443c6ce4ed7bf9e70bb7f1447a0353f45ac5c7974b/coverage-7.10.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23", size = 249021, upload-time = "2025-09-21T20:01:23.907Z" }, - { url = "https://files.pythonhosted.org/packages/26/0f/bd08bd042854f7fd07b45808927ebcce99a7ed0f2f412d11629883517ac2/coverage-7.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab", size = 250626, upload-time = "2025-09-21T20:01:25.721Z" }, - { url = "https://files.pythonhosted.org/packages/8e/a7/4777b14de4abcc2e80c6b1d430f5d51eb18ed1d75fca56cbce5f2db9b36e/coverage-7.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82", size = 248682, upload-time = "2025-09-21T20:01:27.105Z" }, - { url = "https://files.pythonhosted.org/packages/34/72/17d082b00b53cd45679bad682fac058b87f011fd8b9fe31d77f5f8d3a4e4/coverage-7.10.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2", size = 248402, upload-time = "2025-09-21T20:01:28.629Z" }, - { url = "https://files.pythonhosted.org/packages/81/7a/92367572eb5bdd6a84bfa278cc7e97db192f9f45b28c94a9ca1a921c3577/coverage-7.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61", size = 249320, upload-time = "2025-09-21T20:01:30.004Z" }, - { url = "https://files.pythonhosted.org/packages/2f/88/a23cc185f6a805dfc4fdf14a94016835eeb85e22ac3a0e66d5e89acd6462/coverage-7.10.7-cp311-cp311-win32.whl", hash = "sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14", size = 220536, upload-time = "2025-09-21T20:01:32.184Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ef/0b510a399dfca17cec7bc2f05ad8bd78cf55f15c8bc9a73ab20c5c913c2e/coverage-7.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2", size = 221425, upload-time = "2025-09-21T20:01:33.557Z" }, - { url = "https://files.pythonhosted.org/packages/51/7f/023657f301a276e4ba1850f82749bc136f5a7e8768060c2e5d9744a22951/coverage-7.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a", size = 220103, upload-time = "2025-09-21T20:01:34.929Z" }, - { url = "https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417", size = 218290, upload-time = "2025-09-21T20:01:36.455Z" }, - { url = "https://files.pythonhosted.org/packages/37/66/593f9be12fc19fb36711f19a5371af79a718537204d16ea1d36f16bd78d2/coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973", size = 218515, upload-time = "2025-09-21T20:01:37.982Z" }, - { url = "https://files.pythonhosted.org/packages/66/80/4c49f7ae09cafdacc73fbc30949ffe77359635c168f4e9ff33c9ebb07838/coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c", size = 250020, upload-time = "2025-09-21T20:01:39.617Z" }, - { url = "https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7", size = 252769, upload-time = "2025-09-21T20:01:41.341Z" }, - { url = "https://files.pythonhosted.org/packages/98/2e/2dda59afd6103b342e096f246ebc5f87a3363b5412609946c120f4e7750d/coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6", size = 253901, upload-time = "2025-09-21T20:01:43.042Z" }, - { url = "https://files.pythonhosted.org/packages/53/dc/8d8119c9051d50f3119bb4a75f29f1e4a6ab9415cd1fa8bf22fcc3fb3b5f/coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59", size = 250413, upload-time = "2025-09-21T20:01:44.469Z" }, - { url = "https://files.pythonhosted.org/packages/98/b3/edaff9c5d79ee4d4b6d3fe046f2b1d799850425695b789d491a64225d493/coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b", size = 251820, upload-time = "2025-09-21T20:01:45.915Z" }, - { url = "https://files.pythonhosted.org/packages/11/25/9a0728564bb05863f7e513e5a594fe5ffef091b325437f5430e8cfb0d530/coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a", size = 249941, upload-time = "2025-09-21T20:01:47.296Z" }, - { url = "https://files.pythonhosted.org/packages/e0/fd/ca2650443bfbef5b0e74373aac4df67b08180d2f184b482c41499668e258/coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb", size = 249519, upload-time = "2025-09-21T20:01:48.73Z" }, - { url = "https://files.pythonhosted.org/packages/24/79/f692f125fb4299b6f963b0745124998ebb8e73ecdfce4ceceb06a8c6bec5/coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1", size = 251375, upload-time = "2025-09-21T20:01:50.529Z" }, - { url = "https://files.pythonhosted.org/packages/5e/75/61b9bbd6c7d24d896bfeec57acba78e0f8deac68e6baf2d4804f7aae1f88/coverage-7.10.7-cp312-cp312-win32.whl", hash = "sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256", size = 220699, upload-time = "2025-09-21T20:01:51.941Z" }, - { url = "https://files.pythonhosted.org/packages/ca/f3/3bf7905288b45b075918d372498f1cf845b5b579b723c8fd17168018d5f5/coverage-7.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba", size = 221512, upload-time = "2025-09-21T20:01:53.481Z" }, - { url = "https://files.pythonhosted.org/packages/5c/44/3e32dbe933979d05cf2dac5e697c8599cfe038aaf51223ab901e208d5a62/coverage-7.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf", size = 220147, upload-time = "2025-09-21T20:01:55.2Z" }, - { url = "https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d", size = 218320, upload-time = "2025-09-21T20:01:56.629Z" }, - { url = "https://files.pythonhosted.org/packages/72/4f/732fff31c119bb73b35236dd333030f32c4bfe909f445b423e6c7594f9a2/coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b", size = 218575, upload-time = "2025-09-21T20:01:58.203Z" }, - { url = "https://files.pythonhosted.org/packages/87/02/ae7e0af4b674be47566707777db1aa375474f02a1d64b9323e5813a6cdd5/coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e", size = 249568, upload-time = "2025-09-21T20:01:59.748Z" }, - { url = "https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b", size = 252174, upload-time = "2025-09-21T20:02:01.192Z" }, - { url = "https://files.pythonhosted.org/packages/b1/20/b6ea4f69bbb52dac0aebd62157ba6a9dddbfe664f5af8122dac296c3ee15/coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49", size = 253447, upload-time = "2025-09-21T20:02:02.701Z" }, - { url = "https://files.pythonhosted.org/packages/f9/28/4831523ba483a7f90f7b259d2018fef02cb4d5b90bc7c1505d6e5a84883c/coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911", size = 249779, upload-time = "2025-09-21T20:02:04.185Z" }, - { url = "https://files.pythonhosted.org/packages/a7/9f/4331142bc98c10ca6436d2d620c3e165f31e6c58d43479985afce6f3191c/coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0", size = 251604, upload-time = "2025-09-21T20:02:06.034Z" }, - { url = "https://files.pythonhosted.org/packages/ce/60/bda83b96602036b77ecf34e6393a3836365481b69f7ed7079ab85048202b/coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f", size = 249497, upload-time = "2025-09-21T20:02:07.619Z" }, - { url = "https://files.pythonhosted.org/packages/5f/af/152633ff35b2af63977edd835d8e6430f0caef27d171edf2fc76c270ef31/coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c", size = 249350, upload-time = "2025-09-21T20:02:10.34Z" }, - { url = "https://files.pythonhosted.org/packages/9d/71/d92105d122bd21cebba877228990e1646d862e34a98bb3374d3fece5a794/coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f", size = 251111, upload-time = "2025-09-21T20:02:12.122Z" }, - { url = "https://files.pythonhosted.org/packages/a2/9e/9fdb08f4bf476c912f0c3ca292e019aab6712c93c9344a1653986c3fd305/coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698", size = 220746, upload-time = "2025-09-21T20:02:13.919Z" }, - { url = "https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843", size = 221541, upload-time = "2025-09-21T20:02:15.57Z" }, - { url = "https://files.pythonhosted.org/packages/14/3a/d720d7c989562a6e9a14b2c9f5f2876bdb38e9367126d118495b89c99c37/coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546", size = 220170, upload-time = "2025-09-21T20:02:17.395Z" }, - { url = "https://files.pythonhosted.org/packages/bb/22/e04514bf2a735d8b0add31d2b4ab636fc02370730787c576bb995390d2d5/coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c", size = 219029, upload-time = "2025-09-21T20:02:18.936Z" }, - { url = "https://files.pythonhosted.org/packages/11/0b/91128e099035ece15da3445d9015e4b4153a6059403452d324cbb0a575fa/coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15", size = 219259, upload-time = "2025-09-21T20:02:20.44Z" }, - { url = "https://files.pythonhosted.org/packages/8b/51/66420081e72801536a091a0c8f8c1f88a5c4bf7b9b1bdc6222c7afe6dc9b/coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4", size = 260592, upload-time = "2025-09-21T20:02:22.313Z" }, - { url = "https://files.pythonhosted.org/packages/5d/22/9b8d458c2881b22df3db5bb3e7369e63d527d986decb6c11a591ba2364f7/coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0", size = 262768, upload-time = "2025-09-21T20:02:24.287Z" }, - { url = "https://files.pythonhosted.org/packages/f7/08/16bee2c433e60913c610ea200b276e8eeef084b0d200bdcff69920bd5828/coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0", size = 264995, upload-time = "2025-09-21T20:02:26.133Z" }, - { url = "https://files.pythonhosted.org/packages/20/9d/e53eb9771d154859b084b90201e5221bca7674ba449a17c101a5031d4054/coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65", size = 259546, upload-time = "2025-09-21T20:02:27.716Z" }, - { url = "https://files.pythonhosted.org/packages/ad/b0/69bc7050f8d4e56a89fb550a1577d5d0d1db2278106f6f626464067b3817/coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541", size = 262544, upload-time = "2025-09-21T20:02:29.216Z" }, - { url = "https://files.pythonhosted.org/packages/ef/4b/2514b060dbd1bc0aaf23b852c14bb5818f244c664cb16517feff6bb3a5ab/coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6", size = 260308, upload-time = "2025-09-21T20:02:31.226Z" }, - { url = "https://files.pythonhosted.org/packages/54/78/7ba2175007c246d75e496f64c06e94122bdb914790a1285d627a918bd271/coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999", size = 258920, upload-time = "2025-09-21T20:02:32.823Z" }, - { url = "https://files.pythonhosted.org/packages/c0/b3/fac9f7abbc841409b9a410309d73bfa6cfb2e51c3fada738cb607ce174f8/coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2", size = 261434, upload-time = "2025-09-21T20:02:34.86Z" }, - { url = "https://files.pythonhosted.org/packages/ee/51/a03bec00d37faaa891b3ff7387192cef20f01604e5283a5fabc95346befa/coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a", size = 221403, upload-time = "2025-09-21T20:02:37.034Z" }, - { url = "https://files.pythonhosted.org/packages/53/22/3cf25d614e64bf6d8e59c7c669b20d6d940bb337bdee5900b9ca41c820bb/coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb", size = 222469, upload-time = "2025-09-21T20:02:39.011Z" }, - { url = "https://files.pythonhosted.org/packages/49/a1/00164f6d30d8a01c3c9c48418a7a5be394de5349b421b9ee019f380df2a0/coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb", size = 220731, upload-time = "2025-09-21T20:02:40.939Z" }, - { url = "https://files.pythonhosted.org/packages/23/9c/5844ab4ca6a4dd97a1850e030a15ec7d292b5c5cb93082979225126e35dd/coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520", size = 218302, upload-time = "2025-09-21T20:02:42.527Z" }, - { url = "https://files.pythonhosted.org/packages/f0/89/673f6514b0961d1f0e20ddc242e9342f6da21eaba3489901b565c0689f34/coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32", size = 218578, upload-time = "2025-09-21T20:02:44.468Z" }, - { url = "https://files.pythonhosted.org/packages/05/e8/261cae479e85232828fb17ad536765c88dd818c8470aca690b0ac6feeaa3/coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f", size = 249629, upload-time = "2025-09-21T20:02:46.503Z" }, - { url = "https://files.pythonhosted.org/packages/82/62/14ed6546d0207e6eda876434e3e8475a3e9adbe32110ce896c9e0c06bb9a/coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a", size = 252162, upload-time = "2025-09-21T20:02:48.689Z" }, - { url = "https://files.pythonhosted.org/packages/ff/49/07f00db9ac6478e4358165a08fb41b469a1b053212e8a00cb02f0d27a05f/coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360", size = 253517, upload-time = "2025-09-21T20:02:50.31Z" }, - { url = "https://files.pythonhosted.org/packages/a2/59/c5201c62dbf165dfbc91460f6dbbaa85a8b82cfa6131ac45d6c1bfb52deb/coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69", size = 249632, upload-time = "2025-09-21T20:02:51.971Z" }, - { url = "https://files.pythonhosted.org/packages/07/ae/5920097195291a51fb00b3a70b9bbd2edbfe3c84876a1762bd1ef1565ebc/coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14", size = 251520, upload-time = "2025-09-21T20:02:53.858Z" }, - { url = "https://files.pythonhosted.org/packages/b9/3c/a815dde77a2981f5743a60b63df31cb322c944843e57dbd579326625a413/coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe", size = 249455, upload-time = "2025-09-21T20:02:55.807Z" }, - { url = "https://files.pythonhosted.org/packages/aa/99/f5cdd8421ea656abefb6c0ce92556709db2265c41e8f9fc6c8ae0f7824c9/coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e", size = 249287, upload-time = "2025-09-21T20:02:57.784Z" }, - { url = "https://files.pythonhosted.org/packages/c3/7a/e9a2da6a1fc5d007dd51fca083a663ab930a8c4d149c087732a5dbaa0029/coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd", size = 250946, upload-time = "2025-09-21T20:02:59.431Z" }, - { url = "https://files.pythonhosted.org/packages/ef/5b/0b5799aa30380a949005a353715095d6d1da81927d6dbed5def2200a4e25/coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2", size = 221009, upload-time = "2025-09-21T20:03:01.324Z" }, - { url = "https://files.pythonhosted.org/packages/da/b0/e802fbb6eb746de006490abc9bb554b708918b6774b722bb3a0e6aa1b7de/coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681", size = 221804, upload-time = "2025-09-21T20:03:03.4Z" }, - { url = "https://files.pythonhosted.org/packages/9e/e8/71d0c8e374e31f39e3389bb0bd19e527d46f00ea8571ec7ec8fd261d8b44/coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880", size = 220384, upload-time = "2025-09-21T20:03:05.111Z" }, - { url = "https://files.pythonhosted.org/packages/62/09/9a5608d319fa3eba7a2019addeacb8c746fb50872b57a724c9f79f146969/coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63", size = 219047, upload-time = "2025-09-21T20:03:06.795Z" }, - { url = "https://files.pythonhosted.org/packages/f5/6f/f58d46f33db9f2e3647b2d0764704548c184e6f5e014bef528b7f979ef84/coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2", size = 219266, upload-time = "2025-09-21T20:03:08.495Z" }, - { url = "https://files.pythonhosted.org/packages/74/5c/183ffc817ba68e0b443b8c934c8795553eb0c14573813415bd59941ee165/coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d", size = 260767, upload-time = "2025-09-21T20:03:10.172Z" }, - { url = "https://files.pythonhosted.org/packages/0f/48/71a8abe9c1ad7e97548835e3cc1adbf361e743e9d60310c5f75c9e7bf847/coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0", size = 262931, upload-time = "2025-09-21T20:03:11.861Z" }, - { url = "https://files.pythonhosted.org/packages/84/fd/193a8fb132acfc0a901f72020e54be5e48021e1575bb327d8ee1097a28fd/coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699", size = 265186, upload-time = "2025-09-21T20:03:13.539Z" }, - { url = "https://files.pythonhosted.org/packages/b1/8f/74ecc30607dd95ad50e3034221113ccb1c6d4e8085cc761134782995daae/coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9", size = 259470, upload-time = "2025-09-21T20:03:15.584Z" }, - { url = "https://files.pythonhosted.org/packages/0f/55/79ff53a769f20d71b07023ea115c9167c0bb56f281320520cf64c5298a96/coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f", size = 262626, upload-time = "2025-09-21T20:03:17.673Z" }, - { url = "https://files.pythonhosted.org/packages/88/e2/dac66c140009b61ac3fc13af673a574b00c16efdf04f9b5c740703e953c0/coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1", size = 260386, upload-time = "2025-09-21T20:03:19.36Z" }, - { url = "https://files.pythonhosted.org/packages/a2/f1/f48f645e3f33bb9ca8a496bc4a9671b52f2f353146233ebd7c1df6160440/coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0", size = 258852, upload-time = "2025-09-21T20:03:21.007Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3b/8442618972c51a7affeead957995cfa8323c0c9bcf8fa5a027421f720ff4/coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399", size = 261534, upload-time = "2025-09-21T20:03:23.12Z" }, - { url = "https://files.pythonhosted.org/packages/b2/dc/101f3fa3a45146db0cb03f5b4376e24c0aac818309da23e2de0c75295a91/coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235", size = 221784, upload-time = "2025-09-21T20:03:24.769Z" }, - { url = "https://files.pythonhosted.org/packages/4c/a1/74c51803fc70a8a40d7346660379e144be772bab4ac7bb6e6b905152345c/coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d", size = 222905, upload-time = "2025-09-21T20:03:26.93Z" }, - { url = "https://files.pythonhosted.org/packages/12/65/f116a6d2127df30bcafbceef0302d8a64ba87488bf6f73a6d8eebf060873/coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a", size = 220922, upload-time = "2025-09-21T20:03:28.672Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ad/d1c25053764b4c42eb294aae92ab617d2e4f803397f9c7c8295caa77a260/coverage-7.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3", size = 217978, upload-time = "2025-09-21T20:03:30.362Z" }, - { url = "https://files.pythonhosted.org/packages/52/2f/b9f9daa39b80ece0b9548bbb723381e29bc664822d9a12c2135f8922c22b/coverage-7.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c", size = 218370, upload-time = "2025-09-21T20:03:32.147Z" }, - { url = "https://files.pythonhosted.org/packages/dd/6e/30d006c3b469e58449650642383dddf1c8fb63d44fdf92994bfd46570695/coverage-7.10.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396", size = 244802, upload-time = "2025-09-21T20:03:33.919Z" }, - { url = "https://files.pythonhosted.org/packages/b0/49/8a070782ce7e6b94ff6a0b6d7c65ba6bc3091d92a92cef4cd4eb0767965c/coverage-7.10.7-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40", size = 246625, upload-time = "2025-09-21T20:03:36.09Z" }, - { url = "https://files.pythonhosted.org/packages/6a/92/1c1c5a9e8677ce56d42b97bdaca337b2d4d9ebe703d8c174ede52dbabd5f/coverage-7.10.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594", size = 248399, upload-time = "2025-09-21T20:03:38.342Z" }, - { url = "https://files.pythonhosted.org/packages/c0/54/b140edee7257e815de7426d5d9846b58505dffc29795fff2dfb7f8a1c5a0/coverage-7.10.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a", size = 245142, upload-time = "2025-09-21T20:03:40.591Z" }, - { url = "https://files.pythonhosted.org/packages/e4/9e/6d6b8295940b118e8b7083b29226c71f6154f7ff41e9ca431f03de2eac0d/coverage-7.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b", size = 246284, upload-time = "2025-09-21T20:03:42.355Z" }, - { url = "https://files.pythonhosted.org/packages/db/e5/5e957ca747d43dbe4d9714358375c7546cb3cb533007b6813fc20fce37ad/coverage-7.10.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3", size = 244353, upload-time = "2025-09-21T20:03:44.218Z" }, - { url = "https://files.pythonhosted.org/packages/9a/45/540fc5cc92536a1b783b7ef99450bd55a4b3af234aae35a18a339973ce30/coverage-7.10.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0", size = 244430, upload-time = "2025-09-21T20:03:46.065Z" }, - { url = "https://files.pythonhosted.org/packages/75/0b/8287b2e5b38c8fe15d7e3398849bb58d382aedc0864ea0fa1820e8630491/coverage-7.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f", size = 245311, upload-time = "2025-09-21T20:03:48.19Z" }, - { url = "https://files.pythonhosted.org/packages/0c/1d/29724999984740f0c86d03e6420b942439bf5bd7f54d4382cae386a9d1e9/coverage-7.10.7-cp39-cp39-win32.whl", hash = "sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431", size = 220500, upload-time = "2025-09-21T20:03:50.024Z" }, - { url = "https://files.pythonhosted.org/packages/43/11/4b1e6b129943f905ca54c339f343877b55b365ae2558806c1be4f7476ed5/coverage-7.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07", size = 221408, upload-time = "2025-09-21T20:03:51.803Z" }, - { url = "https://files.pythonhosted.org/packages/ec/16/114df1c291c22cac3b0c127a73e0af5c12ed7bbb6558d310429a0ae24023/coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260", size = 209952, upload-time = "2025-09-21T20:03:53.918Z" }, -] - -[package.optional-dependencies] -toml = [ - { name = "tomli", marker = "python_full_version < '3.10'" }, -] - [[package]] name = "coverage" version = "7.13.5" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", size = 915967, upload-time = "2026-03-17T10:33:18.341Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/69/33/e8c48488c29a73fd089f9d71f9653c1be7478f2ad6b5bc870db11a55d23d/coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5", size = 219255, upload-time = "2026-03-17T10:29:51.081Z" }, - { url = "https://files.pythonhosted.org/packages/da/bd/b0ebe9f677d7f4b74a3e115eec7ddd4bcf892074963a00d91e8b164a6386/coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf", size = 219772, upload-time = "2026-03-17T10:29:52.867Z" }, - { url = "https://files.pythonhosted.org/packages/48/cc/5cb9502f4e01972f54eedd48218bb203fe81e294be606a2bc93970208013/coverage-7.13.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8", size = 246532, upload-time = "2026-03-17T10:29:54.688Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d8/3217636d86c7e7b12e126e4f30ef1581047da73140614523af7495ed5f2d/coverage-7.13.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4", size = 248333, upload-time = "2026-03-17T10:29:56.221Z" }, - { url = "https://files.pythonhosted.org/packages/2b/30/2002ac6729ba2d4357438e2ed3c447ad8562866c8c63fc16f6dfc33afe56/coverage-7.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d", size = 250211, upload-time = "2026-03-17T10:29:57.938Z" }, - { url = "https://files.pythonhosted.org/packages/6c/85/552496626d6b9359eb0e2f86f920037c9cbfba09b24d914c6e1528155f7d/coverage-7.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930", size = 252125, upload-time = "2026-03-17T10:29:59.388Z" }, - { url = "https://files.pythonhosted.org/packages/44/21/40256eabdcbccdb6acf6b381b3016a154399a75fe39d406f790ae84d1f3c/coverage-7.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d", size = 247219, upload-time = "2026-03-17T10:30:01.199Z" }, - { url = "https://files.pythonhosted.org/packages/b1/e8/96e2a6c3f21a0ea77d7830b254a1542d0328acc8d7bdf6a284ba7e529f77/coverage-7.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40", size = 248248, upload-time = "2026-03-17T10:30:03.317Z" }, - { url = "https://files.pythonhosted.org/packages/da/ba/8477f549e554827da390ec659f3c38e4b6d95470f4daafc2d8ff94eaa9c2/coverage-7.13.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878", size = 246254, upload-time = "2026-03-17T10:30:04.832Z" }, - { url = "https://files.pythonhosted.org/packages/55/59/bc22aef0e6aa179d5b1b001e8b3654785e9adf27ef24c93dc4228ebd5d68/coverage-7.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400", size = 250067, upload-time = "2026-03-17T10:30:06.535Z" }, - { url = "https://files.pythonhosted.org/packages/de/1b/c6a023a160806a5137dca53468fd97530d6acad24a22003b1578a9c2e429/coverage-7.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0", size = 246521, upload-time = "2026-03-17T10:30:08.486Z" }, - { url = "https://files.pythonhosted.org/packages/2d/3f/3532c85a55aa2f899fa17c186f831cfa1aa434d88ff792a709636f64130e/coverage-7.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0", size = 247126, upload-time = "2026-03-17T10:30:09.966Z" }, - { url = "https://files.pythonhosted.org/packages/aa/2e/b9d56af4a24ef45dfbcda88e06870cb7d57b2b0bfa3a888d79b4c8debd76/coverage-7.13.5-cp310-cp310-win32.whl", hash = "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58", size = 221860, upload-time = "2026-03-17T10:30:11.393Z" }, - { url = "https://files.pythonhosted.org/packages/9f/cc/d938417e7a4d7f0433ad4edee8bb2acdc60dc7ac5af19e2a07a048ecbee3/coverage-7.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e", size = 222788, upload-time = "2026-03-17T10:30:12.886Z" }, { url = "https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d", size = 219381, upload-time = "2026-03-17T10:30:14.68Z" }, { url = "https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587", size = 219880, upload-time = "2026-03-17T10:30:16.231Z" }, { url = "https://files.pythonhosted.org/packages/55/2f/e0e5b237bffdb5d6c530ce87cc1d413a5b7d7dfd60fb067ad6d254c35c76/coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642", size = 250303, upload-time = "2026-03-17T10:30:17.748Z" }, @@ -895,7 +652,7 @@ wheels = [ [package.optional-dependencies] toml = [ - { name = "tomli", marker = "python_full_version >= '3.10' and python_full_version <= '3.11'" }, + { name = "tomli", marker = "python_full_version <= '3.11'" }, ] [[package]] @@ -904,7 +661,6 @@ version = "46.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } wheels = [ @@ -958,31 +714,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" }, ] -[[package]] -name = "dataclasses-json" -version = "0.6.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "marshmallow" }, - { name = "typing-inspect" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/64/a4/f71d9cf3a5ac257c993b5ca3f93df5f7fb395c725e7f1e6479d2514173c3/dataclasses_json-0.6.7.tar.gz", hash = "sha256:b6b3e528266ea45b9535223bc53ca645f5208833c29229e847b3f26a1cc55fc0", size = 32227, upload-time = "2024-06-09T16:20:19.103Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a", size = 28686, upload-time = "2024-06-09T16:20:16.715Z" }, -] - -[[package]] -name = "exceptiongroup" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, -] - [[package]] name = "ghp-import" version = "2.1.0" @@ -995,42 +726,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, ] -[[package]] -name = "griffe" -version = "1.14.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ec/d7/6c09dd7ce4c7837e4cdb11dce980cb45ae3cd87677298dc3b781b6bce7d3/griffe-1.14.0.tar.gz", hash = "sha256:9d2a15c1eca966d68e00517de5d69dd1bc5c9f2335ef6c1775362ba5b8651a13", size = 424684, upload-time = "2025-09-05T15:02:29.167Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/b1/9ff6578d789a89812ff21e4e0f80ffae20a65d5dd84e7a17873fe3b365be/griffe-1.14.0-py3-none-any.whl", hash = "sha256:0e9d52832cccf0f7188cfe585ba962d2674b241c01916d780925df34873bceb0", size = 144439, upload-time = "2025-09-05T15:02:27.511Z" }, -] - -[[package]] -name = "griffe-pydantic" -version = "1.1.8" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "griffe", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/99/52/b05f582287f887f58a1738183d6dd0e799842b83f6f60d65c77ba90cee31/griffe_pydantic-1.1.8.tar.gz", hash = "sha256:72cde69c74c70f3dc0385a7a5243c736cd6bf6fcf8a41cae497383defe107041", size = 43425, upload-time = "2025-10-14T09:12:37.693Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/e3/94b2e39d841a1c07b586903177d3ee802c8ae87567449a541d14028eb657/griffe_pydantic-1.1.8-py3-none-any.whl", hash = "sha256:22212c94216e03bf43d30ff3bc79cd53fb973ae2fe81d8b7510242232a1e6764", size = 12852, upload-time = "2025-10-14T09:12:36.23Z" }, -] - [[package]] name = "griffe-pydantic" version = "1.3.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "griffelib", marker = "python_full_version >= '3.10'" }, + { name = "griffelib" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5a/bd/d2eaeaf3f9910c9cd72793af0de18ee3d3a3a27bb30ab01cfd7659c08dc4/griffe_pydantic-1.3.1.tar.gz", hash = "sha256:f7caedfa0effedb22893bf01cc411fd567614f7b4de7ce0c1f4293eb7acb5c44", size = 38176, upload-time = "2026-02-21T09:38:49.674Z" } wheels = [ @@ -1091,37 +792,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] -[[package]] -name = "importlib-metadata" -version = "8.7.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "zipp" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, -] - -[[package]] -name = "iniconfig" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, -] - [[package]] name = "iniconfig" version = "2.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, @@ -1163,18 +837,6 @@ version = "0.8.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/56/9c/b4b0c54d84da4a94b37bd44151e46d5e583c9534c7e02250b961b1b6d8a8/librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73", size = 177471, upload-time = "2026-02-17T16:13:06.101Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/5f/63f5fa395c7a8a93558c0904ba8f1c8d1b997ca6a3de61bc7659970d66bf/librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc", size = 65697, upload-time = "2026-02-17T16:11:06.903Z" }, - { url = "https://files.pythonhosted.org/packages/ff/e0/0472cf37267b5920eff2f292ccfaede1886288ce35b7f3203d8de00abfe6/librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7", size = 68376, upload-time = "2026-02-17T16:11:08.395Z" }, - { url = "https://files.pythonhosted.org/packages/c8/be/8bd1359fdcd27ab897cd5963294fa4a7c83b20a8564678e4fd12157e56a5/librt-0.8.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6", size = 197084, upload-time = "2026-02-17T16:11:09.774Z" }, - { url = "https://files.pythonhosted.org/packages/e2/fe/163e33fdd091d0c2b102f8a60cc0a61fd730ad44e32617cd161e7cd67a01/librt-0.8.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0", size = 207337, upload-time = "2026-02-17T16:11:11.311Z" }, - { url = "https://files.pythonhosted.org/packages/01/99/f85130582f05dcf0c8902f3d629270231d2f4afdfc567f8305a952ac7f14/librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b", size = 219980, upload-time = "2026-02-17T16:11:12.499Z" }, - { url = "https://files.pythonhosted.org/packages/6f/54/cb5e4d03659e043a26c74e08206412ac9a3742f0477d96f9761a55313b5f/librt-0.8.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6", size = 212921, upload-time = "2026-02-17T16:11:14.484Z" }, - { url = "https://files.pythonhosted.org/packages/b1/81/a3a01e4240579c30f3487f6fed01eb4bc8ef0616da5b4ebac27ca19775f3/librt-0.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71", size = 221381, upload-time = "2026-02-17T16:11:17.459Z" }, - { url = "https://files.pythonhosted.org/packages/08/b0/fc2d54b4b1c6fb81e77288ff31ff25a2c1e62eaef4424a984f228839717b/librt-0.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7", size = 216714, upload-time = "2026-02-17T16:11:19.197Z" }, - { url = "https://files.pythonhosted.org/packages/96/96/85daa73ffbd87e1fb287d7af6553ada66bf25a2a6b0de4764344a05469f6/librt-0.8.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05", size = 214777, upload-time = "2026-02-17T16:11:20.443Z" }, - { url = "https://files.pythonhosted.org/packages/12/9c/c3aa7a2360383f4bf4f04d98195f2739a579128720c603f4807f006a4225/librt-0.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891", size = 237398, upload-time = "2026-02-17T16:11:22.083Z" }, - { url = "https://files.pythonhosted.org/packages/61/19/d350ea89e5274665185dabc4bbb9c3536c3411f862881d316c8b8e00eb66/librt-0.8.1-cp310-cp310-win32.whl", hash = "sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7", size = 54285, upload-time = "2026-02-17T16:11:23.27Z" }, - { url = "https://files.pythonhosted.org/packages/4f/d6/45d587d3d41c112e9543a0093d883eb57a24a03e41561c127818aa2a6bcc/librt-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2", size = 61352, upload-time = "2026-02-17T16:11:24.207Z" }, { url = "https://files.pythonhosted.org/packages/1d/01/0e748af5e4fee180cf7cd12bd12b0513ad23b045dccb2a83191bde82d168/librt-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd", size = 65315, upload-time = "2026-02-17T16:11:25.152Z" }, { url = "https://files.pythonhosted.org/packages/9d/4d/7184806efda571887c798d573ca4134c80ac8642dcdd32f12c31b939c595/librt-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965", size = 68021, upload-time = "2026-02-17T16:11:26.129Z" }, { url = "https://files.pythonhosted.org/packages/ae/88/c3c52d2a5d5101f28d3dc89298444626e7874aa904eed498464c2af17627/librt-0.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da", size = 194500, upload-time = "2026-02-17T16:11:27.177Z" }, @@ -1240,71 +902,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b9/eb/7697f60fbe7042ab4e88f4ee6af496b7f222fffb0a4e3593ef1f29f81652/librt-0.8.1-cp314-cp314t-win32.whl", hash = "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a", size = 51328, upload-time = "2026-02-17T16:12:45.148Z" }, { url = "https://files.pythonhosted.org/packages/7c/72/34bf2eb7a15414a23e5e70ecb9440c1d3179f393d9349338a91e2781c0fb/librt-0.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4", size = 58722, upload-time = "2026-02-17T16:12:46.85Z" }, { url = "https://files.pythonhosted.org/packages/b2/c8/d148e041732d631fc76036f8b30fae4e77b027a1e95b7a84bb522481a940/librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61", size = 48755, upload-time = "2026-02-17T16:12:47.943Z" }, - { url = "https://files.pythonhosted.org/packages/01/1f/c7d8b66a3ca3ca3ed8ded4b32c96ee58a45920ebbbaa934355c74adcc33e/librt-0.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac", size = 65990, upload-time = "2026-02-17T16:12:48.972Z" }, - { url = "https://files.pythonhosted.org/packages/56/be/ee9ba1730052313d08457f19beaa1b878619978863fba09b40aed5b5c123/librt-0.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed", size = 68640, upload-time = "2026-02-17T16:12:50.24Z" }, - { url = "https://files.pythonhosted.org/packages/81/27/b7309298b96f7690cec3ceee38004c1a7f60fcd96d952d3ac344a1e3e8b3/librt-0.8.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd", size = 196099, upload-time = "2026-02-17T16:12:52.788Z" }, - { url = "https://files.pythonhosted.org/packages/10/48/160a5aacdcb21824b10a52378c39e88c46a29bb31efdaf3910dd1f9b670e/librt-0.8.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851", size = 206663, upload-time = "2026-02-17T16:12:55.017Z" }, - { url = "https://files.pythonhosted.org/packages/ee/65/33dd1d8caabb7c6805d87d095b143417dc96b0277c06ffa0508361422c82/librt-0.8.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128", size = 219318, upload-time = "2026-02-17T16:12:56.145Z" }, - { url = "https://files.pythonhosted.org/packages/09/d4/353805aa6181c7950a2462bd6e855366eeca21a501f375228d72a51547df/librt-0.8.1-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac", size = 212191, upload-time = "2026-02-17T16:12:57.326Z" }, - { url = "https://files.pythonhosted.org/packages/06/08/725b3f304d61eba56c713c251fb833a06d84bf93381caad5152366f5d2bb/librt-0.8.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551", size = 220672, upload-time = "2026-02-17T16:12:58.497Z" }, - { url = "https://files.pythonhosted.org/packages/0e/55/e8cdf04145872b3b97cb9b68287b22d1c08348227063f305aec11a3e6ce7/librt-0.8.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5", size = 216172, upload-time = "2026-02-17T16:12:59.751Z" }, - { url = "https://files.pythonhosted.org/packages/8f/d8/23b1c6592d2422dd6829c672f45b1f1c257f219926b0d216fedb572d0184/librt-0.8.1-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6", size = 214116, upload-time = "2026-02-17T16:13:01.056Z" }, - { url = "https://files.pythonhosted.org/packages/c9/92/2b44fd3cc3313f44e43bdbb41343735b568fa675fa351642b408ee48d418/librt-0.8.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed", size = 236664, upload-time = "2026-02-17T16:13:02.314Z" }, - { url = "https://files.pythonhosted.org/packages/00/23/92313ecdab80e142d8ea10e8dfa6297694359dbaacc9e81679bdc8cbceb6/librt-0.8.1-cp39-cp39-win32.whl", hash = "sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc", size = 54368, upload-time = "2026-02-17T16:13:03.549Z" }, - { url = "https://files.pythonhosted.org/packages/68/36/18f6e768afad6b55a690d38427c53251b69b7ba8795512730fd2508b31a9/librt-0.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7", size = 61507, upload-time = "2026-02-17T16:13:04.556Z" }, -] - -[[package]] -name = "markdown" -version = "3.9" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8d/37/02347f6d6d8279247a5837082ebc26fc0d5aaeaf75aa013fcbb433c777ab/markdown-3.9.tar.gz", hash = "sha256:d2900fe1782bd33bdbbd56859defef70c2e78fc46668f8eb9df3128138f2cb6a", size = 364585, upload-time = "2025-09-04T20:25:22.885Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/ae/44c4a6a4cbb496d93c6257954260fe3a6e91b7bed2240e5dad2a717f5111/markdown-3.9-py3-none-any.whl", hash = "sha256:9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280", size = 107441, upload-time = "2025-09-04T20:25:21.784Z" }, ] [[package]] name = "markdown" version = "3.10.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, ] -[[package]] -name = "markdown-it-py" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "mdurl", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, -] - [[package]] name = "markdown-it-py" version = "4.0.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "mdurl", marker = "python_full_version >= '3.10'" }, + { name = "mdurl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } wheels = [ @@ -1317,17 +931,6 @@ version = "3.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, - { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, - { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, - { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, - { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, - { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, - { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, - { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, - { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, - { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, - { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, @@ -1394,29 +997,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, - { url = "https://files.pythonhosted.org/packages/56/23/0d8c13a44bde9154821586520840643467aee574d8ce79a17da539ee7fed/markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26", size = 11623, upload-time = "2025-09-27T18:37:29.296Z" }, - { url = "https://files.pythonhosted.org/packages/fd/23/07a2cb9a8045d5f3f0890a8c3bc0859d7a47bfd9a560b563899bec7b72ed/markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc", size = 12049, upload-time = "2025-09-27T18:37:30.234Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e4/6be85eb81503f8e11b61c0b6369b6e077dcf0a74adbd9ebf6b349937b4e9/markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c", size = 21923, upload-time = "2025-09-27T18:37:31.177Z" }, - { url = "https://files.pythonhosted.org/packages/6f/bc/4dc914ead3fe6ddaef035341fee0fc956949bbd27335b611829292b89ee2/markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42", size = 20543, upload-time = "2025-09-27T18:37:32.168Z" }, - { url = "https://files.pythonhosted.org/packages/89/6e/5fe81fbcfba4aef4093d5f856e5c774ec2057946052d18d168219b7bd9f9/markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b", size = 20585, upload-time = "2025-09-27T18:37:33.166Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f6/e0e5a3d3ae9c4020f696cd055f940ef86b64fe88de26f3a0308b9d3d048c/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758", size = 21387, upload-time = "2025-09-27T18:37:34.185Z" }, - { url = "https://files.pythonhosted.org/packages/c8/25/651753ef4dea08ea790f4fbb65146a9a44a014986996ca40102e237aa49a/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2", size = 20133, upload-time = "2025-09-27T18:37:35.138Z" }, - { url = "https://files.pythonhosted.org/packages/dc/0a/c3cf2b4fef5f0426e8a6d7fce3cb966a17817c568ce59d76b92a233fdbec/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d", size = 20588, upload-time = "2025-09-27T18:37:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/cd/1b/a7782984844bd519ad4ffdbebbba2671ec5d0ebbeac34736c15fb86399e8/markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7", size = 14566, upload-time = "2025-09-27T18:37:37.09Z" }, - { url = "https://files.pythonhosted.org/packages/18/1f/8d9c20e1c9440e215a44be5ab64359e207fcb4f675543f1cf9a2a7f648d0/markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e", size = 15053, upload-time = "2025-09-27T18:37:38.054Z" }, - { url = "https://files.pythonhosted.org/packages/4e/d3/fe08482b5cd995033556d45041a4f4e76e7f0521112a9c9991d40d39825f/markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8", size = 13928, upload-time = "2025-09-27T18:37:39.037Z" }, -] - -[[package]] -name = "marshmallow" -version = "3.22.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/70/40/faa10dc4500bca85f41ca9d8cefab282dd23d0fcc7a9b5fab40691e72e76/marshmallow-3.22.0.tar.gz", hash = "sha256:4972f529104a220bb8637d595aa4c9762afbe7f7a77d82dc58c1615d70c5823e", size = 176836, upload-time = "2024-08-20T16:30:30.929Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/78/c1de55eb3311f2c200a8b91724414b8d6f5ae78891c15d9d936ea43c3dba/marshmallow-3.22.0-py3-none-any.whl", hash = "sha256:71a2dce49ef901c3f97ed296ae5051135fd3febd2bf43afe0ae9a82143a494d9", size = 49334, upload-time = "2024-08-20T16:30:29.351Z" }, ] [[package]] @@ -1442,14 +1022,11 @@ name = "mkdocs" version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "ghp-import" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "jinja2" }, - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "markupsafe" }, { name = "mergedeep" }, { name = "mkdocs-get-deps" }, @@ -1469,8 +1046,7 @@ name = "mkdocs-autorefs" version = "1.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "markupsafe" }, { name = "mkdocs" }, ] @@ -1484,10 +1060,8 @@ name = "mkdocs-get-deps" version = "0.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "mergedeep" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "platformdirs", version = "4.9.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "platformdirs" }, { name = "pyyaml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ce/25/b3cccb187655b9393572bde9b09261d267c3bf2f2cdabe347673be5976a6/mkdocs_get_deps-0.2.2.tar.gz", hash = "sha256:8ee8d5f316cdbbb2834bc1df6e69c08fe769a83e040060de26d3c19fad3599a1", size = 11047, upload-time = "2026-03-10T02:46:33.632Z" } @@ -1497,15 +1071,14 @@ wheels = [ [[package]] name = "mkdocs-material" -version = "9.7.5" +version = "9.7.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "babel" }, { name = "backrefs" }, { name = "colorama" }, { name = "jinja2" }, - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "mkdocs" }, { name = "mkdocs-material-extensions" }, { name = "paginate" }, @@ -1513,9 +1086,9 @@ dependencies = [ { name = "pymdown-extensions" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/76/5c202fecdc45d53e83e03a85bae70c48b6c81e9f87f0bc19a9e9c723bdc0/mkdocs_material-9.7.5.tar.gz", hash = "sha256:f76bdab532bad1d9c57ca7187b37eccf64dd12e1586909307f8856db3be384ea", size = 4097749, upload-time = "2026-03-10T15:43:22.809Z" } +sdist = { url = "https://files.pythonhosted.org/packages/45/29/6d2bcf41ae40802c4beda2432396fff97b8456fb496371d1bc7aad6512ec/mkdocs_material-9.7.6.tar.gz", hash = "sha256:00bdde50574f776d328b1862fe65daeaf581ec309bd150f7bff345a098c64a69", size = 4097959, upload-time = "2026-03-19T15:41:58.161Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/45/e1/e8080dcfa95cca267662a6f4afe29237452bdeb5a2a6555ac83646d21915/mkdocs_material-9.7.5-py3-none-any.whl", hash = "sha256:7cf9df2ff121fd098ff6e05c732b0be3699afca9642e2dfe4926c40eb5873eec", size = 9305251, upload-time = "2026-03-10T15:43:19.089Z" }, + { url = "https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl", hash = "sha256:71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba", size = 9305470, upload-time = "2026-03-19T15:41:55.217Z" }, ] [[package]] @@ -1532,10 +1105,8 @@ name = "mkdocstrings" version = "0.30.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "jinja2" }, - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "markupsafe" }, { name = "mkdocs" }, { name = "mkdocs-autorefs" }, @@ -1548,40 +1119,17 @@ wheels = [ [package.optional-dependencies] python = [ - { name = "mkdocstrings-python", version = "1.18.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "mkdocstrings-python", version = "2.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, -] - -[[package]] -name = "mkdocstrings-python" -version = "1.18.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "griffe", marker = "python_full_version < '3.10'" }, - { name = "mkdocs-autorefs", marker = "python_full_version < '3.10'" }, - { name = "mkdocstrings", marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/95/ae/58ab2bfbee2792e92a98b97e872f7c003deb903071f75d8d83aa55db28fa/mkdocstrings_python-1.18.2.tar.gz", hash = "sha256:4ad536920a07b6336f50d4c6d5603316fafb1172c5c882370cbbc954770ad323", size = 207972, upload-time = "2025-08-28T16:11:19.847Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/8f/ce008599d9adebf33ed144e7736914385e8537f5fc686fdb7cceb8c22431/mkdocstrings_python-1.18.2-py3-none-any.whl", hash = "sha256:944fe6deb8f08f33fa936d538233c4036e9f53e840994f6146e8e94eb71b600d", size = 138215, upload-time = "2025-08-28T16:11:18.176Z" }, + { name = "mkdocstrings-python" }, ] [[package]] name = "mkdocstrings-python" version = "2.0.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "griffelib", marker = "python_full_version >= '3.10'" }, - { name = "mkdocs-autorefs", marker = "python_full_version >= '3.10'" }, - { name = "mkdocstrings", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, + { name = "griffelib" }, + { name = "mkdocs-autorefs" }, + { name = "mkdocstrings" }, ] sdist = { url = "https://files.pythonhosted.org/packages/29/33/c225eaf898634bdda489a6766fc35d1683c640bffe0e0acd10646b13536d/mkdocstrings_python-2.0.3.tar.gz", hash = "sha256:c518632751cc869439b31c9d3177678ad2bfa5c21b79b863956ad68fc92c13b8", size = 199083, upload-time = "2026-02-20T10:38:36.368Z" } wheels = [ @@ -1616,17 +1164,10 @@ dependencies = [ { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, { name = "pathspec" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" }, - { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" }, - { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" }, - { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" }, - { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" }, - { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" }, { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" }, { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" }, { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" }, @@ -1651,12 +1192,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f7/88436084550ca9af5e610fa45286be04c3b63374df3e021c762fe8c4369f/mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3", size = 13102606, upload-time = "2025-12-15T05:02:46.833Z" }, - { url = "https://files.pythonhosted.org/packages/ca/a5/43dfad311a734b48a752790571fd9e12d61893849a01bff346a54011957f/mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a", size = 12164496, upload-time = "2025-12-15T05:03:41.947Z" }, - { url = "https://files.pythonhosted.org/packages/88/f0/efbfa391395cce2f2771f937e0620cfd185ec88f2b9cd88711028a768e96/mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67", size = 12772068, upload-time = "2025-12-15T05:02:53.689Z" }, - { url = "https://files.pythonhosted.org/packages/25/05/58b3ba28f5aed10479e899a12d2120d582ba9fa6288851b20bf1c32cbb4f/mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e", size = 13520385, upload-time = "2025-12-15T05:02:38.328Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a0/c006ccaff50b31e542ae69b92fe7e2f55d99fba3a55e01067dd564325f85/mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376", size = 13796221, upload-time = "2025-12-15T05:03:22.147Z" }, - { url = "https://files.pythonhosted.org/packages/b2/ff/8bdb051cd710f01b880472241bd36b3f817a8e1c5d5540d0b761675b6de2/mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24", size = 10055456, upload-time = "2025-12-15T05:03:35.169Z" }, { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, ] @@ -1710,14 +1245,14 @@ wheels = [ [[package]] name = "mypy-boto3-ec2" -version = "1.42.62" +version = "1.42.71" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4f/5b/6d6c6a1294fc13ad12ed78a22e6a29c63291de14d51830b59e8cbac535e0/mypy_boto3_ec2-1.42.62.tar.gz", hash = "sha256:5af94008bf7561c17d177249846f7ac127c228280c6efd57237c4ba804ebaa24", size = 441387, upload-time = "2026-03-05T21:51:54.487Z" } +sdist = { url = "https://files.pythonhosted.org/packages/68/15/b602ca5840d26d5ba8d7e5f73dc7d9f5d0858af8fd2420ee74131de63d1e/mypy_boto3_ec2-1.42.71.tar.gz", hash = "sha256:9e531887fb797466ec7cc1bf7a968881464ae407205c14d69852bc3cf469a60d", size = 441510, upload-time = "2026-03-18T19:54:02.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/1b/cd7a5c224e6802469baa594fce134ca18d78a379d677b44bc5885ff03621/mypy_boto3_ec2-1.42.62-py3-none-any.whl", hash = "sha256:05222356cdfa9bae93398841e0e317b920a94927350578ecde2e2ff1a4f433e8", size = 430717, upload-time = "2026-03-05T21:51:45.538Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/b0145f193d0d5d00e7b48aa50f3d0147fa383b810386df5e65dd5fbf5f78/mypy_boto3_ec2-1.42.71-py3-none-any.whl", hash = "sha256:5b7b7df51731b59f716e52be1efb53d9fc8c9356c32d7b63d68cb57e1860ae12", size = 430825, upload-time = "2026-03-18T19:53:57.405Z" }, ] [[package]] @@ -1849,25 +1384,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] -[[package]] -name = "platformdirs" -version = "4.4.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, -] - [[package]] name = "platformdirs" version = "4.9.4" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/19/56/8d4c30c8a1d07013911a8fdbd8f89440ef9f08d07a1b50ab8ca8be5a20f9/platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", size = 28737, upload-time = "2026-03-05T18:34:13.271Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868", size = 21216, upload-time = "2026-03-05T18:34:12.172Z" }, @@ -1894,25 +1414,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, ] -[[package]] -name = "pycparser" -version = "2.23" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, -] - [[package]] name = "pycparser" version = "3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, @@ -1942,19 +1447,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, - { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, - { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, - { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, - { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, - { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, - { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, - { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, - { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, - { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, - { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, - { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, @@ -2025,19 +1517,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/54/db/160dffb57ed9a3705c4cbcbff0ac03bdae45f1ca7d58ab74645550df3fbd/pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf", size = 2107999, upload-time = "2025-11-04T13:42:03.885Z" }, - { url = "https://files.pythonhosted.org/packages/a3/7d/88e7de946f60d9263cc84819f32513520b85c0f8322f9b8f6e4afc938383/pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5", size = 1929745, upload-time = "2025-11-04T13:42:06.075Z" }, - { url = "https://files.pythonhosted.org/packages/d5/c2/aef51e5b283780e85e99ff19db0f05842d2d4a8a8cd15e63b0280029b08f/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d", size = 1920220, upload-time = "2025-11-04T13:42:08.457Z" }, - { url = "https://files.pythonhosted.org/packages/c7/97/492ab10f9ac8695cd76b2fdb24e9e61f394051df71594e9bcc891c9f586e/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60", size = 2067296, upload-time = "2025-11-04T13:42:10.817Z" }, - { url = "https://files.pythonhosted.org/packages/ec/23/984149650e5269c59a2a4c41d234a9570adc68ab29981825cfaf4cfad8f4/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82", size = 2231548, upload-time = "2025-11-04T13:42:13.843Z" }, - { url = "https://files.pythonhosted.org/packages/71/0c/85bcbb885b9732c28bec67a222dbed5ed2d77baee1f8bba2002e8cd00c5c/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5", size = 2362571, upload-time = "2025-11-04T13:42:16.208Z" }, - { url = "https://files.pythonhosted.org/packages/c0/4a/412d2048be12c334003e9b823a3fa3d038e46cc2d64dd8aab50b31b65499/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3", size = 2068175, upload-time = "2025-11-04T13:42:18.911Z" }, - { url = "https://files.pythonhosted.org/packages/73/f4/c58b6a776b502d0a5540ad02e232514285513572060f0d78f7832ca3c98b/pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425", size = 2177203, upload-time = "2025-11-04T13:42:22.578Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ae/f06ea4c7e7a9eead3d165e7623cd2ea0cb788e277e4f935af63fc98fa4e6/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504", size = 2148191, upload-time = "2025-11-04T13:42:24.89Z" }, - { url = "https://files.pythonhosted.org/packages/c1/57/25a11dcdc656bf5f8b05902c3c2934ac3ea296257cc4a3f79a6319e61856/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5", size = 2343907, upload-time = "2025-11-04T13:42:27.683Z" }, - { url = "https://files.pythonhosted.org/packages/96/82/e33d5f4933d7a03327c0c43c65d575e5919d4974ffc026bc917a5f7b9f61/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3", size = 2322174, upload-time = "2025-11-04T13:42:30.776Z" }, - { url = "https://files.pythonhosted.org/packages/81/45/4091be67ce9f469e81656f880f3506f6a5624121ec5eb3eab37d7581897d/pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460", size = 1990353, upload-time = "2025-11-04T13:42:33.111Z" }, - { url = "https://files.pythonhosted.org/packages/44/8a/a98aede18db6e9cd5d66bcacd8a409fcf8134204cdede2e7de35c5a2c5ef/pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b", size = 2015698, upload-time = "2025-11-04T13:42:35.484Z" }, { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, @@ -2046,14 +1525,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, - { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, - { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, - { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, - { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, - { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, - { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, @@ -2064,34 +1535,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, ] -[[package]] -name = "pydantic-settings" -version = "2.11.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "pydantic", marker = "python_full_version < '3.10'" }, - { name = "python-dotenv", version = "1.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "typing-inspection", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/20/c5/dbbc27b814c71676593d1c3f718e6cd7d4f00652cefa24b75f7aa3efb25e/pydantic_settings-2.11.0.tar.gz", hash = "sha256:d0e87a1c7d33593beb7194adb8470fc426e95ba02af83a0f23474a04c9a08180", size = 188394, upload-time = "2025-09-24T14:19:11.764Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/d6/887a1ff844e64aa823fb4905978d882a633cfe295c32eacad582b78a7d8b/pydantic_settings-2.11.0-py3-none-any.whl", hash = "sha256:fe2cea3413b9530d10f3a5875adffb17ada5c1e1bab0b2885546d7310415207c", size = 48608, upload-time = "2025-09-24T14:19:10.015Z" }, -] - [[package]] name = "pydantic-settings" version = "2.13.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "python-dotenv", version = "1.2.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, ] sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" } wheels = [ @@ -2112,8 +1563,7 @@ name = "pymdown-extensions" version = "10.21" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "pyyaml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ba/63/06673d1eb6d8f83c0ea1f677d770e12565fb516928b4109c9e2055656a9e/pymdown_extensions-10.21.tar.gz", hash = "sha256:39f4a020f40773f6b2ff31d2cd2546c2c04d0a6498c31d9c688d2be07e1767d5", size = 853363, upload-time = "2026-02-15T20:44:06.748Z" } @@ -2136,12 +1586,9 @@ version = "7.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, - { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/80/1f/9d8e98e4133ffb16c90f3b405c43e38d3abb715bb5d7a63a5a684f7e46a3/pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280", size = 1357116, upload-time = "2023-12-31T12:00:18.035Z" } wheels = [ @@ -2153,8 +1600,7 @@ name = "pytest-cov" version = "7.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, - { name = "coverage", version = "7.13.5", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, + { name = "coverage", extra = ["toml"] }, { name = "pluggy" }, { name = "pytest" }, ] @@ -2175,25 +1621,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] -[[package]] -name = "python-dotenv" -version = "1.2.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, -] - [[package]] name = "python-dotenv" version = "1.2.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, @@ -2214,15 +1645,6 @@ version = "6.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, - { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, - { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, - { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, - { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, - { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, - { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, - { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, @@ -2270,15 +1692,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, - { url = "https://files.pythonhosted.org/packages/9f/62/67fc8e68a75f738c9200422bf65693fb79a4cd0dc5b23310e5202e978090/pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da", size = 184450, upload-time = "2025-09-25T21:33:00.618Z" }, - { url = "https://files.pythonhosted.org/packages/ae/92/861f152ce87c452b11b9d0977952259aa7df792d71c1053365cc7b09cc08/pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917", size = 174319, upload-time = "2025-09-25T21:33:02.086Z" }, - { url = "https://files.pythonhosted.org/packages/d0/cd/f0cfc8c74f8a030017a2b9c771b7f47e5dd702c3e28e5b2071374bda2948/pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9", size = 737631, upload-time = "2025-09-25T21:33:03.25Z" }, - { url = "https://files.pythonhosted.org/packages/ef/b2/18f2bd28cd2055a79a46c9b0895c0b3d987ce40ee471cecf58a1a0199805/pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5", size = 836795, upload-time = "2025-09-25T21:33:05.014Z" }, - { url = "https://files.pythonhosted.org/packages/73/b9/793686b2d54b531203c160ef12bec60228a0109c79bae6c1277961026770/pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a", size = 750767, upload-time = "2025-09-25T21:33:06.398Z" }, - { url = "https://files.pythonhosted.org/packages/a9/86/a137b39a611def2ed78b0e66ce2fe13ee701a07c07aebe55c340ed2a050e/pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926", size = 727982, upload-time = "2025-09-25T21:33:08.708Z" }, - { url = "https://files.pythonhosted.org/packages/dd/62/71c27c94f457cf4418ef8ccc71735324c549f7e3ea9d34aba50874563561/pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7", size = 755677, upload-time = "2025-09-25T21:33:09.876Z" }, - { url = "https://files.pythonhosted.org/packages/29/3d/6f5e0d58bd924fb0d06c3a6bad00effbdae2de5adb5cda5648006ffbd8d3/pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0", size = 142592, upload-time = "2025-09-25T21:33:10.983Z" }, - { url = "https://files.pythonhosted.org/packages/f0/0c/25113e0b5e103d7f1490c0e947e303fe4a696c10b501dea7a9f49d4e876c/pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007", size = 158777, upload-time = "2025-09-25T21:33:15.55Z" }, ] [[package]] @@ -2313,8 +1726,7 @@ dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, { name = "idna" }, - { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ @@ -2328,8 +1740,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml" }, { name = "requests" }, - { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9f/b4/b7e040379838cc71bf5aabdb26998dfbe5ee73904c92c1c161faf5de8866/responses-0.26.0.tar.gz", hash = "sha256:c7f6923e6343ef3682816ba421c006626777893cb0d5e1434f674b649bac9eb4", size = 81303, upload-time = "2026-02-19T14:38:05.574Z" } wheels = [ @@ -2341,8 +1752,7 @@ name = "rich" version = "14.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown-it-py" }, { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } @@ -2355,11 +1765,9 @@ name = "rich-click" version = "1.9.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "rich" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/04/27/091e140ea834272188e63f8dd6faac1f5c687582b687197b3e0ec3c78ebf/rich_click-1.9.7.tar.gz", hash = "sha256:022997c1e30731995bdbc8ec2f82819340d42543237f033a003c7b1f843fc5dc", size = 74838, upload-time = "2026-01-31T04:29:27.707Z" } wheels = [ @@ -2368,27 +1776,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/df/f8629c19c5318601d3121e230f74cbee7a3732339c52b21daa2b82ef9c7d/ruff-0.15.6.tar.gz", hash = "sha256:8394c7bb153a4e3811a4ecdacd4a8e6a4fa8097028119160dffecdcdf9b56ae4", size = 4597916, upload-time = "2026-03-12T23:05:47.51Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/2f/4e03a7e5ce99b517e98d3b4951f411de2b0fa8348d39cf446671adcce9a2/ruff-0.15.6-py3-none-linux_armv6l.whl", hash = "sha256:7c98c3b16407b2cf3d0f2b80c80187384bc92c6774d85fefa913ecd941256fff", size = 10508953, upload-time = "2026-03-12T23:05:17.246Z" }, - { url = "https://files.pythonhosted.org/packages/70/60/55bcdc3e9f80bcf39edf0cd272da6fa511a3d94d5a0dd9e0adf76ceebdb4/ruff-0.15.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ee7dcfaad8b282a284df4aa6ddc2741b3f4a18b0555d626805555a820ea181c3", size = 10942257, upload-time = "2026-03-12T23:05:23.076Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f9/005c29bd1726c0f492bfa215e95154cf480574140cb5f867c797c18c790b/ruff-0.15.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3bd9967851a25f038fc8b9ae88a7fbd1b609f30349231dffaa37b6804923c4bb", size = 10322683, upload-time = "2026-03-12T23:05:33.738Z" }, - { url = "https://files.pythonhosted.org/packages/5f/74/2f861f5fd7cbb2146bddb5501450300ce41562da36d21868c69b7a828169/ruff-0.15.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13f4594b04e42cd24a41da653886b04d2ff87adbf57497ed4f728b0e8a4866f8", size = 10660986, upload-time = "2026-03-12T23:05:53.245Z" }, - { url = "https://files.pythonhosted.org/packages/c1/a1/309f2364a424eccb763cdafc49df843c282609f47fe53aa83f38272389e0/ruff-0.15.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2ed8aea2f3fe57886d3f00ea5b8aae5bf68d5e195f487f037a955ff9fbaac9e", size = 10332177, upload-time = "2026-03-12T23:05:56.145Z" }, - { url = "https://files.pythonhosted.org/packages/30/41/7ebf1d32658b4bab20f8ac80972fb19cd4e2c6b78552be263a680edc55ac/ruff-0.15.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70789d3e7830b848b548aae96766431c0dc01a6c78c13381f423bf7076c66d15", size = 11170783, upload-time = "2026-03-12T23:06:01.742Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/6d488f6adca047df82cd62c304638bcb00821c36bd4881cfca221561fdfc/ruff-0.15.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:542aaf1de3154cea088ced5a819ce872611256ffe2498e750bbae5247a8114e9", size = 12044201, upload-time = "2026-03-12T23:05:28.697Z" }, - { url = "https://files.pythonhosted.org/packages/71/68/e6f125df4af7e6d0b498f8d373274794bc5156b324e8ab4bf5c1b4fc0ec7/ruff-0.15.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c22e6f02c16cfac3888aa636e9eba857254d15bbacc9906c9689fdecb1953ab", size = 11421561, upload-time = "2026-03-12T23:05:31.236Z" }, - { url = "https://files.pythonhosted.org/packages/f1/9f/f85ef5fd01a52e0b472b26dc1b4bd228b8f6f0435975442ffa4741278703/ruff-0.15.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98893c4c0aadc8e448cfa315bd0cc343a5323d740fe5f28ef8a3f9e21b381f7e", size = 11310928, upload-time = "2026-03-12T23:05:45.288Z" }, - { url = "https://files.pythonhosted.org/packages/8c/26/b75f8c421f5654304b89471ed384ae8c7f42b4dff58fa6ce1626d7f2b59a/ruff-0.15.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:70d263770d234912374493e8cc1e7385c5d49376e41dfa51c5c3453169dc581c", size = 11235186, upload-time = "2026-03-12T23:05:50.677Z" }, - { url = "https://files.pythonhosted.org/packages/fc/d4/d5a6d065962ff7a68a86c9b4f5500f7d101a0792078de636526c0edd40da/ruff-0.15.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:55a1ad63c5a6e54b1f21b7514dfadc0c7fb40093fa22e95143cf3f64ebdcd512", size = 10635231, upload-time = "2026-03-12T23:05:37.044Z" }, - { url = "https://files.pythonhosted.org/packages/d6/56/7c3acf3d50910375349016cf33de24be021532042afbed87942858992491/ruff-0.15.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8dc473ba093c5ec238bb1e7429ee676dca24643c471e11fbaa8a857925b061c0", size = 10340357, upload-time = "2026-03-12T23:06:04.748Z" }, - { url = "https://files.pythonhosted.org/packages/06/54/6faa39e9c1033ff6a3b6e76b5df536931cd30caf64988e112bbf91ef5ce5/ruff-0.15.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:85b042377c2a5561131767974617006f99f7e13c63c111b998f29fc1e58a4cfb", size = 10860583, upload-time = "2026-03-12T23:05:58.978Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/509a201b843b4dfb0b32acdedf68d951d3377988cae43949ba4c4133a96a/ruff-0.15.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cef49e30bc5a86a6a92098a7fbf6e467a234d90b63305d6f3ec01225a9d092e0", size = 11410976, upload-time = "2026-03-12T23:05:39.955Z" }, - { url = "https://files.pythonhosted.org/packages/6c/25/3fc9114abf979a41673ce877c08016f8e660ad6cf508c3957f537d2e9fa9/ruff-0.15.6-py3-none-win32.whl", hash = "sha256:bbf67d39832404812a2d23020dda68fee7f18ce15654e96fb1d3ad21a5fe436c", size = 10616872, upload-time = "2026-03-12T23:05:42.451Z" }, - { url = "https://files.pythonhosted.org/packages/89/7a/09ece68445ceac348df06e08bf75db72d0e8427765b96c9c0ffabc1be1d9/ruff-0.15.6-py3-none-win_amd64.whl", hash = "sha256:aee25bc84c2f1007ecb5037dff75cef00414fdf17c23f07dc13e577883dca406", size = 11787271, upload-time = "2026-03-12T23:05:20.168Z" }, - { url = "https://files.pythonhosted.org/packages/7f/d0/578c47dd68152ddddddf31cd7fc67dc30b7cdf639a86275fda821b0d9d98/ruff-0.15.6-py3-none-win_arm64.whl", hash = "sha256:c34de3dd0b0ba203be50ae70f5910b17188556630e2178fd7d79fc030eb0d837", size = 11060497, upload-time = "2026-03-12T23:05:25.968Z" }, +version = "0.15.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/22/9e4f66ee588588dc6c9af6a994e12d26e19efbe874d1a909d09a6dac7a59/ruff-0.15.7.tar.gz", hash = "sha256:04f1ae61fc20fe0b148617c324d9d009b5f63412c0b16474f3d5f1a1a665f7ac", size = 4601277, upload-time = "2026-03-19T16:26:22.605Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/2f/0b08ced94412af091807b6119ca03755d651d3d93a242682bf020189db94/ruff-0.15.7-py3-none-linux_armv6l.whl", hash = "sha256:a81cc5b6910fb7dfc7c32d20652e50fa05963f6e13ead3c5915c41ac5d16668e", size = 10489037, upload-time = "2026-03-19T16:26:32.47Z" }, + { url = "https://files.pythonhosted.org/packages/91/4a/82e0fa632e5c8b1eba5ee86ecd929e8ff327bbdbfb3c6ac5d81631bef605/ruff-0.15.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:722d165bd52403f3bdabc0ce9e41fc47070ac56d7a91b4e0d097b516a53a3477", size = 10955433, upload-time = "2026-03-19T16:27:00.205Z" }, + { url = "https://files.pythonhosted.org/packages/ab/10/12586735d0ff42526ad78c049bf51d7428618c8b5c467e72508c694119df/ruff-0.15.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7fbc2448094262552146cbe1b9643a92f66559d3761f1ad0656d4991491af49e", size = 10269302, upload-time = "2026-03-19T16:26:26.183Z" }, + { url = "https://files.pythonhosted.org/packages/eb/5d/32b5c44ccf149a26623671df49cbfbd0a0ae511ff3df9d9d2426966a8d57/ruff-0.15.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b39329b60eba44156d138275323cc726bbfbddcec3063da57caa8a8b1d50adf", size = 10607625, upload-time = "2026-03-19T16:27:03.263Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f1/f0001cabe86173aaacb6eb9bb734aa0605f9a6aa6fa7d43cb49cbc4af9c9/ruff-0.15.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87768c151808505f2bfc93ae44e5f9e7c8518943e5074f76ac21558ef5627c85", size = 10324743, upload-time = "2026-03-19T16:27:09.791Z" }, + { url = "https://files.pythonhosted.org/packages/7a/87/b8a8f3d56b8d848008559e7c9d8bf367934d5367f6d932ba779456e2f73b/ruff-0.15.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb0511670002c6c529ec66c0e30641c976c8963de26a113f3a30456b702468b0", size = 11138536, upload-time = "2026-03-19T16:27:06.101Z" }, + { url = "https://files.pythonhosted.org/packages/e4/f2/4fd0d05aab0c5934b2e1464784f85ba2eab9d54bffc53fb5430d1ed8b829/ruff-0.15.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0d19644f801849229db8345180a71bee5407b429dd217f853ec515e968a6912", size = 11994292, upload-time = "2026-03-19T16:26:48.718Z" }, + { url = "https://files.pythonhosted.org/packages/64/22/fc4483871e767e5e95d1622ad83dad5ebb830f762ed0420fde7dfa9d9b08/ruff-0.15.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4806d8e09ef5e84eb19ba833d0442f7e300b23fe3f0981cae159a248a10f0036", size = 11398981, upload-time = "2026-03-19T16:26:54.513Z" }, + { url = "https://files.pythonhosted.org/packages/b0/99/66f0343176d5eab02c3f7fcd2de7a8e0dd7a41f0d982bee56cd1c24db62b/ruff-0.15.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dce0896488562f09a27b9c91b1f58a097457143931f3c4d519690dea54e624c5", size = 11242422, upload-time = "2026-03-19T16:26:29.277Z" }, + { url = "https://files.pythonhosted.org/packages/5d/3a/a7060f145bfdcce4c987ea27788b30c60e2c81d6e9a65157ca8afe646328/ruff-0.15.7-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1852ce241d2bc89e5dc823e03cff4ce73d816b5c6cdadd27dbfe7b03217d2a12", size = 11232158, upload-time = "2026-03-19T16:26:42.321Z" }, + { url = "https://files.pythonhosted.org/packages/a7/53/90fbb9e08b29c048c403558d3cdd0adf2668b02ce9d50602452e187cd4af/ruff-0.15.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5f3e4b221fb4bd293f79912fc5e93a9063ebd6d0dcbd528f91b89172a9b8436c", size = 10577861, upload-time = "2026-03-19T16:26:57.459Z" }, + { url = "https://files.pythonhosted.org/packages/2f/aa/5f486226538fe4d0f0439e2da1716e1acf895e2a232b26f2459c55f8ddad/ruff-0.15.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b15e48602c9c1d9bdc504b472e90b90c97dc7d46c7028011ae67f3861ceba7b4", size = 10327310, upload-time = "2026-03-19T16:26:35.909Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/271afdffb81fe7bfc8c43ba079e9d96238f674380099457a74ccb3863857/ruff-0.15.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b4705e0e85cedc74b0a23cf6a179dbb3df184cb227761979cc76c0440b5ab0d", size = 10840752, upload-time = "2026-03-19T16:26:45.723Z" }, + { url = "https://files.pythonhosted.org/packages/bf/29/a4ae78394f76c7759953c47884eb44de271b03a66634148d9f7d11e721bd/ruff-0.15.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:112c1fa316a558bb34319282c1200a8bf0495f1b735aeb78bfcb2991e6087580", size = 11336961, upload-time = "2026-03-19T16:26:39.076Z" }, + { url = "https://files.pythonhosted.org/packages/26/6b/8786ba5736562220d588a2f6653e6c17e90c59ced34a2d7b512ef8956103/ruff-0.15.7-py3-none-win32.whl", hash = "sha256:6d39e2d3505b082323352f733599f28169d12e891f7dd407f2d4f54b4c2886de", size = 10582538, upload-time = "2026-03-19T16:26:15.992Z" }, + { url = "https://files.pythonhosted.org/packages/2b/e9/346d4d3fffc6871125e877dae8d9a1966b254fbd92a50f8561078b88b099/ruff-0.15.7-py3-none-win_amd64.whl", hash = "sha256:4d53d712ddebcd7dace1bc395367aec12c057aacfe9adbb6d832302575f4d3a1", size = 11755839, upload-time = "2026-03-19T16:26:19.897Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e8/726643a3ea68c727da31570bde48c7a10f1aa60eddd628d94078fec586ff/ruff-0.15.7-py3-none-win_arm64.whl", hash = "sha256:18e8d73f1c3fdf27931497972250340f92e8c861722161a9caeb89a58ead6ed2", size = 11023304, upload-time = "2026-03-19T16:26:51.669Z" }, ] [[package]] @@ -2409,19 +1817,6 @@ version = "3.20.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/41/f4/a1ac5ed32f7ed9a088d62a59d410d4c204b3b3815722e2ccfb491fa8251b/simplejson-3.20.2.tar.gz", hash = "sha256:5fe7a6ce14d1c300d80d08695b7f7e633de6cd72c80644021874d985b3393649", size = 85784, upload-time = "2025-09-26T16:29:36.64Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/09/2bf3761de89ea2d91bdce6cf107dcd858892d0adc22c995684878826cc6b/simplejson-3.20.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6d7286dc11af60a2f76eafb0c2acde2d997e87890e37e24590bb513bec9f1bc5", size = 94039, upload-time = "2025-09-26T16:27:29.283Z" }, - { url = "https://files.pythonhosted.org/packages/0f/33/c3277db8931f0ae9e54b9292668863365672d90fb0f632f4cf9829cb7d68/simplejson-3.20.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c01379b4861c3b0aa40cba8d44f2b448f5743999aa68aaa5d3ef7049d4a28a2d", size = 75894, upload-time = "2025-09-26T16:27:30.378Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ea/ae47b04d03c7c8a7b7b1a8b39a6e27c3bd424e52f4988d70aca6293ff5e5/simplejson-3.20.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a16b029ca25645b3bc44e84a4f941efa51bf93c180b31bd704ce6349d1fc77c1", size = 76116, upload-time = "2025-09-26T16:27:31.42Z" }, - { url = "https://files.pythonhosted.org/packages/4b/42/6c9af551e5a8d0f171d6dce3d9d1260068927f7b80f1f09834e07887c8c4/simplejson-3.20.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e22a5fb7b1437ffb057e02e1936a3bfb19084ae9d221ec5e9f4cf85f69946b6", size = 138827, upload-time = "2025-09-26T16:27:32.486Z" }, - { url = "https://files.pythonhosted.org/packages/2b/22/5e268bbcbe9f75577491e406ec0a5536f5b2fa91a3b52031fea51cd83e1d/simplejson-3.20.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8b6ff02fc7b8555c906c24735908854819b0d0dc85883d453e23ca4c0445d01", size = 146772, upload-time = "2025-09-26T16:27:34.036Z" }, - { url = "https://files.pythonhosted.org/packages/71/b4/800f14728e2ad666f420dfdb57697ca128aeae7f991b35759c09356b829a/simplejson-3.20.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2bfc1c396ad972ba4431130b42307b2321dba14d988580c1ac421ec6a6b7cee3", size = 134497, upload-time = "2025-09-26T16:27:35.211Z" }, - { url = "https://files.pythonhosted.org/packages/c1/b9/c54eef4226c6ac8e9a389bbe5b21fef116768f97a2dc1a683c716ffe66ef/simplejson-3.20.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a97249ee1aee005d891b5a211faf58092a309f3d9d440bc269043b08f662eda", size = 138172, upload-time = "2025-09-26T16:27:36.44Z" }, - { url = "https://files.pythonhosted.org/packages/09/36/4e282f5211b34620f1b2e4b51d9ddaab5af82219b9b7b78360a33f7e5387/simplejson-3.20.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f1036be00b5edaddbddbb89c0f80ed229714a941cfd21e51386dc69c237201c2", size = 140272, upload-time = "2025-09-26T16:27:37.605Z" }, - { url = "https://files.pythonhosted.org/packages/aa/b0/94ad2cf32f477c449e1f63c863d8a513e2408d651c4e58fe4b6a7434e168/simplejson-3.20.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5d6f5bacb8cdee64946b45f2680afa3f54cd38e62471ceda89f777693aeca4e4", size = 140468, upload-time = "2025-09-26T16:27:39.015Z" }, - { url = "https://files.pythonhosted.org/packages/e5/46/827731e4163be3f987cb8ee90f5d444161db8f540b5e735355faa098d9bc/simplejson-3.20.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8db6841fb796ec5af632f677abf21c6425a1ebea0d9ac3ef1a340b8dc69f52b8", size = 148700, upload-time = "2025-09-26T16:27:40.171Z" }, - { url = "https://files.pythonhosted.org/packages/c7/28/c32121064b1ec2fb7b5d872d9a1abda62df064d35e0160eddfa907118343/simplejson-3.20.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0a341f7cc2aae82ee2b31f8a827fd2e51d09626f8b3accc441a6907c88aedb7", size = 141323, upload-time = "2025-09-26T16:27:41.324Z" }, - { url = "https://files.pythonhosted.org/packages/46/b6/c897c54326fe86dd12d101981171a49361949f4728294f418c3b86a1af77/simplejson-3.20.2-cp310-cp310-win32.whl", hash = "sha256:27f9c01a6bc581d32ab026f515226864576da05ef322d7fc141cd8a15a95ce53", size = 74377, upload-time = "2025-09-26T16:27:42.533Z" }, - { url = "https://files.pythonhosted.org/packages/ad/87/a6e03d4d80cca99c1fee4e960f3440e2f21be9470e537970f960ca5547f1/simplejson-3.20.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0a63ec98a4547ff366871bf832a7367ee43d047bcec0b07b66c794e2137b476", size = 76081, upload-time = "2025-09-26T16:27:43.945Z" }, { url = "https://files.pythonhosted.org/packages/b9/3e/96898c6c66d9dca3f9bd14d7487bf783b4acc77471b42f979babbb68d4ca/simplejson-3.20.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:06190b33cd7849efc413a5738d3da00b90e4a5382fd3d584c841ac20fb828c6f", size = 92633, upload-time = "2025-09-26T16:27:45.028Z" }, { url = "https://files.pythonhosted.org/packages/6b/a2/cd2e10b880368305d89dd540685b8bdcc136df2b3c76b5ddd72596254539/simplejson-3.20.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4ad4eac7d858947a30d2c404e61f16b84d16be79eb6fb316341885bdde864fa8", size = 75309, upload-time = "2025-09-26T16:27:46.142Z" }, { url = "https://files.pythonhosted.org/packages/5d/02/290f7282eaa6ebe945d35c47e6534348af97472446951dce0d144e013f4c/simplejson-3.20.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b392e11c6165d4a0fde41754a0e13e1d88a5ad782b245a973dd4b2bdb4e5076a", size = 75308, upload-time = "2025-09-26T16:27:47.542Z" }, @@ -2461,19 +1856,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/21/603709455827cdf5b9d83abe726343f542491ca8dc6a2528eb08de0cf034/simplejson-3.20.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f28ee755fadb426ba2e464d6fcf25d3f152a05eb6b38e0b4f790352f5540c769", size = 154717, upload-time = "2025-09-26T16:28:30.288Z" }, { url = "https://files.pythonhosted.org/packages/3c/f9/dc7f7a4bac16cf7eb55a4df03ad93190e11826d2a8950052949d3dfc11e2/simplejson-3.20.2-cp313-cp313-win32.whl", hash = "sha256:472785b52e48e3eed9b78b95e26a256f59bb1ee38339be3075dad799e2e1e661", size = 74289, upload-time = "2025-09-26T16:28:31.809Z" }, { url = "https://files.pythonhosted.org/packages/87/10/d42ad61230436735c68af1120622b28a782877146a83d714da7b6a2a1c4e/simplejson-3.20.2-cp313-cp313-win_amd64.whl", hash = "sha256:a1a85013eb33e4820286139540accbe2c98d2da894b2dcefd280209db508e608", size = 75972, upload-time = "2025-09-26T16:28:32.883Z" }, - { url = "https://files.pythonhosted.org/packages/b8/2d/7c4968c60ddc8b504b77301cc80d6e75cd0269b81a779b01d66d8f36dcb8/simplejson-3.20.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b3bf76512ccb07d47944ebdca44c65b781612d38b9098566b4bb40f713fc4047", size = 94039, upload-time = "2025-09-26T16:29:17.406Z" }, - { url = "https://files.pythonhosted.org/packages/e8/e4/d96b56fb87f245240b514c1fe552e76c17e09f0faa1f61137b2296f81529/simplejson-3.20.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:214e26acf2dfb9ff3314e65c4e168a6b125bced0e2d99a65ea7b0f169db1e562", size = 75893, upload-time = "2025-09-26T16:29:18.534Z" }, - { url = "https://files.pythonhosted.org/packages/09/4f/be411eeb52ab21d6d4c00722b632dd2bd430c01a47dfed3c15ef5ad7ee6e/simplejson-3.20.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2fb1259ca9c385b0395bad59cdbf79535a5a84fb1988f339a49bfbc57455a35a", size = 76104, upload-time = "2025-09-26T16:29:19.66Z" }, - { url = "https://files.pythonhosted.org/packages/66/6f/3bd0007b64881a90a058c59a4869b1b4f130ddb86a726f884fafc67e5ef7/simplejson-3.20.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c34e028a2ba8553a208ded1da5fa8501833875078c4c00a50dffc33622057881", size = 138261, upload-time = "2025-09-26T16:29:20.822Z" }, - { url = "https://files.pythonhosted.org/packages/15/5d/b6d0b71508e503c759a0a7563cb2c28716ec8af9828ca9f5b59023011406/simplejson-3.20.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b538f9d9e503b0dd43af60496780cb50755e4d8e5b34e5647b887675c1ae9fee", size = 146397, upload-time = "2025-09-26T16:29:22.363Z" }, - { url = "https://files.pythonhosted.org/packages/19/24/40b3e5a3ca5e6f80cc1c639fcd5565ae087e72e8656dea780f02302ddc97/simplejson-3.20.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab998e416ded6c58f549a22b6a8847e75a9e1ef98eb9fbb2863e1f9e61a4105b", size = 134020, upload-time = "2025-09-26T16:29:23.615Z" }, - { url = "https://files.pythonhosted.org/packages/b9/8c/8fc2c2734ac9e514124635b25ca8f7e347db1ded4a30417ee41e78e6d61c/simplejson-3.20.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a8f1c307edf5fbf0c6db3396c5d3471409c4a40c7a2a466fbc762f20d46601a", size = 137598, upload-time = "2025-09-26T16:29:24.835Z" }, - { url = "https://files.pythonhosted.org/packages/2e/d9/15036d7f43c6208fb0fbc827f9f897c1f577fba02aeb7a8a223581da4925/simplejson-3.20.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5a7bbac80bdb82a44303f5630baee140aee208e5a4618e8b9fde3fc400a42671", size = 139770, upload-time = "2025-09-26T16:29:26.244Z" }, - { url = "https://files.pythonhosted.org/packages/73/cc/18374fb9dfcb4827b692ca5a33bdb607384ca06cdb645e0b863022dae8a3/simplejson-3.20.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5ef70ec8fe1569872e5a3e4720c1e1dcb823879a3c78bc02589eb88fab920b1f", size = 139884, upload-time = "2025-09-26T16:29:28.51Z" }, - { url = "https://files.pythonhosted.org/packages/5c/a2/1526d4152806670124dd499ff831726a92bd7e029e8349c4affa78ea8845/simplejson-3.20.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:cb11c09c99253a74c36925d461c86ea25f0140f3b98ff678322734ddc0f038d7", size = 148166, upload-time = "2025-09-26T16:29:29.789Z" }, - { url = "https://files.pythonhosted.org/packages/a4/77/fc16d41b5f67a2591c9b6ff7b0f6aed2b2aed1b6912bb346b61279697638/simplejson-3.20.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:66f7c78c6ef776f8bd9afaad455e88b8197a51e95617bcc44b50dd974a7825ba", size = 140778, upload-time = "2025-09-26T16:29:31.025Z" }, - { url = "https://files.pythonhosted.org/packages/4a/97/a26ef6b7387349623c042f329df70a4f3baf3a365fe6d1154d73da1dcf5a/simplejson-3.20.2-cp39-cp39-win32.whl", hash = "sha256:619ada86bfe3a5aa02b8222ca6bfc5aa3e1075c1fb5b3263d24ba579382df472", size = 74339, upload-time = "2025-09-26T16:29:32.648Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b7/94c6049a99e3c04eed2064e91295370b7429e2361188e35a78df562312e0/simplejson-3.20.2-cp39-cp39-win_amd64.whl", hash = "sha256:44a6235e09ca5cc41aa5870a952489c06aa4aee3361ae46daa947d8398e57502", size = 76067, upload-time = "2025-09-26T16:29:34.184Z" }, { url = "https://files.pythonhosted.org/packages/05/5b/83e1ff87eb60ca706972f7e02e15c0b33396e7bdbd080069a5d1b53cf0d8/simplejson-3.20.2-py3-none-any.whl", hash = "sha256:3b6bb7fb96efd673eac2e4235200bfffdc2353ad12c54117e1e4e2fc485ac017", size = 57309, upload-time = "2025-09-26T16:29:35.312Z" }, ] @@ -2496,24 +1878,15 @@ wheels = [ ] [[package]] -name = "tenacity" -version = "9.1.2" +name = "stringcase" +version = "1.2.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, -] +sdist = { url = "https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008", size = 2958, upload-time = "2017-08-06T01:40:57.021Z" } [[package]] name = "tenacity" version = "9.1.4" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, @@ -2634,25 +2007,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] -[[package]] -name = "urllib3" -version = "1.26.20" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380, upload-time = "2024-08-29T15:43:11.37Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225, upload-time = "2024-08-29T15:43:08.921Z" }, -] - [[package]] name = "urllib3" version = "2.6.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, @@ -2664,9 +2022,6 @@ version = "6.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/56/90994d789c61df619bfc5ce2ecdabd5eeff564e1eb47512bd01b5e019569/watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26", size = 96390, upload-time = "2024-11-01T14:06:24.793Z" }, - { url = "https://files.pythonhosted.org/packages/55/46/9a67ee697342ddf3c6daa97e3a587a56d6c4052f881ed926a849fcf7371c/watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112", size = 88389, upload-time = "2024-11-01T14:06:27.112Z" }, - { url = "https://files.pythonhosted.org/packages/44/65/91b0985747c52064d8701e1075eb96f8c40a79df889e59a399453adfb882/watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3", size = 89020, upload-time = "2024-11-01T14:06:29.876Z" }, { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" }, { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" }, { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" }, @@ -2676,13 +2031,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, - { url = "https://files.pythonhosted.org/packages/05/52/7223011bb760fce8ddc53416beb65b83a3ea6d7d13738dde75eeb2c89679/watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8", size = 96390, upload-time = "2024-11-01T14:06:49.325Z" }, - { url = "https://files.pythonhosted.org/packages/9c/62/d2b21bc4e706d3a9d467561f487c2938cbd881c69f3808c43ac1ec242391/watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a", size = 88386, upload-time = "2024-11-01T14:06:50.536Z" }, - { url = "https://files.pythonhosted.org/packages/ea/22/1c90b20eda9f4132e4603a26296108728a8bfe9584b006bd05dd94548853/watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c", size = 89017, upload-time = "2024-11-01T14:06:51.717Z" }, - { url = "https://files.pythonhosted.org/packages/30/ad/d17b5d42e28a8b91f8ed01cb949da092827afb9995d4559fd448d0472763/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881", size = 87902, upload-time = "2024-11-01T14:06:53.119Z" }, - { url = "https://files.pythonhosted.org/packages/5c/ca/c3649991d140ff6ab67bfc85ab42b165ead119c9e12211e08089d763ece5/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11", size = 88380, upload-time = "2024-11-01T14:06:55.19Z" }, - { url = "https://files.pythonhosted.org/packages/5b/79/69f2b0e8d3f2afd462029031baafb1b75d11bb62703f0e1022b2e54d49ee/watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa", size = 87903, upload-time = "2024-11-01T14:06:57.052Z" }, - { url = "https://files.pythonhosted.org/packages/e2/2b/dc048dd71c2e5f0f7ebc04dd7912981ec45793a03c0dc462438e0591ba5d/watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e", size = 88381, upload-time = "2024-11-01T14:06:58.193Z" }, { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, @@ -2748,12 +2096,3 @@ sdist = { url = "https://files.pythonhosted.org/packages/19/70/80f3b7c10d2630aa6 wheels = [ { url = "https://files.pythonhosted.org/packages/38/34/98a2f52245f4d47be93b580dae5f9861ef58977d73a79eb47c58f1ad1f3a/xmltodict-1.0.4-py3-none-any.whl", hash = "sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a", size = 13580, upload-time = "2026-02-22T02:21:21.039Z" }, ] - -[[package]] -name = "zipp" -version = "3.23.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, -]