Skip to content

Commit 991bec7

Browse files
committed
improv: envelope structure & import
1 parent 1e4a49c commit 991bec7

File tree

12 files changed

+93
-69
lines changed

12 files changed

+93
-69
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Advanced parser utility
22
"""
3-
from .envelopes import Envelope, InvalidEnvelopeError, parse_envelope
3+
from . import envelopes
44
from .parser import parser
55

6-
__all__ = ["InvalidEnvelopeError", "Envelope", "parse_envelope", "parser"]
6+
__all__ = ["envelopes", "parser"]
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
from .envelopes import Envelope, InvalidEnvelopeError, parse_envelope
1+
from .dynamodb import DynamoDBEnvelope
2+
from .event_bridge import EventBridgeEnvelope
3+
from .sqs import SqsEnvelope
24

3-
__all__ = ["InvalidEnvelopeError", "Envelope", "parse_envelope"]
5+
SQS = SqsEnvelope
6+
DYNAMODB_STREAM = DynamoDBEnvelope
7+
EVENTBRIDGE = EventBridgeEnvelope

aws_lambda_powertools/utilities/parser/envelopes/base.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from pydantic import BaseModel, ValidationError
66

7+
from ..exceptions import InvalidEnvelopeError
8+
79
logger = logging.getLogger(__name__)
810

911

@@ -38,3 +40,11 @@ def _parse_user_json_string_schema(user_event: str, schema: BaseModel) -> Any:
3840
@abstractmethod
3941
def parse(self, event: Dict[str, Any], schema: BaseModel):
4042
return NotImplemented
43+
44+
45+
def parse_envelope(event: Dict[str, Any], envelope: BaseEnvelope, schema: BaseModel):
46+
if not callable(envelope) and not isinstance(BaseEnvelope):
47+
logger.exception("envelope must be a callable and instance of BaseEnvelope")
48+
raise InvalidEnvelopeError("envelope must be a callable and instance of BaseEnvelope")
49+
logger.debug(f"Parsing and validating event schema, envelope={envelope}")
50+
return envelope().parse(event=event, schema=schema)

aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,34 @@
44
from pydantic import BaseModel, ValidationError
55
from typing_extensions import Literal
66

7-
from aws_lambda_powertools.utilities.parser.envelopes.base import BaseEnvelope
8-
from aws_lambda_powertools.utilities.parser.schemas import DynamoDBSchema
7+
from ..schemas import DynamoDBSchema
8+
from .base import BaseEnvelope
99

1010
logger = logging.getLogger(__name__)
1111

1212

13-
# returns a List of dictionaries which each contains two keys, "NewImage" and "OldImage".
14-
# The values are the parsed schema models. The images' values can also be None.
15-
# Length of the list is the record's amount in the original event.
1613
class DynamoDBEnvelope(BaseEnvelope):
14+
""" DynamoDB Stream Envelope to extract data within NewImage/OldImage
15+
16+
Note: Values are the parsed schema models. Images' values can also be None, and
17+
length of the list is the record's amount in the original event.
18+
"""
19+
1720
def parse(self, event: Dict[str, Any], schema: BaseModel) -> List[Dict[Literal["NewImage", "OldImage"], BaseModel]]:
21+
"""Parses DynamoDB Stream records found in either NewImage and OldImage with schema provided
22+
23+
Parameters
24+
----------
25+
event : Dict
26+
Lambda event to be parsed
27+
schema : BaseModel
28+
User schema provided to parse after extracting data using envelope
29+
30+
Returns
31+
-------
32+
List
33+
List of records parsed with schema provided
34+
"""
1835
try:
1936
parsed_envelope = DynamoDBSchema(**event)
2037
except (ValidationError, TypeError):

aws_lambda_powertools/utilities/parser/envelopes/envelopes.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,24 @@
99
logger = logging.getLogger(__name__)
1010

1111

12-
# returns a parsed BaseModel object according to schema type
1312
class EventBridgeEnvelope(BaseEnvelope):
13+
"""EventBridge envelope to extract data in detail key"""
14+
1415
def parse(self, event: Dict[str, Any], schema: BaseModel) -> BaseModel:
16+
"""Parses data found with schema provided
17+
18+
Parameters
19+
----------
20+
event : Dict
21+
Lambda event to be parsed
22+
schema : BaseModel
23+
User schema provided to parse after extracting data using envelope
24+
25+
Returns
26+
-------
27+
Any
28+
Parsed detail payload with schema provided
29+
"""
1530
try:
1631
parsed_envelope = EventBridgeSchema(**event)
1732
except (ValidationError, TypeError):

aws_lambda_powertools/utilities/parser/envelopes/sqs.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,37 @@
33

44
from pydantic import BaseModel, ValidationError
55

6-
from aws_lambda_powertools.utilities.parser.envelopes.base import BaseEnvelope
7-
from aws_lambda_powertools.utilities.parser.schemas import SqsSchema
6+
from ..schemas import SqsSchema
7+
from .base import BaseEnvelope
88

99
logger = logging.getLogger(__name__)
1010

1111

12-
# returns a list of parsed schemas of type BaseModel or plain string.
13-
# The record's body parameter is a string. However, it can also be a JSON encoded string which
14-
# can then be parsed into a BaseModel object.
15-
# Note that all records will be parsed the same way so if schema is str,
16-
# all the items in the list will be parsed as str and npt as JSON (and vice versa).
1712
class SqsEnvelope(BaseEnvelope):
13+
"""SQS Envelope to extract array of Records
14+
15+
The record's body parameter is a string, though it can also be a JSON encoded string.
16+
Regardless of it's type it'll be parsed into a BaseModel object.
17+
18+
Note: Records will be parsed the same way so if schema is str,
19+
all items in the list will be parsed as str and npt as JSON (and vice versa)
20+
"""
21+
1822
def parse(self, event: Dict[str, Any], schema: Union[BaseModel, str]) -> List[Union[BaseModel, str]]:
23+
"""Parses records found with schema provided
24+
25+
Parameters
26+
----------
27+
event : Dict
28+
Lambda event to be parsed
29+
schema : BaseModel
30+
User schema provided to parse after extracting data using envelope
31+
32+
Returns
33+
-------
34+
List
35+
List of records parsed with schema provided
36+
"""
1937
try:
2038
parsed_envelope = SqsSchema(**event)
2139
except (ValidationError, TypeError):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class InvalidEnvelopeError(Exception):
2+
"""Input envelope is not one of the Envelope enum values"""

aws_lambda_powertools/utilities/parser/parser.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
from pydantic import BaseModel, ValidationError
55

66
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
7-
from aws_lambda_powertools.utilities.parser.envelopes import Envelope, parse_envelope
7+
8+
from .envelopes.base import BaseEnvelope, parse_envelope
89

910
logger = logging.getLogger(__name__)
1011

@@ -15,7 +16,7 @@ def parser(
1516
event: Dict[str, Any],
1617
context: Dict[str, Any],
1718
schema: BaseModel,
18-
envelope: Optional[Envelope] = None,
19+
envelope: Optional[BaseEnvelope] = None,
1920
) -> Any:
2021
"""Decorator to conduct advanced parsing & validation for lambda handlers events
2122

tests/functional/parser/test_dynamodb.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import pytest
44
from pydantic.error_wrappers import ValidationError
55

6-
from aws_lambda_powertools.utilities.parser.envelopes.envelopes import Envelope
6+
from aws_lambda_powertools.utilities.parser import envelopes
77
from aws_lambda_powertools.utilities.parser.parser import parser
88
from aws_lambda_powertools.utilities.typing import LambdaContext
99
from tests.functional.parser.schemas import MyAdvancedDynamoBusiness, MyDynamoBusiness
1010
from tests.functional.parser.utils import load_event
1111

1212

13-
@parser(schema=MyDynamoBusiness, envelope=Envelope.DYNAMODB_STREAM)
13+
@parser(schema=MyDynamoBusiness, envelope=envelopes.DYNAMODB_STREAM)
1414
def handle_dynamodb(event: List[Dict[str, MyDynamoBusiness]], _: LambdaContext):
1515
assert len(event) == 2
1616
assert event[0]["OldImage"] is None

0 commit comments

Comments
 (0)