Skip to content

Commit

Permalink
Improve error message for oneOf and anyOf
Browse files Browse the repository at this point in the history
  • Loading branch information
abravalheri committed Feb 27, 2022
1 parent d63d682 commit 79f0e23
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 14 deletions.
5 changes: 3 additions & 2 deletions fastjsonschema/draft04.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def generate_any_of(self):
self.l('except JsonSchemaValueException: pass')

with self.l('if not {variable}_any_of_count{count}:', count=count, optimize=False):
self.exc('{name} must be valid by one of anyOf definition', rule='anyOf')
self.exc('{name} cannot be validated by any definition', rule='anyOf')

def generate_one_of(self):
"""
Expand Down Expand Up @@ -188,7 +188,8 @@ def generate_one_of(self):
self.l('except JsonSchemaValueException: pass')

with self.l('if {variable}_one_of_count{count} != 1:', count=count):
self.exc('{name} must be valid exactly by one of oneOf definition', rule='oneOf')
dynamic = '" (" + str({variable}_one_of_count{}) + " matches found)"'
self.exc('{name} must be valid exactly by one definition', count, append_to_msg=dynamic, rule='oneOf')

def generate_not(self):
"""
Expand Down
7 changes: 5 additions & 2 deletions fastjsonschema/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,14 @@ def e(self, string):
"""
return str(string).replace('"', '\\"')

def exc(self, msg, *args, rule=None):
def exc(self, msg, *args, append_to_msg=None, rule=None):
"""
Short-cut for creating raising exception in the code.
"""
msg = 'raise JsonSchemaValueException("'+msg+'", value={variable}, name="{name}", definition={definition}, rule={rule})'
arg = '"'+msg+'"'
if append_to_msg:
arg += ' + (' + append_to_msg + ')'
msg = 'raise JsonSchemaValueException('+arg+', value={variable}, name="{name}", definition={definition}, rule={rule})'
definition = self._expand_refs(self._definition)
definition_rule = self.e(definition.get(rule) if isinstance(definition, dict) else None)
self.l(msg, *args, definition=repr(definition), rule=repr(rule), definition_rule=definition_rule)
Expand Down
20 changes: 11 additions & 9 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_all_of(asserter, value, expected):
]}, value, expected)


exc = JsonSchemaValueException('data must be valid by one of anyOf definition', value='{data}', name='data', definition='{definition}', rule='anyOf')
exc = JsonSchemaValueException('data cannot be validated by any definition', value='{data}', name='data', definition='{definition}', rule='anyOf')
@pytest.mark.parametrize('value, expected', [
(0, 0),
(None, exc),
Expand All @@ -55,13 +55,16 @@ def test_any_of(asserter, value, expected):
]}, value, expected)


exc = JsonSchemaValueException('data must be valid exactly by one of oneOf definition', value='{data}', name='data', definition='{definition}', rule='oneOf')
def exc(n):
suffix = " ({} matches found)".format(n)
return JsonSchemaValueException('data must be valid exactly by one definition' + suffix, value='{data}', name='data', definition='{definition}', rule='oneOf')

@pytest.mark.parametrize('value, expected', [
(0, exc),
(2, exc),
(0, exc(2)),
(2, exc(0)),
(9, 9),
(10, 10),
(15, exc),
(15, exc(2)),
])
def test_one_of(asserter, value, expected):
asserter({'oneOf': [
Expand All @@ -70,13 +73,12 @@ def test_one_of(asserter, value, expected):
]}, value, expected)


exc = JsonSchemaValueException('data must be valid exactly by one of oneOf definition', value='{data}', name='data', definition='{definition}', rule='oneOf')
@pytest.mark.parametrize('value, expected', [
(0, exc),
(2, exc),
(0, exc(2)),
(2, exc(0)),
(9, 9),
(10, 10),
(15, exc),
(15, exc(2)),
])
def test_one_of_factorized(asserter, value, expected):
asserter({
Expand Down
2 changes: 1 addition & 1 deletion tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
),
(
[9, 'hello', [1], {'a': 'a', 'b': 'b', 'x': 'x'}, 42, 15],
JsonSchemaValueException('data[5] must be valid exactly by one of oneOf definition', value=15, name='data[5]', definition=definition['items'][5], rule='oneOf'),
JsonSchemaValueException('data[5] must be valid exactly by one definition (2 matches found)', value=15, name='data[5]', definition=definition['items'][5], rule='oneOf'),
),
])
def test_integration(asserter, value, expected):
Expand Down

0 comments on commit 79f0e23

Please sign in to comment.