Skip to content

Commit afa9ab7

Browse files
committed
Rewrote all SchemaConflict exceptions to be more human readable.
1 parent 1c7471c commit afa9ab7

File tree

4 files changed

+75
-18
lines changed

4 files changed

+75
-18
lines changed

ReleaseNotes.rst

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Release Notes
1010
- Reworked all RuleError exceptions to now have better exception messages.
1111
- RuleError exceptions now have a unique 'error_key' that can make it easier to identify what error it is.
1212
- Paths for RuleErrors have been moved inside the exception as a variable.
13+
- Rewrote all SchemaConflict exceptions to be more human readable.
1314

1415

1516
1.3.0

docs/Upgrade Instructions.md

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ Python 3.2 support have been dropped. It was going to be dropped when python 3.5
99

1010
All logging and exception messages have been fixed to work with unicode characters in schema and data files. If you use this in lib mode then you should test your code to ensure it is still compatible.
1111

12+
If you use `RuleError` in your code, you must update to use the new `msg` and `error_key` variables.
13+
14+
If you use `SchemaConflict` in your code, you must update to use the new `msg` and `error_key` variables.
15+
1216

1317
## 1.2.0 --> 1.3.0
1418

pykwalify/rule.py

+57-10
Original file line numberDiff line numberDiff line change
@@ -628,25 +628,72 @@ def check_conflicts(self, schema, rule, path):
628628

629629
if self._type == "seq":
630630
if all([sa not in schema for sa in sequence_aliases]):
631-
raise SchemaConflict(u"seq.nosequence")
631+
raise SchemaConflict(
632+
msg="Type is sequence but no sequence alias found on same level",
633+
error_key=u"seq.no_sequence",
634+
path=path,
635+
)
636+
632637
if self._enum is not None:
633-
raise SchemaConflict(u"seq.conflict :: enum: {}".format(path))
638+
raise SchemaConflict(
639+
msg="Sequence and enum can't be on the same level in the schema",
640+
error_key=u"seq.conflict.enum",
641+
path=path,
642+
)
643+
634644
if self._pattern is not None:
635-
raise SchemaConflict(u"seq.conflict :: pattern: {}".format(path))
645+
raise SchemaConflict(
646+
msg="Sequence and pattern can't be on the same level in the schema",
647+
error_key=u"seq.conflict.pattern",
648+
path=path,
649+
)
650+
636651
if self._mapping is not None:
637-
raise SchemaConflict(u"seq.conflict :: mapping: {}".format(path))
652+
raise SchemaConflict(
653+
msg="Sequence and mapping can't be on the same level in the schema",
654+
error_key=u"seq.conflict.mapping",
655+
path=path,
656+
)
638657
elif self._type == "map":
639658
if all([ma not in schema for ma in mapping_aliases]) and not self._allowempty_map:
640-
raise SchemaConflict(u"map.nomapping")
659+
raise SchemaConflict(
660+
msg="Type is mapping but no mapping alias found on same level",
661+
error_key=u"map.no_mapping",
662+
path=path,
663+
)
664+
641665
if self._enum is not None:
642-
raise SchemaConflict(u"map.conflict :: enum:")
666+
raise SchemaConflict(
667+
msg="Mapping and enum can't be on the same level in the schema",
668+
error_key=u"map.conflict.enum",
669+
path=path,
670+
)
671+
643672
if self._sequence is not None:
644-
raise SchemaConflict(u"map.conflict :: mapping: {}".format(path))
673+
raise SchemaConflict(
674+
msg="Mapping and sequence can't be on the same level in the schema",
675+
error_key=u"map.conflict.sequence",
676+
path=path,
677+
)
645678
else:
646679
if self._sequence is not None:
647-
raise SchemaConflict(u"scalar.conflict :: sequence: {}".format(path))
680+
raise SchemaConflict(
681+
msg="Scalar and sequence can't be on the same level in the schema",
682+
error_key=u"scalar.conflict.sequence",
683+
path=path,
684+
)
685+
648686
if self._mapping is not None:
649-
raise SchemaConflict(u"scalar.conflict :: mapping: {}".format(path))
687+
raise SchemaConflict(
688+
msg="Scalar and mapping can't be on the same level in the schema",
689+
error_key=u"scalar.conflict.mapping",
690+
path=path,
691+
)
692+
650693
if self._enum is not None:
651694
if self._range is not None:
652-
raise SchemaConflict(u"enum.conflict :: range: {}".format(path))
695+
raise SchemaConflict(
696+
msg="Enum and range can't be on the same level in the schema",
697+
error_key=u"enum.conflict.range",
698+
path=path,
699+
)

