Skip to content

Commit 5bd51ee

Browse files
fix(parser): Improve types for parser.py
When attempting to use the parse function we noticed we were getting error messages like: Value of type variable "Model" of "parse" cannot be "Type[UserModel]" Further investigation (using the example shown at https://awslabs.github.io/aws-lambda-powertools-python/latest/utilities/parser/#envelopes) showed that the types were incorrect for the example. The function signatures were expecting an instance of `Model`, however the example (and code) seemeed to expect a `Type[Model]`. Similarly the signatures were expecting an optional instance of an Envelope, but the code allows for either an instance or a Type. Also, added a `TypeVar` for the decorator, specifying that the event_parser` decorator returns the same type as the handler used. Finally updated documentation on use of parser.
1 parent 213caed commit 5bd51ee

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

Diff for: aws_lambda_powertools/utilities/parser/parser.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Any, Callable, Dict, Optional
2+
from typing import Any, Callable, Dict, Optional, Type, TypeVar, Union
33

44
from ...middleware_factory import lambda_handler_decorator
55
from ..typing import LambdaContext
@@ -10,14 +10,17 @@
1010
logger = logging.getLogger(__name__)
1111

1212

13+
EventParserReturnType = TypeVar("EventParserReturnType")
14+
15+
1316
@lambda_handler_decorator
1417
def event_parser(
15-
handler: Callable[[Any, LambdaContext], Any],
18+
handler: Callable[[Any, LambdaContext], EventParserReturnType],
1619
event: Dict[str, Any],
1720
context: LambdaContext,
18-
model: Model,
19-
envelope: Optional[Envelope] = None,
20-
) -> Any:
21+
model: Type[Model],
22+
envelope: Optional[Union[Envelope, Type[Envelope]]] = None,
23+
) -> EventParserReturnType:
2124
"""Lambda handler decorator to parse & validate events using Pydantic models
2225
2326
It requires a model that implements Pydantic BaseModel to parse & validate the event.
@@ -83,7 +86,9 @@ def handler(event: Order, context: LambdaContext):
8386
return handler(parsed_event, context)
8487

8588

86-
def parse(event: Dict[str, Any], model: Model, envelope: Optional[Envelope] = None) -> Model:
89+
def parse(
90+
event: Dict[str, Any], model: Type[Model], envelope: Optional[Union[Envelope, Type[Envelope]]] = None
91+
) -> Model:
8792
"""Standalone function to parse & validate events using Pydantic models
8893
8994
Typically used when you need fine-grained control over error handling compared to event_parser decorator.

Diff for: docs/utilities/parser.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -272,21 +272,21 @@ Here's an example of parsing a model found in an event coming from EventBridge,
272272
}
273273
}
274274

275-
ret = parse(model=UserModel, envelope=envelopes.EventBridgeModel, event=payload)
275+
ret = parse(model=UserModel, envelope=envelopes.EventBridgeEnvelope, event=payload)
276276

277277
# Parsed model only contains our actual model, not the entire EventBridge + Payload parsed
278278
assert ret.password1 == ret.password2
279279

280280
# Same behaviour but using our decorator
281-
@event_parser(model=UserModel, envelope=envelopes.EventBridgeModel)
281+
@event_parser(model=UserModel, envelope=envelopes.EventBridgeEnvelope)
282282
def handler(event: UserModel, context: LambdaContext):
283283
assert event.password1 == event.password2
284284
```
285285

286286
**What's going on here, you might ask**:
287287

288288
1. We imported built-in `envelopes` from the parser utility
289-
2. Used `envelopes.EventBridgeModel` as the envelope for our `UserModel` model
289+
2. Used `envelopes.EventBridgeEnvelope` as the envelope for our `UserModel` model
290290
3. Parser parsed the original event against the EventBridge model
291291
4. Parser then parsed the `detail` key using `UserModel`
292292

0 commit comments

Comments
 (0)