Skip to content

Commit 4e738e9

Browse files
committed
improv: export Pydantic ValidationError instead of our own
1 parent ab1f0d2 commit 4e738e9

File tree

9 files changed

+27
-39
lines changed

9 files changed

+27
-39
lines changed

aws_lambda_powertools/utilities/parser/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
"""
33
from . import envelopes
44
from .envelopes import BaseEnvelope
5-
from .exceptions import ModelValidationError
65
from .parser import event_parser, parse
7-
from .pydantic import BaseModel, Field, root_validator, validator
6+
from .pydantic import BaseModel, Field, ValidationError, root_validator, validator
87

98
__all__ = [
109
"event_parser",
@@ -15,5 +14,5 @@
1514
"Field",
1615
"validator",
1716
"root_validator",
18-
"ModelValidationError",
17+
"ValidationError",
1918
]

aws_lambda_powertools/utilities/parser/exceptions.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,5 @@ class InvalidEnvelopeError(Exception):
22
"""Input envelope is not callable and instance of BaseEnvelope"""
33

44

5-
class ModelValidationError(Exception):
6-
"""Input data does not conform with model"""
7-
8-
95
class InvalidModelTypeError(Exception):
106
"""Input data model does not implement BaseModel"""

aws_lambda_powertools/utilities/parser/parser.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import logging
22
from typing import Any, Callable, Dict, Optional
33

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

66
from ...middleware_factory import lambda_handler_decorator
77
from ..typing import LambdaContext
88
from .envelopes.base import BaseEnvelope
9-
from .exceptions import InvalidEnvelopeError, InvalidModelTypeError, ModelValidationError
9+
from .exceptions import InvalidEnvelopeError, InvalidModelTypeError
1010

1111
logger = logging.getLogger(__name__)
1212

@@ -72,7 +72,7 @@ def handler(event: Order, context: LambdaContext):
7272
7373
Raises
7474
------
75-
ModelValidationError
75+
ValidationError
7676
When input event does not conform with model provided
7777
InvalidModelTypeError
7878
When model given does not implement BaseModel
@@ -94,7 +94,7 @@ def parse(event: Dict[str, Any], model: BaseModel, envelope: Optional[BaseEnvelo
9494
9595
**Lambda handler decorator to parse & validate event**
9696
97-
from aws_lambda_powertools.utilities.parser.exceptions import ModelValidationError
97+
from aws_lambda_powertools.utilities.parser import ValidationError
9898
9999
class Order(BaseModel):
100100
id: int
@@ -104,7 +104,7 @@ class Order(BaseModel):
104104
def handler(event: Order, context: LambdaContext):
105105
try:
106106
parse(model=Order)
107-
except ModelValidationError:
107+
except ValidationError:
108108
...
109109
110110
**Lambda handler decorator to parse & validate event - using built-in envelope**
@@ -117,7 +117,7 @@ class Order(BaseModel):
117117
def handler(event: Order, context: LambdaContext):
118118
try:
119119
parse(model=Order, envelope=envelopes.EVENTBRIDGE)
120-
except ModelValidationError:
120+
except ValidationError:
121121
...
122122
123123
Parameters
@@ -131,7 +131,7 @@ def handler(event: Order, context: LambdaContext):
131131
132132
Raises
133133
------
134-
ModelValidationError
134+
ValidationError
135135
When input event does not conform with model provided
136136
InvalidModelTypeError
137137
When model given does not implement BaseModel
@@ -144,16 +144,12 @@ def handler(event: Order, context: LambdaContext):
144144
return envelope().parse(data=event, model=model)
145145
except AttributeError:
146146
raise InvalidEnvelopeError(f"Envelope must implement BaseEnvelope, envelope={envelope}")
147-
except (ValidationError, TypeError) as e:
148-
raise ModelValidationError(f"Input event does not conform with model, envelope={envelope}") from e
149147

150148
try:
151149
logger.debug("Parsing and validating event model; no envelope used")
152150
if isinstance(event, str):
153151
return model.parse_raw(event)
154152

155153
return model.parse_obj(event)
156-
except (ValidationError, TypeError) as e:
157-
raise ModelValidationError("Input event does not conform with model") from e
158154
except AttributeError:
159155
raise InvalidModelTypeError("Input model must implement BaseModel")

docs/content/utilities/parser.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,10 @@ You can parse inbound events using **event_parser** decorator, or the standalone
139139

140140
Use the decorator for fail fast scenarios where you want your Lambda function to raise an exception in the event of a malformed payload.
141141

142-
`event_parser` decorator will throw a `ModelValidationError` if your event cannot be parsed according to the model.
142+
`event_parser` decorator will throw a `ValidationError` if your event cannot be parsed according to the model.
143143

144144
```python=:title=event_parser_decorator.py
145-
from aws_lambda_powertools.utilities.parser import event_parser, BaseModel, ModelValidationError
145+
from aws_lambda_powertools.utilities.parser import event_parser, BaseModel, ValidationError
146146
from aws_lambda_powertools.utilities.typing import LambdaContext
147147
import json
148148

@@ -187,7 +187,7 @@ handler(event=json.dumps(payload), context=LambdaContext()) # also works if even
187187
Use this standalone function when you want more control over the data validation process, for example returning a 400 error for malformed payloads.
188188

189189
```python:title=parse_standalone_example.py
190-
from aws_lambda_powertools.utilities.parser import parse, BaseModel, ModelValidationError
190+
from aws_lambda_powertools.utilities.parser import parse, BaseModel, ValidationError
191191

192192
class OrderItem(BaseModel):
193193
id: int
@@ -219,7 +219,7 @@ def my_function():
219219
parsed_payload: Order = parse(event=payload, model=Order) # highlight-line
220220
# payload dict is now parsed into our model
221221
return parsed_payload.items
222-
except ModelValidationError:
222+
except ValidationError:
223223
return {
224224
"status_code": 400,
225225
"message": "Invalid order"

tests/functional/parser/conftest.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from typing import Any, Dict
22

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

6-
from aws_lambda_powertools.utilities.parser import BaseEnvelope, ModelValidationError
6+
from aws_lambda_powertools.utilities.parser import BaseEnvelope
77

88

99
@pytest.fixture
@@ -37,10 +37,7 @@ class MyDummyEnvelope(BaseEnvelope):
3737
"""Unwrap dummy event within payload key"""
3838

3939
def parse(self, data: Dict[str, Any], model: BaseModel):
40-
try:
41-
parsed_enveloped = dummy_envelope_schema(**data)
42-
except (ValidationError, TypeError) as e:
43-
raise ModelValidationError("Dummy input does not conform with schema") from e
40+
parsed_enveloped = dummy_envelope_schema(**data)
4441
return self._parse(data=parsed_enveloped.payload, model=model)
4542

4643
return MyDummyEnvelope

tests/functional/parser/test_dynamodb.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from aws_lambda_powertools.utilities.parser import envelopes, event_parser, exceptions
5+
from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, event_parser
66
from aws_lambda_powertools.utilities.typing import LambdaContext
77
from tests.functional.parser.schemas import MyAdvancedDynamoBusiness, MyDynamoBusiness
88
from tests.functional.parser.utils import load_event
@@ -59,11 +59,11 @@ def test_dynamo_db_stream_trigger_event_no_envelope():
5959

6060
def test_validate_event_does_not_conform_with_model_no_envelope():
6161
event_dict: Any = {"hello": "s"}
62-
with pytest.raises(exceptions.ModelValidationError):
62+
with pytest.raises(ValidationError):
6363
handle_dynamodb_no_envelope(event_dict, LambdaContext())
6464

6565

6666
def test_validate_event_does_not_conform_with_model():
6767
event_dict: Any = {"hello": "s"}
68-
with pytest.raises(exceptions.ModelValidationError):
68+
with pytest.raises(ValidationError):
6969
handle_dynamodb(event_dict, LambdaContext())

tests/functional/parser/test_eventbridge.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from aws_lambda_powertools.utilities.parser import envelopes, event_parser, exceptions
5+
from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, event_parser
66
from aws_lambda_powertools.utilities.typing import LambdaContext
77
from tests.functional.parser.schemas import MyAdvancedEventbridgeBusiness, MyEventbridgeBusiness
88
from tests.functional.parser.utils import load_event
@@ -46,7 +46,7 @@ def test_validate_event_does_not_conform_with_user_dict_model():
4646
"resources": ["arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0"],
4747
"detail": {},
4848
}
49-
with pytest.raises(exceptions.ModelValidationError) as e:
49+
with pytest.raises(ValidationError) as e:
5050
handle_eventbridge(event_dict, LambdaContext())
5151
print(e.exconly())
5252

@@ -57,5 +57,5 @@ def test_handle_eventbridge_trigger_event_no_envelope():
5757

5858

5959
def test_handle_invalid_event_with_eventbridge_envelope():
60-
with pytest.raises(exceptions.ModelValidationError):
60+
with pytest.raises(ValidationError):
6161
handle_eventbridge(event={}, context=LambdaContext())

tests/functional/parser/test_parser.py

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

44
import pytest
55

6-
from aws_lambda_powertools.utilities.parser import event_parser, exceptions
6+
from aws_lambda_powertools.utilities.parser import ValidationError, event_parser, exceptions
77
from aws_lambda_powertools.utilities.typing import LambdaContext
88

99

@@ -13,7 +13,7 @@ def test_parser_unsupported_event(dummy_schema, invalid_value):
1313
def handle_no_envelope(event: Dict, _: LambdaContext):
1414
return event
1515

16-
with pytest.raises(exceptions.ModelValidationError):
16+
with pytest.raises(ValidationError):
1717
handle_no_envelope(event=invalid_value, context=LambdaContext())
1818

1919

tests/functional/parser/test_sqs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from aws_lambda_powertools.utilities.parser import envelopes, event_parser, exceptions
5+
from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, event_parser
66
from aws_lambda_powertools.utilities.typing import LambdaContext
77
from tests.functional.parser.schemas import MyAdvancedSqsBusiness, MySqsBusiness
88
from tests.functional.parser.utils import load_event
@@ -23,7 +23,7 @@ def test_handle_sqs_trigger_event_json_body(sqs_event): # noqa: F811
2323
def test_validate_event_does_not_conform_with_model():
2424
event: Any = {"invalid": "event"}
2525

26-
with pytest.raises(exceptions.ModelValidationError):
26+
with pytest.raises(ValidationError):
2727
handle_sqs_json_body(event, LambdaContext())
2828

2929

@@ -51,7 +51,7 @@ def test_validate_event_does_not_conform_user_json_string_with_model():
5151
]
5252
}
5353

54-
with pytest.raises(exceptions.ModelValidationError):
54+
with pytest.raises(ValidationError):
5555
handle_sqs_json_body(event, LambdaContext())
5656

5757

0 commit comments

Comments
 (0)