tests/test_rule.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,12 @@ def test_sequence(self):
231231
# Test error is raised when sequence key is missing
232232
with pytest.raises(SchemaConflict) as ex:
233233
Rule(schema={"type": "seq"})
234-
assert ex.value.msg.startswith("seq.nosequence"), "Wrong exception was raised"
234+
assert str(ex.value) == "<SchemaConflict: error code 5: Type is sequence but no sequence alias found on same level: Path: '/'>"
235235

236236
# sequence and pattern can't be used at same time
237237
with pytest.raises(SchemaConflict) as ex:
238238
Rule(schema={"type": "seq", "sequence": [{"type": "str"}], "pattern": "..."})
239-
assert ex.value.msg.startswith("seq.conflict :: pattern"), "Wrong exception was raised"
239+
assert str(ex.value) == "<SchemaConflict: error code 5: Sequence and pattern can't be on the same level in the schema: Path: '/'>"
240240

241241
def test_build_sequence_multiple_values(self):
242242
"""
@@ -276,7 +276,7 @@ def test_mapping(self):
276276
# when type is specefied, 'mapping' key must be present
277277
with pytest.raises(SchemaConflict) as ex:
278278
Rule(schema={"type": "map"})
279-
assert ex.value.msg.startswith("map.nomapping"), "Wrong exception was raised"
279+
assert str(ex.value) == "<SchemaConflict: error code 5: Type is mapping but no mapping alias found on same level: Path: '/'>"
280280

281281
# 'map' and 'enum' can't be used at same time
282282
# TODO: This do not work because it currently raises RuleError: <RuleError: error code 4: enum.notscalar>
@@ -295,24 +295,29 @@ def test_check_conflicts(self):
295295
# Test sequence and mapping can't be used at same level
296296
with pytest.raises(SchemaConflict) as ex:
297297
Rule(schema={"type": "seq", "sequence": [{"type": "str"}], "mapping": {"name": {"type": "str", "pattern": ".+@.+"}}})
298-
assert ex.value.msg.startswith("seq.conflict :: mapping"), "Wrong exception was raised"
298+
assert str(ex.value) == "<SchemaConflict: error code 5: Sequence and mapping can't be on the same level in the schema: Path: '/'>"
299+
assert ex.value.error_key == 'seq.conflict.mapping'
299300

300301
# Mapping and sequence can't used at same time
301302
with pytest.raises(SchemaConflict) as ex:
302303
Rule(schema={"type": "map", "mapping": {"foo": {"type": "str"}}, "sequence": [{"type": "str"}]})
303-
assert ex.value.msg.startswith("map.conflict :: mapping"), "Wrong exception was raised"
304+
assert str(ex.value) == "<SchemaConflict: error code 5: Mapping and sequence can't be on the same level in the schema: Path: '/'>"
305+
assert ex.value.error_key == 'map.conflict.sequence'
304306

305307
# scalar type and sequence can't be used at same time
306308
with pytest.raises(SchemaConflict) as ex:
307309
Rule(schema={"type": "int", "sequence": [{"type": "str"}]})
308-
assert ex.value.msg.startswith("scalar.conflict :: sequence"), "Wrong exception was raised"
310+
assert str(ex.value) == "<SchemaConflict: error code 5: Scalar and sequence can't be on the same level in the schema: Path: '/'>"
311+
assert ex.value.error_key == 'scalar.conflict.sequence'
309312

310313
# scalar type and mapping can't be used at same time
311314
with pytest.raises(SchemaConflict) as ex:
312315
Rule(schema={"type": "int", "mapping": {"foo": {"type": "str"}}})
313-
assert ex.value.msg.startswith("scalar.conflict :: mapping"), "Wrong exception was raised"
316+
assert str(ex.value) == "<SchemaConflict: error code 5: Scalar and mapping can't be on the same level in the schema: Path: '/'>"
317+
assert ex.value.error_key == 'scalar.conflict.mapping'
314318

315319
# scalar type and enum can't be used at same time
316320
with pytest.raises(SchemaConflict) as ex:
317321
Rule(schema={"type": "int", "enum": [1, 2, 3], "range": {"max": 10, "min": 1}})
318-
assert ex.value.msg.startswith("enum.conflict :: range"), "Wrong exception was raised"
322+
assert str(ex.value) == "<SchemaConflict: error code 5: Enum and range can't be on the same level in the schema: Path: '/'>"
323+
assert ex.value.error_key == 'enum.conflict.range'

0 commit comments

Comments
 (0)