Skip to content

Commit d451d47

Browse files
committed
improv: raise own exception; remove duplicates
1 parent c7f242a commit d451d47

File tree

9 files changed

+57
-42
lines changed

9 files changed

+57
-42
lines changed

aws_lambda_powertools/utilities/parser/envelopes/base.py

+13-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from pydantic import BaseModel, ValidationError
66

7-
from ..exceptions import InvalidEnvelopeError
7+
from ..exceptions import InvalidEnvelopeError, SchemaValidationError
88

99
logger = logging.getLogger(__name__)
1010

@@ -14,28 +14,29 @@ class BaseEnvelope(ABC):
1414
def _parse_user_dict_schema(user_event: Dict[str, Any], schema: BaseModel) -> Any:
1515
if user_event is None:
1616
return None
17-
logger.debug("parsing user dictionary schema")
1817
try:
18+
logger.debug("parsing user dictionary schema")
1919
return schema(**user_event)
20-
except (ValidationError, TypeError):
20+
except (ValidationError, TypeError) as e:
2121
logger.exception("Validation exception while extracting user custom schema")
22-
raise
22+
raise SchemaValidationError("Failed to extract custom schema") from e
2323

2424
@staticmethod
2525
def _parse_user_json_string_schema(user_event: str, schema: BaseModel) -> Any:
2626
if user_event is None:
2727
return None
28+
2829
# this is used in cases where the underlying schema is not a Dict that can be parsed as baseModel
29-
# but a plain string i.e SQS has plain string payload
30-
if schema == str:
30+
# but a plain string as payload i.e. SQS: "body": "Test message."
31+
if schema is str:
3132
logger.debug("input is string, returning")
3233
return user_event
33-
logger.debug("trying to parse as json encoded string")
34+
3435
try:
36+
logger.debug("trying to parse as json encoded string")
3537
return schema.parse_raw(user_event)
36-
except (ValidationError, TypeError):
37-
logger.exception("Validation exception while extracting user custom schema")
38-
raise
38+
except (ValidationError, TypeError) as e:
39+
raise SchemaValidationError("Failed to extract custom schema from JSON string") from e
3940

4041
@abstractmethod
4142
def parse(self, event: Dict[str, Any], schema: BaseModel):
@@ -44,7 +45,7 @@ def parse(self, event: Dict[str, Any], schema: BaseModel):
4445

4546
def parse_envelope(event: Dict[str, Any], envelope: BaseEnvelope, schema: BaseModel):
4647
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")
48+
raise InvalidEnvelopeError(f"envelope must be a callable and instance of BaseEnvelope, envelope={envelope}")
49+
4950
logger.debug(f"Parsing and validating event schema, envelope={envelope}")
5051
return envelope().parse(event=event, schema=schema)

aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pydantic import BaseModel, ValidationError
55
from typing_extensions import Literal
66

7+
from ..exceptions import SchemaValidationError
78
from ..schemas import DynamoDBSchema
89
from .base import BaseEnvelope
910

