Skip to content

Commit

Permalink
refactor(parser): add from __future__ import annotations (#4983)
Browse files Browse the repository at this point in the history
* refactor(parser): add from __future__ import annotations

and update code according to ruff rules TCH, UP006, UP007, UP037 and
FA100.

* Fix type alias with Python 3.8

See https://bugs.python.org/issue45117

* Fix pydantic not working with Python 3.8

    TypeError: You have a type annotation 'str | None' which makes use
    of newer typing features than are supported in your version of Python.
    To handle this error, you should either remove the use of new syntax
    or install the `eval_type_backport` package.

* Update ruff.toml

Configure lint.per-file-ignores in ruff.toml instead of adding a

    # ruff: noqa: FA100

line to each file.

---------

Co-authored-by: Leandro Damascena <[email protected]>
  • Loading branch information
ericbn and leandrodamascena authored Aug 18, 2024
1 parent a0463d1 commit 4688495
Show file tree
Hide file tree
Showing 14 changed files with 35 additions and 44 deletions.
6 changes: 5 additions & 1 deletion aws_lambda_powertools/utilities/parser/functions.py
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
4 changes: 1 addition & 3 deletions aws_lambda_powertools/utilities/parser/models/apigw.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 1 addition & 3 deletions aws_lambda_powertools/utilities/parser/models/apigwv2.py
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
Original file line number Diff line number Diff line change
@@ -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")
Expand Down
4 changes: 2 additions & 2 deletions aws_lambda_powertools/utilities/parser/models/dynamodb.py
Original file line number Diff line number Diff line change
@@ -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()

Expand Down
3 changes: 1 addition & 2 deletions aws_lambda_powertools/utilities/parser/models/kafka.py
Original file line number Diff line number Diff line change
@@ -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 = ","

Expand Down
3 changes: 1 addition & 2 deletions aws_lambda_powertools/utilities/parser/models/kinesis.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
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

from aws_lambda_powertools.shared.functions import base64_decode
from aws_lambda_powertools.utilities.parser.models.cloudwatch import (
CloudWatchLogsDecode,
)
from aws_lambda_powertools.utilities.parser.types import Literal


class KinesisDataStreamRecordPayload(BaseModel):
Expand Down
4 changes: 1 addition & 3 deletions aws_lambda_powertools/utilities/parser/models/s3.py
Original file line number Diff line number Diff line change
@@ -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


Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 1 addition & 3 deletions aws_lambda_powertools/utilities/parser/models/ses.py
Original file line number Diff line number Diff line change
@@ -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"]
Expand Down
4 changes: 1 addition & 3 deletions aws_lambda_powertools/utilities/parser/models/sns.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 1 addition & 3 deletions aws_lambda_powertools/utilities/parser/models/sqs.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
28 changes: 15 additions & 13 deletions aws_lambda_powertools/utilities/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,29 @@

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__)


@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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

0 comments on commit 4688495

Please sign in to comment.