Skip to content

Commit e24eb02

Browse files
author
Michael Brewer
authored
feat(validator): include missing data elements from a validation error (#686)
1 parent 4ab9f49 commit e24eb02

File tree

3 files changed

+80
-5
lines changed

3 files changed

+80
-5
lines changed

aws_lambda_powertools/utilities/validation/base.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ def validate_data_against_schema(data: Union[Dict, str], schema: Dict, formats:
3232
fastjsonschema.validate(definition=schema, data=data, formats=formats)
3333
except (TypeError, AttributeError, fastjsonschema.JsonSchemaDefinitionException) as e:
3434
raise InvalidSchemaFormatError(f"Schema received: {schema}, Formats: {formats}. Error: {e}")
35-
except fastjsonschema.JsonSchemaException as e:
36-
message = f"Failed schema validation. Error: {e.message}, Path: {e.path}, Data: {e.value}" # noqa: B306, E501
37-
raise SchemaValidationError(message)
35+
except fastjsonschema.JsonSchemaValueException as e:
36+
message = f"Failed schema validation. Error: {e.message}, Path: {e.path}, Data: {e.value}"
37+
raise SchemaValidationError(
38+
message,
39+
validation_message=e.message,
40+
name=e.name,
41+
path=e.path,
42+
value=e.value,
43+
definition=e.definition,
44+
rule=e.rule,
45+
rule_definition=e.rule_definition,
46+
)

aws_lambda_powertools/utilities/validation/exceptions.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,59 @@
1+
from typing import Any, List, Optional
2+
13
from ...exceptions import InvalidEnvelopeExpressionError
24

35

46
class SchemaValidationError(Exception):
57
"""When serialization fail schema validation"""
68

9+
def __init__(
10+
self,
11+
message: str,
12+
validation_message: Optional[str] = None,
13+
name: Optional[str] = None,
14+
path: Optional[List] = None,
15+
value: Optional[Any] = None,
16+
definition: Optional[Any] = None,
17+
rule: Optional[str] = None,
18+
rule_definition: Optional[Any] = None,
19+
):
20+
"""
21+
22+
Parameters
23+
----------
24+
message : str
25+
Powertools formatted error message
26+
validation_message : str, optional
27+
Containing human-readable information what is wrong
28+
(e.g. `data.property[index] must be smaller than or equal to 42`)
29+
name : str, optional
30+
name of a path in the data structure
31+
(e.g. `data.property[index]`)
32+
path: List, optional
33+
`path` as an array in the data structure
34+
(e.g. `['data', 'property', 'index']`),
35+
value : Any, optional
36+
The invalid value
37+
definition : Any, optional
38+
The full rule `definition`
39+
(e.g. `42`)
40+
rule : str, optional
41+
`rule` which the `data` is breaking
42+
(e.g. `maximum`)
43+
rule_definition : Any, optional
44+
The specific rule `definition`
45+
(e.g. `42`)
46+
"""
47+
super().__init__(message)
48+
self.message = message
49+
self.validation_message = validation_message
50+
self.name = name
51+
self.path = path
52+
self.value = value
53+
self.definition = definition
54+
self.rule = rule
55+
self.rule_definition = rule_definition
56+
757

858
class InvalidSchemaFormatError(Exception):
959
"""When JSON Schema is in invalid format"""

tests/functional/validator/test_validator.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import re
2+
13
import jmespath
24
import pytest
35
from jmespath import functions
@@ -22,8 +24,22 @@ def test_validate_base64_string_envelope(schema, wrapped_event_base64_json_strin
2224

2325

2426
def test_validate_event_does_not_conform_with_schema(schema):
25-
with pytest.raises(exceptions.SchemaValidationError):
26-
validate(event={"message": "hello_world"}, schema=schema)
27+
data = {"message": "hello_world"}
28+
message = "data must contain ['message', 'username'] properties"
29+
with pytest.raises(
30+
exceptions.SchemaValidationError,
31+
match=re.escape(f"Failed schema validation. Error: {message}, Path: ['data'], Data: {data}"),
32+
) as e:
33+
validate(event=data, schema=schema)
34+
35+
assert str(e.value) == e.value.message
36+
assert e.value.validation_message == message
37+
assert e.value.name == "data"
38+
assert e.value.path is not None
39+
assert e.value.value == data
40+
assert e.value.definition == schema
41+
assert e.value.rule == "required"
42+
assert e.value.rule_definition == schema.get("required")
2743

2844

2945
def test_validate_json_string_no_envelope(schema, wrapped_event_json_string):

0 commit comments

Comments
 (0)