@@ -31,12 +32,17 @@ def parse(self, event: Dict[str, Any], schema: BaseModel) -> List[Dict[Literal["
3132
-------
3233
List
3334
List of records parsed with schema provided
35+
36+
Raises
37+
------
38+
SchemaValidationError
39+
When input event doesn't conform with schema provided
3440
"""
3541
try:
3642
parsed_envelope = DynamoDBSchema(**event)
37-
except (ValidationError, TypeError):
38-
logger.exception("Validation exception received from input dynamodb stream event")
39-
raise
43+
except (ValidationError, TypeError) as e:
44+
raise SchemaValidationError("DynamoDB input doesn't conform with schema") from e
45+
4046
output = []
4147
for record in parsed_envelope.Records:
4248
output.append(

aws_lambda_powertools/utilities/parser/envelopes/event_bridge.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
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+
911
logger = logging.getLogger(__name__)
1012

1113

@@ -26,10 +28,14 @@ def parse(self, event: Dict[str, Any], schema: BaseModel) -> BaseModel:
2628
-------
2729
Any
2830
Parsed detail payload with schema provided
31+
32+
Raises
33+
------
34+
SchemaValidationError
35+
When input event doesn't conform with schema provided
2936
"""
3037
try:
3138
parsed_envelope = EventBridgeSchema(**event)
3239
except (ValidationError, TypeError):
33-
logger.exception("Validation exception received from input eventbridge event")
34-
raise
40+
raise SchemaValidationError("EventBridge input doesn't conform with schema") from ValidationError
3541
return self._parse_user_dict_schema(parsed_envelope.detail, schema)

aws_lambda_powertools/utilities/parser/envelopes/sqs.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from pydantic import BaseModel, ValidationError
55

6+
from ..exceptions import SchemaValidationError
67
from ..schemas import SqsSchema
78
from .base import BaseEnvelope
89

@@ -33,12 +34,16 @@ def parse(self, event: Dict[str, Any], schema: Union[BaseModel, str]) -> List[Un
3334
-------
3435
List
3536
List of records parsed with schema provided
37+
38+
Raises
39+
------
40+
SchemaValidationError
41+
When input event doesn't conform with schema provided
3642
"""
3743
try:
3844
parsed_envelope = SqsSchema(**event)
39-
except (ValidationError, TypeError):
40-
logger.exception("Validation exception received from input sqs event")
41-
raise
45+
except (ValidationError, TypeError) as e:
46+
raise SchemaValidationError("SQS input doesn't conform with schema") from e
4247
output = []
4348
for record in parsed_envelope.Records:
4449
output.append(self._parse_user_json_string_schema(record.body, schema))
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
class InvalidEnvelopeError(Exception):
2-
"""Input envelope is not one of the Envelope enum values"""
2+
"""Input envelope is not callable and instance of BaseEnvelope"""
3+
4+
5+
class SchemaValidationError(Exception):
6+
"""Input data does not conform with schema"""

aws_lambda_powertools/utilities/parser/parser.py

+6-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
77

88
from .envelopes.base import BaseEnvelope, parse_envelope
9+
from .exceptions import SchemaValidationError
910

1011
logger = logging.getLogger(__name__)
1112

@@ -49,19 +50,16 @@ def handler(event: MyBusiness , context: LambdaContext):
4950
5051
Raises
5152
------
52-
err
53-
TypeError - in case event is None
54-
pydantic.ValidationError - event fails validation, either of the envelope
53+
SchemaValidationError
54+
When input event doesn't conform with schema provided
5555
"""
5656
lambda_handler_name = handler.__name__
57-
parsed_event = None
5857
if envelope is None:
5958
try:
60-
logger.debug("Parsing and validating event schema, no envelope is used")
59+
logger.debug("Parsing and validating event schema; no envelope used")
6160
parsed_event = schema(**event)
62-
except (ValidationError, TypeError):
63-
logger.exception("Validation exception received from input event")
64-
raise
61+
except (ValidationError, TypeError) as e:
62+
raise SchemaValidationError("Input event doesn't conform with schema") from e
6563
else:
6664
parsed_event = parse_envelope(event, envelope, schema)
6765

tests/functional/parser/test_dynamodb.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from typing import Any, Dict, List
22

33
import pytest
4-
from pydantic.error_wrappers import ValidationError
54

6-
from aws_lambda_powertools.utilities.parser import envelopes
7-
from aws_lambda_powertools.utilities.parser.parser import parser
5+
from aws_lambda_powertools.utilities.parser import envelopes, exceptions, parser
86
from aws_lambda_powertools.utilities.typing import LambdaContext
97
from tests.functional.parser.schemas import MyAdvancedDynamoBusiness, MyDynamoBusiness
108
from tests.functional.parser.utils import load_event
@@ -61,11 +59,11 @@ def test_dynamo_db_stream_trigger_event_no_envelope():
6159

6260
def test_validate_event_does_not_conform_with_schema_no_envelope():
6361
event_dict: Any = {"hello": "s"}
64-
with pytest.raises(ValidationError):
62+
with pytest.raises(exceptions.SchemaValidationError):
6563
handle_dynamodb_no_envelope(event_dict, LambdaContext())
6664

6765

6866
def test_validate_event_does_not_conform_with_schema():
6967
event_dict: Any = {"hello": "s"}
70-
with pytest.raises(ValidationError):
68+
with pytest.raises(exceptions.SchemaValidationError):
7169
handle_dynamodb(event_dict, LambdaContext())

tests/functional/parser/test_eventbridge.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from typing import Any
22

33
import pytest
4-
from pydantic import ValidationError
54

6-
from aws_lambda_powertools.utilities.parser import envelopes, parser
5+
from aws_lambda_powertools.utilities.parser import envelopes, exceptions, parser
76
from aws_lambda_powertools.utilities.typing import LambdaContext
87
from tests.functional.parser.schemas import MyAdvancedEventbridgeBusiness, MyEventbridgeBusiness
98
from tests.functional.parser.utils import load_event
@@ -47,7 +46,7 @@ def test_validate_event_does_not_conform_with_user_dict_schema():
4746
"resources": ["arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0"],
4847
"detail": {},
4948
}
50-
with pytest.raises(ValidationError) as e:
49+
with pytest.raises(exceptions.SchemaValidationError) as e:
5150
handle_eventbridge(event_dict, LambdaContext())
5251
print(e.exconly())
5352

tests/functional/parser/test_sqs.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from typing import Any, List
22

33
import pytest
4-
from pydantic import ValidationError
54

6-
from aws_lambda_powertools.utilities.parser import envelopes
7-
from aws_lambda_powertools.utilities.parser.parser import parser
5+
from aws_lambda_powertools.utilities.parser import envelopes, exceptions, parser
86
from aws_lambda_powertools.utilities.typing import LambdaContext
97
from tests.functional.parser.schemas import MyAdvancedSqsBusiness, MySqsBusiness
108
from tests.functional.parser.utils import load_event
@@ -37,7 +35,7 @@ def test_handle_sqs_trigger_event_json_body(sqs_event): # noqa: F811
3735
def test_validate_event_does_not_conform_with_schema():
3836
event: Any = {"invalid": "event"}
3937

40-
with pytest.raises(ValidationError):
38+
with pytest.raises(exceptions.SchemaValidationError):
4139
handle_sqs_json_body(event, LambdaContext())
4240

4341

@@ -65,7 +63,7 @@ def test_validate_event_does_not_conform_user_json_string_with_schema():
6563
]
6664
}
6765

68-
with pytest.raises(ValidationError):
66+
with pytest.raises(exceptions.SchemaValidationError):
6967
handle_sqs_json_body(event, LambdaContext())
7068

7169

0 commit comments

Comments
 (0)