diff --git a/aws_lambda_powertools/utilities/parser/functions.py b/aws_lambda_powertools/utilities/parser/functions.py index 696437a6550..4cf3f131395 100644 --- a/aws_lambda_powertools/utilities/parser/functions.py +++ b/aws_lambda_powertools/utilities/parser/functions.py @@ -1,9 +1,13 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from pydantic import TypeAdapter from aws_lambda_powertools.shared.cache_dict import LRUDict -from aws_lambda_powertools.utilities.parser.types import T + +if TYPE_CHECKING: + from aws_lambda_powertools.utilities.parser.types import T CACHE_TYPE_ADAPTER = LRUDict(max_items=1024) diff --git a/aws_lambda_powertools/utilities/parser/models/apigw.py b/aws_lambda_powertools/utilities/parser/models/apigw.py index 301360b556d..f19530a3e25 100644 --- a/aws_lambda_powertools/utilities/parser/models/apigw.py +++ b/aws_lambda_powertools/utilities/parser/models/apigw.py @@ -1,11 +1,9 @@ from datetime import datetime -from typing import Any, Dict, List, Optional, Type, Union +from typing import Any, Dict, List, Literal, Optional, Type, Union from pydantic import BaseModel, model_validator from pydantic.networks import IPvAnyNetwork -from aws_lambda_powertools.utilities.parser.types import Literal - class ApiGatewayUserCertValidity(BaseModel): notBefore: str diff --git a/aws_lambda_powertools/utilities/parser/models/apigwv2.py b/aws_lambda_powertools/utilities/parser/models/apigwv2.py index 8f0f8dbf50c..9c6638993a9 100644 --- a/aws_lambda_powertools/utilities/parser/models/apigwv2.py +++ b/aws_lambda_powertools/utilities/parser/models/apigwv2.py @@ -1,11 +1,9 @@ from datetime import datetime -from typing import Any, Dict, List, Optional, Type, Union +from typing import Any, Dict, List, Literal, Optional, Type, Union from pydantic import BaseModel, Field from pydantic.networks import IPvAnyNetwork -from aws_lambda_powertools.utilities.parser.types import Literal - class RequestContextV2AuthorizerIamCognito(BaseModel): amr: List[str] diff --git a/aws_lambda_powertools/utilities/parser/models/cloudformation_custom_resource.py b/aws_lambda_powertools/utilities/parser/models/cloudformation_custom_resource.py index 27e9ba996aa..fcdb749afde 100644 --- a/aws_lambda_powertools/utilities/parser/models/cloudformation_custom_resource.py +++ b/aws_lambda_powertools/utilities/parser/models/cloudformation_custom_resource.py @@ -1,9 +1,7 @@ -from typing import Any, Dict, Union +from typing import Any, Dict, Literal, Union from pydantic import BaseModel, Field, HttpUrl -from aws_lambda_powertools.utilities.parser.types import Literal - class CloudFormationCustomResourceBaseModel(BaseModel): request_type: str = Field(..., alias="RequestType") diff --git a/aws_lambda_powertools/utilities/parser/models/dynamodb.py b/aws_lambda_powertools/utilities/parser/models/dynamodb.py index 7a3581ab13f..99d82c7853d 100644 --- a/aws_lambda_powertools/utilities/parser/models/dynamodb.py +++ b/aws_lambda_powertools/utilities/parser/models/dynamodb.py @@ -1,10 +1,10 @@ +# ruff: noqa: FA100 from datetime import datetime -from typing import Any, Dict, List, Optional, Type, Union +from typing import Any, Dict, List, Literal, Optional, Type, Union from pydantic import BaseModel, field_validator from aws_lambda_powertools.shared.dynamodb_deserializer import TypeDeserializer -from aws_lambda_powertools.utilities.parser.types import Literal _DESERIALIZER = TypeDeserializer() diff --git a/aws_lambda_powertools/utilities/parser/models/kafka.py b/aws_lambda_powertools/utilities/parser/models/kafka.py index ea81408d301..4969f7f427b 100644 --- a/aws_lambda_powertools/utilities/parser/models/kafka.py +++ b/aws_lambda_powertools/utilities/parser/models/kafka.py @@ -1,10 +1,9 @@ from datetime import datetime -from typing import Dict, List, Type, Union +from typing import Dict, List, Literal, Type, Union from pydantic import BaseModel, field_validator from aws_lambda_powertools.shared.functions import base64_decode, bytes_to_string -from aws_lambda_powertools.utilities.parser.types import Literal SERVERS_DELIMITER = "," diff --git a/aws_lambda_powertools/utilities/parser/models/kinesis.py b/aws_lambda_powertools/utilities/parser/models/kinesis.py index be81eb5fa92..4b1a93fd226 100644 --- a/aws_lambda_powertools/utilities/parser/models/kinesis.py +++ b/aws_lambda_powertools/utilities/parser/models/kinesis.py @@ -1,6 +1,6 @@ import json import zlib -from typing import Dict, List, Type, Union +from typing import Dict, List, Literal, Type, Union from pydantic import BaseModel, field_validator @@ -8,7 +8,6 @@ from aws_lambda_powertools.utilities.parser.models.cloudwatch import ( CloudWatchLogsDecode, ) -from aws_lambda_powertools.utilities.parser.types import Literal class KinesisDataStreamRecordPayload(BaseModel): diff --git a/aws_lambda_powertools/utilities/parser/models/s3.py b/aws_lambda_powertools/utilities/parser/models/s3.py index cfba76fb078..4de89d42c78 100644 --- a/aws_lambda_powertools/utilities/parser/models/s3.py +++ b/aws_lambda_powertools/utilities/parser/models/s3.py @@ -1,13 +1,11 @@ from datetime import datetime -from typing import List, Optional +from typing import List, Literal, Optional from pydantic import BaseModel, model_validator from pydantic.fields import Field from pydantic.networks import IPvAnyNetwork from pydantic.types import NonNegativeFloat -from aws_lambda_powertools.utilities.parser.types import Literal - from .event_bridge import EventBridgeModel diff --git a/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py b/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py index affff0921fb..934ace9ac07 100644 --- a/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py +++ b/aws_lambda_powertools/utilities/parser/models/s3_batch_operation.py @@ -1,9 +1,7 @@ -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Literal, Optional from pydantic import BaseModel, model_validator -from aws_lambda_powertools.utilities.parser.types import Literal - class S3BatchOperationTaskModel(BaseModel): taskId: str diff --git a/aws_lambda_powertools/utilities/parser/models/ses.py b/aws_lambda_powertools/utilities/parser/models/ses.py index 2e9e93f368e..59a5226292f 100644 --- a/aws_lambda_powertools/utilities/parser/models/ses.py +++ b/aws_lambda_powertools/utilities/parser/models/ses.py @@ -1,11 +1,9 @@ from datetime import datetime -from typing import List, Optional +from typing import List, Literal, Optional from pydantic import BaseModel, Field from pydantic.types import PositiveInt -from ..types import Literal - class SesReceiptVerdict(BaseModel): status: Literal["PASS", "FAIL", "GRAY", "PROCESSING_FAILED"] diff --git a/aws_lambda_powertools/utilities/parser/models/sns.py b/aws_lambda_powertools/utilities/parser/models/sns.py index 6dccf956f8a..585489e9323 100644 --- a/aws_lambda_powertools/utilities/parser/models/sns.py +++ b/aws_lambda_powertools/utilities/parser/models/sns.py @@ -1,12 +1,10 @@ from datetime import datetime -from typing import Dict, List, Optional, Union +from typing import Dict, List, Literal, Optional, Union from typing import Type as TypingType from pydantic import BaseModel, model_validator from pydantic.networks import HttpUrl -from aws_lambda_powertools.utilities.parser.types import Literal - class SnsMsgAttributeModel(BaseModel): Type: str diff --git a/aws_lambda_powertools/utilities/parser/models/sqs.py b/aws_lambda_powertools/utilities/parser/models/sqs.py index 317b76c3227..efa5130bf06 100644 --- a/aws_lambda_powertools/utilities/parser/models/sqs.py +++ b/aws_lambda_powertools/utilities/parser/models/sqs.py @@ -1,10 +1,8 @@ from datetime import datetime -from typing import Dict, List, Optional, Sequence, Type, Union +from typing import Dict, List, Literal, Optional, Sequence, Type, Union from pydantic import BaseModel -from aws_lambda_powertools.utilities.parser.types import Literal - class SqsAttributesModel(BaseModel): ApproximateReceiveCount: str diff --git a/aws_lambda_powertools/utilities/parser/parser.py b/aws_lambda_powertools/utilities/parser/parser.py index 26a6c439704..3d2f236c75e 100644 --- a/aws_lambda_powertools/utilities/parser/parser.py +++ b/aws_lambda_powertools/utilities/parser/parser.py @@ -2,16 +2,18 @@ import logging import typing -from typing import Any, Callable, Dict, Optional, Type, overload +from typing import TYPE_CHECKING, Any, Callable, overload from pydantic import PydanticSchemaGenerationError, ValidationError from aws_lambda_powertools.middleware_factory import lambda_handler_decorator -from aws_lambda_powertools.utilities.parser.envelopes.base import Envelope from aws_lambda_powertools.utilities.parser.exceptions import InvalidEnvelopeError, InvalidModelTypeError from aws_lambda_powertools.utilities.parser.functions import _retrieve_or_set_model_from_cache -from aws_lambda_powertools.utilities.parser.types import EventParserReturnType, T -from aws_lambda_powertools.utilities.typing import LambdaContext + +if TYPE_CHECKING: + from aws_lambda_powertools.utilities.parser.envelopes.base import Envelope + from aws_lambda_powertools.utilities.parser.types import EventParserReturnType, T + from aws_lambda_powertools.utilities.typing import LambdaContext logger = logging.getLogger(__name__) @@ -19,10 +21,10 @@ @lambda_handler_decorator def event_parser( handler: Callable[..., EventParserReturnType], - event: Dict[str, Any], + event: dict[str, Any], context: LambdaContext, - model: Optional[type[T]] = None, - envelope: Optional[Type[Envelope]] = None, + model: type[T] | None = None, + envelope: type[Envelope] | None = None, **kwargs: Any, ) -> EventParserReturnType: """Lambda handler decorator to parse & validate events using Pydantic models @@ -67,11 +69,11 @@ def handler(event: Order, context: LambdaContext): ---------- handler: Callable Method to annotate on - event: Dict + event: dict Lambda event to be parsed & validated context: LambdaContext Lambda context object - model: Optional[type[T]] + model: type[T] | None Your data model that will replace the event. envelope: Envelope Optional envelope to extract the model from @@ -111,14 +113,14 @@ def handler(event: Order, context: LambdaContext): @overload -def parse(event: Dict[str, Any], model: type[T]) -> T: ... # pragma: no cover +def parse(event: dict[str, Any], model: type[T]) -> T: ... # pragma: no cover @overload -def parse(event: Dict[str, Any], model: type[T], envelope: Type[Envelope]) -> T: ... # pragma: no cover +def parse(event: dict[str, Any], model: type[T], envelope: type[Envelope]) -> T: ... # pragma: no cover -def parse(event: Dict[str, Any], model: type[T], envelope: Optional[Type[Envelope]] = None): +def parse(event: dict[str, Any], model: type[T], envelope: type[Envelope] | None = None): """Standalone function to parse & validate events using Pydantic models Typically used when you need fine-grained control over error handling compared to event_parser decorator. @@ -156,7 +158,7 @@ def handler(event: Order, context: LambdaContext): Parameters ---------- - event: Dict + event: dict Lambda event to be parsed & validated model: Model Your data model that will replace the event diff --git a/ruff.toml b/ruff.toml index 374a183541b..264870c35df 100644 --- a/ruff.toml +++ b/ruff.toml @@ -90,3 +90,6 @@ split-on-trailing-comma = true "aws_lambda_powertools/event_handler/openapi/compat.py" = ["F401"] # Maintenance: we're keeping EphemeralMetrics code in case of Hyrum's law so we can quickly revert it "aws_lambda_powertools/metrics/metrics.py" = ["ERA001"] +"examples/*" = ["FA100"] +"tests/*" = ["FA100"] +"aws_lambda_powertools/utilities/parser/models/*" = ["FA100"] \ No newline at end of file