Skip to content

Commit 8ccaff1

Browse files
authored
Merge pull request #145 from abravalheri/improve-errors-oneof-anyof
Improve error message for `oneOf`, `anyOf` and `not` (slightly)
2 parents 1f1ac93 + 1444717 commit 8ccaff1

File tree

4 files changed

+24
-18
lines changed

4 files changed

+24
-18
lines changed

fastjsonschema/draft04.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def generate_any_of(self):
158158
self.l('except JsonSchemaValueException: pass')
159159

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

163163
def generate_one_of(self):
164164
"""
@@ -188,7 +188,8 @@ def generate_one_of(self):
188188
self.l('except JsonSchemaValueException: pass')
189189

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

193194
def generate_not(self):
194195
"""
@@ -210,13 +211,13 @@ def generate_not(self):
210211
return
211212
elif not not_definition:
212213
with self.l('if {}:', self._variable):
213-
self.exc('{name} must not be valid by not definition', rule='not')
214+
self.exc('{name} must NOT match a disallowed definition', rule='not')
214215
else:
215216
with self.l('try:', optimize=False):
216217
self.generate_func_code_block(not_definition, self._variable, self._variable_name)
217218
self.l('except JsonSchemaValueException: pass')
218219
with self.l('else:'):
219-
self.exc('{name} must not be valid by not definition', rule='not')
220+
self.exc('{name} must NOT match a disallowed definition', rule='not')
220221

221222
def generate_min_length(self):
222223
with self.l('if isinstance({variable}, str):'):

fastjsonschema/generator.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,14 @@ def e(self, string):
255255
"""
256256
return str(string).replace('"', '\\"')
257257

258-
def exc(self, msg, *args, rule=None):
258+
def exc(self, msg, *args, append_to_msg=None, rule=None):
259259
"""
260260
Short-cut for creating raising exception in the code.
261261
"""
262-
msg = 'raise JsonSchemaValueException("'+msg+'", value={variable}, name="{name}", definition={definition}, rule={rule})'
262+
arg = '"'+msg+'"'
263+
if append_to_msg:
264+
arg += ' + (' + append_to_msg + ')'
265+
msg = 'raise JsonSchemaValueException('+arg+', value={variable}, name="{name}", definition={definition}, rule={rule})'
263266
definition = self._expand_refs(self._definition)
264267
definition_rule = self.e(definition.get(rule) if isinstance(definition, dict) else None)
265268
self.l(msg, *args, definition=repr(definition), rule=repr(rule), definition_rule=definition_rule)

tests/test_common.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_all_of(asserter, value, expected):
3939
]}, value, expected)
4040

4141

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

5757

58-
exc = JsonSchemaValueException('data must be valid exactly by one of oneOf definition', value='{data}', name='data', definition='{definition}', rule='oneOf')
58+
def exc(n):
59+
suffix = " ({} matches found)".format(n)
60+
return JsonSchemaValueException('data must be valid exactly by one definition' + suffix, value='{data}', name='data', definition='{definition}', rule='oneOf')
61+
5962
@pytest.mark.parametrize('value, expected', [
60-
(0, exc),
61-
(2, exc),
63+
(0, exc(2)),
64+
(2, exc(0)),
6265
(9, 9),
6366
(10, 10),
64-
(15, exc),
67+
(15, exc(2)),
6568
])
6669
def test_one_of(asserter, value, expected):
6770
asserter({'oneOf': [
@@ -70,13 +73,12 @@ def test_one_of(asserter, value, expected):
7073
]}, value, expected)
7174

7275

73-
exc = JsonSchemaValueException('data must be valid exactly by one of oneOf definition', value='{data}', name='data', definition='{definition}', rule='oneOf')
7476
@pytest.mark.parametrize('value, expected', [
75-
(0, exc),
76-
(2, exc),
77+
(0, exc(2)),
78+
(2, exc(0)),
7779
(9, 9),
7880
(10, 10),
79-
(15, exc),
81+
(15, exc(2)),
8082
])
8183
def test_one_of_factorized(asserter, value, expected):
8284
asserter({
@@ -89,7 +91,7 @@ def test_one_of_factorized(asserter, value, expected):
8991

9092

9193
@pytest.mark.parametrize('value, expected', [
92-
(0, JsonSchemaValueException('data must not be valid by not definition', value='{data}', name='data', definition='{definition}', rule='not')),
94+
(0, JsonSchemaValueException('data must NOT match a disallowed definition', value='{data}', name='data', definition='{definition}', rule='not')),
9395
(True, True),
9496
('abc', 'abc'),
9597
([], []),

tests/test_integration.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@
9494
),
9595
(
9696
[9, 'hello', [1], {'a': 'a', 'b': 'b', 'x': 'x'}, None, 5],
97-
JsonSchemaValueException('data[4] must not be valid by not definition', value=None, name='data[4]', definition=definition['items'][4], rule='not'),
97+
JsonSchemaValueException('data[4] must NOT match a disallowed definition', value=None, name='data[4]', definition=definition['items'][4], rule='not'),
9898
),
9999
(
100100
[9, 'hello', [1], {'a': 'a', 'b': 'b', 'x': 'x'}, 42, 15],
101-
JsonSchemaValueException('data[5] must be valid exactly by one of oneOf definition', value=15, name='data[5]', definition=definition['items'][5], rule='oneOf'),
101+
JsonSchemaValueException('data[5] must be valid exactly by one definition (2 matches found)', value=15, name='data[5]', definition=definition['items'][5], rule='oneOf'),
102102
),
103103
])
104104
def test_integration(asserter, value, expected):

0 commit comments

Comments
 (0)