diff --git a/aws_lambda_powertools/utilities/parser/parser.py b/aws_lambda_powertools/utilities/parser/parser.py index 16cdc45c907..7a7f6aec56b 100644 --- a/aws_lambda_powertools/utilities/parser/parser.py +++ b/aws_lambda_powertools/utilities/parser/parser.py @@ -1,5 +1,5 @@ import logging -from typing import Any, Callable, Dict, Optional +from typing import Any, Callable, Dict, Optional, Type, TypeVar, Union from ...middleware_factory import lambda_handler_decorator from ..typing import LambdaContext @@ -10,14 +10,17 @@ logger = logging.getLogger(__name__) +EventParserReturnType = TypeVar("EventParserReturnType") + + @lambda_handler_decorator def event_parser( - handler: Callable[[Any, LambdaContext], Any], + handler: Callable[[Any, LambdaContext], EventParserReturnType], event: Dict[str, Any], context: LambdaContext, - model: Model, - envelope: Optional[Envelope] = None, -) -> Any: + model: Type[Model], + envelope: Optional[Union[Envelope, Type[Envelope]]] = None, +) -> EventParserReturnType: """Lambda handler decorator to parse & validate events using Pydantic models It requires a model that implements Pydantic BaseModel to parse & validate the event. @@ -83,7 +86,9 @@ def handler(event: Order, context: LambdaContext): return handler(parsed_event, context) -def parse(event: Dict[str, Any], model: Model, envelope: Optional[Envelope] = None) -> Model: +def parse( + event: Dict[str, Any], model: Type[Model], envelope: Optional[Union[Envelope, Type[Envelope]]] = None +) -> Model: """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. diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 7fa78a5e372..4428c1453d5 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -272,13 +272,13 @@ Here's an example of parsing a model found in an event coming from EventBridge, } } - ret = parse(model=UserModel, envelope=envelopes.EventBridgeModel, event=payload) + ret = parse(model=UserModel, envelope=envelopes.EventBridgeEnvelope, event=payload) # Parsed model only contains our actual model, not the entire EventBridge + Payload parsed assert ret.password1 == ret.password2 # Same behaviour but using our decorator - @event_parser(model=UserModel, envelope=envelopes.EventBridgeModel) + @event_parser(model=UserModel, envelope=envelopes.EventBridgeEnvelope) def handler(event: UserModel, context: LambdaContext): assert event.password1 == event.password2 ``` @@ -286,7 +286,7 @@ Here's an example of parsing a model found in an event coming from EventBridge, **What's going on here, you might ask**: 1. We imported built-in `envelopes` from the parser utility -2. Used `envelopes.EventBridgeModel` as the envelope for our `UserModel` model +2. Used `envelopes.EventBridgeEnvelope` as the envelope for our `UserModel` model 3. Parser parsed the original event against the EventBridge model 4. Parser then parsed the `detail` key using `UserModel`