Skip to content

Commit 89122ac

Browse files
committed
improv: propagate exception to parser
1 parent 002cc54 commit 89122ac

File tree

7 files changed

+36
-61
lines changed

7 files changed

+36
-61
lines changed

aws_lambda_powertools/utilities/parser/envelopes/base.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,26 @@
22
from abc import ABC, abstractmethod
33
from typing import Any, Dict, Union
44

5-
from pydantic import BaseModel, ValidationError
6-
7-
from ..exceptions import SchemaValidationError
5+
from pydantic import BaseModel
86

97
logger = logging.getLogger(__name__)
108

119

1210
class BaseEnvelope(ABC):
11+
"""ABC implementation for creating a supported Envelope"""
12+
1313
@staticmethod
1414
def _parse(event: Union[Dict[str, Any], str], schema: BaseModel) -> Any:
1515
if event is None:
1616
logger.debug("Skipping parsing as event is None")
1717
return event
1818

19-
try:
20-
logger.debug("parsing event against schema")
21-
if isinstance(event, str):
22-
logger.debug("parsing event as string")
23-
return schema.parse_raw(event)
24-
else:
25-
return schema.parse_obj(event)
26-
except (ValidationError, TypeError) as e:
27-
raise SchemaValidationError("Failed to extract custom schema") from e
19+
logger.debug("parsing event against schema")
20+
if isinstance(event, str):
21+
logger.debug("parsing event as string")
22+
return schema.parse_raw(event)
23+
24+
return schema.parse_obj(event)
2825

2926
@abstractmethod
3027
def parse(self, event: Dict[str, Any], schema: BaseModel):

aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import logging
22
from typing import Any, Dict, List
33

4-
from pydantic import BaseModel, ValidationError
4+
from pydantic import BaseModel
55
from typing_extensions import Literal
66

7-
from ..exceptions import SchemaValidationError
87
from ..schemas import DynamoDBSchema
98
from .base import BaseEnvelope
109

