From 5b113cf5d21d8ab1f34b4c4e1067cbf256e28e64 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 15 Apr 2025 17:59:07 +0100 Subject: [PATCH 1/4] Using generics types --- aws_lambda_powertools/utilities/batch/base.py | 4 +++- .../utilities/batch/decorators.py | 4 +++- .../batch/_pydantic/sample_models.py | 9 ++++---- .../test_utilities_batch_pydantic.py | 21 ++++++++++++------- .../test_utilities_batch.py | 9 ++++++-- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/aws_lambda_powertools/utilities/batch/base.py b/aws_lambda_powertools/utilities/batch/base.py index 2cb74296ca0..c70419873a1 100644 --- a/aws_lambda_powertools/utilities/batch/base.py +++ b/aws_lambda_powertools/utilities/batch/base.py @@ -14,7 +14,7 @@ import sys from abc import ABC, abstractmethod from enum import Enum -from typing import TYPE_CHECKING, Any, Callable, Tuple, Union, overload +from typing import TYPE_CHECKING, Any, Tuple, Union, overload from aws_lambda_powertools.shared import constants from aws_lambda_powertools.utilities.batch.exceptions import ( @@ -31,6 +31,8 @@ from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord if TYPE_CHECKING: + from collections.abc import Callable + from aws_lambda_powertools.utilities.batch.types import ( PartialItemFailureResponse, PartialItemFailures, diff --git a/aws_lambda_powertools/utilities/batch/decorators.py b/aws_lambda_powertools/utilities/batch/decorators.py index 2b9f5433e70..320535141fc 100644 --- a/aws_lambda_powertools/utilities/batch/decorators.py +++ b/aws_lambda_powertools/utilities/batch/decorators.py @@ -1,7 +1,7 @@ from __future__ import annotations import warnings -from typing import TYPE_CHECKING, Any, Awaitable, Callable +from typing import TYPE_CHECKING, Any from typing_extensions import deprecated @@ -16,6 +16,8 @@ from aws_lambda_powertools.warnings import PowertoolsDeprecationWarning if TYPE_CHECKING: + from collections.abc import Awaitable, Callable + from aws_lambda_powertools.utilities.batch.types import PartialItemFailureResponse from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/tests/functional/batch/_pydantic/sample_models.py b/tests/functional/batch/_pydantic/sample_models.py index c2912b3f8a3..dba2f8a7744 100644 --- a/tests/functional/batch/_pydantic/sample_models.py +++ b/tests/functional/batch/_pydantic/sample_models.py @@ -1,5 +1,6 @@ +from __future__ import annotations + import json -from typing import Dict, Optional from pydantic import field_validator @@ -36,7 +37,7 @@ class OrderDynamoDB(BaseModel): # auto transform json string # so Pydantic can auto-initialize nested Order model @field_validator("Message", mode="before") - def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): + def transform_message_to_dict(cls, value: dict[Literal["S"], str]): try: return json.loads(value) except TypeError: @@ -44,8 +45,8 @@ def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: Optional[OrderDynamoDB] = None - OldImage: Optional[OrderDynamoDB] = None + NewImage: OrderDynamoDB | None = None + OldImage: OrderDynamoDB | None = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): diff --git a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py index 382cbdb0335..26c5998d78f 100644 --- a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py +++ b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import json import uuid from random import randint -from typing import Any, Awaitable, Callable, Dict, Optional +from typing import TYPE_CHECKING, Any import pytest from pydantic import BaseModel, field_validator @@ -33,6 +35,9 @@ ) from tests.functional.utils import b64_to_str, str_to_b64 +if TYPE_CHECKING: + from collections.abc import Awaitable, Callable + @pytest.fixture(scope="module") def sqs_event_fifo_factory() -> Callable: @@ -236,7 +241,7 @@ async def record_handler(record: OrderDynamoDBRecord): @pytest.fixture(scope="module") def order_event_factory() -> Callable: - def factory(item: Dict) -> str: + def factory(item: dict[str, Any]) -> str: return json.dumps({"item": item}) return factory @@ -307,12 +312,12 @@ class OrderDynamoDB(BaseModel): # auto transform json string # so Pydantic can auto-initialize nested Order model @field_validator("Message", mode="before") - def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): + def transform_message_to_dict(cls, value: dict[Literal["S"], str]): return json.loads(value) class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: Optional[OrderDynamoDB] = None - OldImage: Optional[OrderDynamoDB] = None + NewImage: OrderDynamoDB | None = None + OldImage: OrderDynamoDB | None = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): dynamodb: OrderDynamoDBChangeRecord @@ -351,12 +356,12 @@ class OrderDynamoDB(BaseModel): # auto transform json string # so Pydantic can auto-initialize nested Order model @field_validator("Message", mode="before") - def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): + def transform_message_to_dict(cls, value: dict[Literal["S"], str]): return json.loads(value) class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: Optional[OrderDynamoDB] = None - OldImage: Optional[OrderDynamoDB] = None + NewImage: OrderDynamoDB | None = None + OldImage: OrderDynamoDB | None = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): dynamodb: OrderDynamoDBChangeRecord diff --git a/tests/functional/batch/required_dependencies/test_utilities_batch.py b/tests/functional/batch/required_dependencies/test_utilities_batch.py index 4c91dd54a1e..2a31c13946d 100644 --- a/tests/functional/batch/required_dependencies/test_utilities_batch.py +++ b/tests/functional/batch/required_dependencies/test_utilities_batch.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import json import uuid from random import randint -from typing import Any, Awaitable, Callable, Dict +from typing import TYPE_CHECKING, Any import pytest @@ -26,6 +28,9 @@ from aws_lambda_powertools.warnings import PowertoolsDeprecationWarning from tests.functional.utils import b64_to_str, str_to_b64 +if TYPE_CHECKING: + from collections.abc import Awaitable, Callable + @pytest.fixture(scope="module") def sqs_event_fifo_factory() -> Callable: @@ -169,7 +174,7 @@ def handler(record: DynamoDBRecord): @pytest.fixture(scope="module") def order_event_factory() -> Callable: - def factory(item: Dict) -> str: + def factory(item: dict[str, Any]) -> str: return json.dumps({"item": item}) return factory From 92067bdb3b14a7ac9904efa79a9237194c11a0df Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 15 Apr 2025 18:46:49 +0100 Subject: [PATCH 2/4] Using generics types --- .../_pydantic/test_utilities_batch_pydantic.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py index 26c5998d78f..2d15291780b 100644 --- a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py +++ b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py @@ -1,9 +1,7 @@ -from __future__ import annotations - import json import uuid from random import randint -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Dict, Optional import pytest from pydantic import BaseModel, field_validator @@ -241,7 +239,7 @@ async def record_handler(record: OrderDynamoDBRecord): @pytest.fixture(scope="module") def order_event_factory() -> Callable: - def factory(item: dict[str, Any]) -> str: + def factory(item: Dict) -> str: return json.dumps({"item": item}) return factory @@ -312,12 +310,12 @@ class OrderDynamoDB(BaseModel): # auto transform json string # so Pydantic can auto-initialize nested Order model @field_validator("Message", mode="before") - def transform_message_to_dict(cls, value: dict[Literal["S"], str]): + def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): return json.loads(value) class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: OrderDynamoDB | None = None - OldImage: OrderDynamoDB | None = None + NewImage: Optional[OrderDynamoDB] = None + OldImage: Optional[OrderDynamoDB] = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): dynamodb: OrderDynamoDBChangeRecord @@ -356,12 +354,12 @@ class OrderDynamoDB(BaseModel): # auto transform json string # so Pydantic can auto-initialize nested Order model @field_validator("Message", mode="before") - def transform_message_to_dict(cls, value: dict[Literal["S"], str]): + def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): return json.loads(value) class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: OrderDynamoDB | None = None - OldImage: OrderDynamoDB | None = None + NewImage: Optional[OrderDynamoDB] = None + OldImage: Optional[OrderDynamoDB] = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel): dynamodb: OrderDynamoDBChangeRecord From 7dfdc9ef7118a4b73d41a1efff24393d95565aab Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 15 Apr 2025 19:03:59 +0100 Subject: [PATCH 3/4] Using generics types --- .../batch/_pydantic/test_utilities_batch_pydantic.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py index 2d15291780b..382cbdb0335 100644 --- a/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py +++ b/tests/functional/batch/_pydantic/test_utilities_batch_pydantic.py @@ -1,7 +1,7 @@ import json import uuid from random import randint -from typing import TYPE_CHECKING, Any, Dict, Optional +from typing import Any, Awaitable, Callable, Dict, Optional import pytest from pydantic import BaseModel, field_validator @@ -33,9 +33,6 @@ ) from tests.functional.utils import b64_to_str, str_to_b64 -if TYPE_CHECKING: - from collections.abc import Awaitable, Callable - @pytest.fixture(scope="module") def sqs_event_fifo_factory() -> Callable: From ae39605f9be45f0526c72dec76c18ab0bf11ab0e Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 15 Apr 2025 20:22:21 +0100 Subject: [PATCH 4/4] Using generics types --- tests/functional/batch/_pydantic/sample_models.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/functional/batch/_pydantic/sample_models.py b/tests/functional/batch/_pydantic/sample_models.py index dba2f8a7744..c2912b3f8a3 100644 --- a/tests/functional/batch/_pydantic/sample_models.py +++ b/tests/functional/batch/_pydantic/sample_models.py @@ -1,6 +1,5 @@ -from __future__ import annotations - import json +from typing import Dict, Optional from pydantic import field_validator @@ -37,7 +36,7 @@ class OrderDynamoDB(BaseModel): # auto transform json string # so Pydantic can auto-initialize nested Order model @field_validator("Message", mode="before") - def transform_message_to_dict(cls, value: dict[Literal["S"], str]): + def transform_message_to_dict(cls, value: Dict[Literal["S"], str]): try: return json.loads(value) except TypeError: @@ -45,8 +44,8 @@ def transform_message_to_dict(cls, value: dict[Literal["S"], str]): class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel): - NewImage: OrderDynamoDB | None = None - OldImage: OrderDynamoDB | None = None + NewImage: Optional[OrderDynamoDB] = None + OldImage: Optional[OrderDynamoDB] = None class OrderDynamoDBRecord(DynamoDBStreamRecordModel):