@@ -32,17 +31,8 @@ def parse(self, event: Dict[str, Any], schema: BaseModel) -> List[Dict[Literal["
3231
-------
3332
List
3433
List of records parsed with schema provided
35-
36-
Raises
37-
------
38-
SchemaValidationError
39-
When input event doesn't conform with schema provided
4034
"""
41-
try:
42-
parsed_envelope = DynamoDBSchema(**event)
43-
except (ValidationError, TypeError) as e:
44-
raise SchemaValidationError("DynamoDB input doesn't conform with schema") from e
45-
35+
parsed_envelope = DynamoDBSchema(**event)
4636
output = []
4737
for record in parsed_envelope.Records:
4838
output.append(
Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import logging
22
from typing import Any, Dict
33

4-
from pydantic import BaseModel, ValidationError
4+
from pydantic import BaseModel
55

66
from aws_lambda_powertools.utilities.parser.envelopes.base import BaseEnvelope
77
from aws_lambda_powertools.utilities.parser.schemas import EventBridgeSchema
88

9-
from ..exceptions import SchemaValidationError
10-
119
logger = logging.getLogger(__name__)
1210

1311

@@ -28,14 +26,6 @@ def parse(self, event: Dict[str, Any], schema: BaseModel) -> BaseModel:
2826
-------
2927
Any
3028
Parsed detail payload with schema provided
31-
32-
Raises
33-
------
34-
SchemaValidationError
35-
When input event doesn't conform with schema provided
3629
"""
37-
try:
38-
parsed_envelope = EventBridgeSchema(**event)
39-
return self._parse(parsed_envelope.detail, schema)
40-
except ValidationError as e:
41-
raise SchemaValidationError("EventBridge input doesn't conform with schema") from e
30+
parsed_envelope = EventBridgeSchema(**event)
31+
return self._parse(parsed_envelope.detail, schema)

aws_lambda_powertools/utilities/parser/envelopes/sqs.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import logging
22
from typing import Any, Dict, List, Union
33

4-
from pydantic import BaseModel, ValidationError
4+
from pydantic import BaseModel
55

6-
from ..exceptions import SchemaValidationError
76
from ..schemas import SqsSchema
87
from .base import BaseEnvelope
98

@@ -34,16 +33,8 @@ def parse(self, event: Dict[str, Any], schema: Union[BaseModel, str]) -> List[Un
3433
-------
3534
List
3635
List of records parsed with schema provided
37-
38-
Raises
39-
------
40-
SchemaValidationError
41-
When input event doesn't conform with schema provided
4236
"""
43-
try:
44-
parsed_envelope = SqsSchema(**event)
45-
except (ValidationError, TypeError) as e:
46-
raise SchemaValidationError("SQS input doesn't conform with schema") from e
37+
parsed_envelope = SqsSchema(**event)
4738
output = []
4839
for record in parsed_envelope.Records:
4940
output.append(self._parse(record.body, schema))

aws_lambda_powertools/utilities/parser/parser.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def handler(event: MyBusiness , context: LambdaContext):
5151
Raises
5252
------
5353
SchemaValidationError
54-
When input event doesn't conform with schema provided
54+
When input event does not conform with schema provided
5555
InvalidSchemaTypeError
5656
When schema given does not implement BaseModel
5757
"""
@@ -92,23 +92,25 @@ def handler(event: MyBusiness , context: LambdaContext):
9292
Raises
9393
------
9494
SchemaValidationError
95-
When input event doesn't conform with schema provided
95+
When input event does not conform with schema provided
9696
InvalidSchemaTypeError
9797
When schema given does not implement BaseModel
98-
98+
InvalidEnvelopeError
99+
When envelope given does not implement BaseEnvelope
99100
"""
100-
if envelope:
101+
if envelope and callable(envelope):
101102
try:
102-
logger.debug(f"Parsing and validating event schema, envelope={envelope}")
103-
# noinspection PyCallingNonCallable
103+
logger.debug(f"Parsing and validating event schema with envelope={envelope}")
104104
return envelope().parse(event=event, schema=schema)
105-
except (TypeError, AttributeError):
106-
raise InvalidEnvelopeError(f"envelope must be a callable and instance of BaseEnvelope, envelope={envelope}")
105+
except AttributeError:
106+
raise InvalidEnvelopeError(f"Envelope must implement BaseEnvelope, envelope={envelope}")
107+
except (ValidationError, TypeError) as e:
108+
raise SchemaValidationError(f"Input event does not conform with schema, envelope={envelope}") from e
107109

108110
try:
109111
logger.debug("Parsing and validating event schema; no envelope used")
110112
return schema.parse_obj(event)
111113
except (ValidationError, TypeError) as e:
112-
raise SchemaValidationError("Input event doesn't conform with schema") from e
114+
raise SchemaValidationError("Input event does not conform with schema") from e
113115
except AttributeError:
114116
raise InvalidSchemaTypeError("Input schema must implement BaseModel")

tests/functional/parser/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def parse(self, event: Dict[str, Any], schema: BaseModel):
4141
try:
4242
parsed_enveloped = dummy_envelope_schema(**event)
4343
except (ValidationError, TypeError) as e:
44-
raise SchemaValidationError("Dummy input doesn't conform with schema") from e
44+
raise SchemaValidationError("Dummy input does not conform with schema") from e
4545
return self._parse(event=parsed_enveloped.payload, schema=schema)
4646

4747
return MyDummyEnvelope

tests/functional/parser/test_parser.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@ def handle_no_envelope(event: Dict, _: LambdaContext):
1616
handle_no_envelope(event=invalid_value, context=LambdaContext())
1717

1818

19-
@pytest.mark.parametrize("invalid_envelope", [True, ["dummy"], ("dummy"), object])
20-
def test_parser_invalid_envelope_type(dummy_event, dummy_schema, invalid_envelope):
19+
@pytest.mark.parametrize(
20+
"invalid_envelope,expected", [(True, ""), (["dummy"], ""), (object, exceptions.InvalidEnvelopeError)]
21+
)
22+
def test_parser_invalid_envelope_type(dummy_event, dummy_schema, invalid_envelope, expected):
2123
@parser(schema=dummy_schema, envelope=invalid_envelope)
2224
def handle_no_envelope(event: Dict, _: LambdaContext):
2325
return event
2426

25-
with pytest.raises(exceptions.InvalidEnvelopeError):
27+
if hasattr(expected, "__cause__"):
28+
with pytest.raises(expected):
29+
handle_no_envelope(event=dummy_event["payload"], context=LambdaContext())
30+
else:
2631
handle_no_envelope(event=dummy_event["payload"], context=LambdaContext())
2732

2833

0 commit comments

Comments
 (0)