diff options
author | Julian Berman <Julian@GrayVines.com> | 2013-09-22 12:32:33 -0400 |
---|---|---|
committer | Julian Berman <Julian@GrayVines.com> | 2013-10-27 18:35:28 -0400 |
commit | 3c6568b2171794aadc8df25dd79a5d491008fb48 (patch) | |
tree | b5df198c872ee6c28d628b120cf73423666627b1 | |
parent | 11dd8a53a856aba6df76ec8fd2c5cee2e5007236 (diff) | |
download | jsonschema-3c6568b2171794aadc8df25dd79a5d491008fb48.tar.gz |
Sort errors based on their paths.
-rw-r--r-- | jsonschema/exceptions.py | 50 | ||||
-rw-r--r-- | jsonschema/tests/test_exceptions.py | 40 |
2 files changed, 72 insertions, 18 deletions
diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions.py index e94907d..fe592e2 100644 --- a/jsonschema/exceptions.py +++ b/jsonschema/exceptions.py @@ -24,24 +24,19 @@ class _Error(Exception): self.instance = instance self.schema = schema - @classmethod - def create_from(cls, other): - return cls( - message=other.message, - cause=other.cause, - context=other.context, - path=other.path, - schema_path=other.schema_path, - validator=other.validator, - validator_value=other.validator_value, - instance=other.instance, - schema=other.schema, - ) - - def _set(self, **kwargs): - for k, v in iteritems(kwargs): - if getattr(self, k) is _unset: - setattr(self, k, v) + def __lt__(self, other): + if not isinstance(other, self.__class__): + # On Py2 Python will "helpfully" make this succeed. So be more + # forceful, because we really don't want this to work, it probably + # means a ValidationError and a SchemaError are being compared + # accidentally. + if not PY3: + message = "unorderable types: %s() < %s()" % ( + self.__class__.__name__, other.__class__.__name__, + ) + raise TypeError(message) + return NotImplemented + return self.path < other.path def __repr__(self): return "<%s: %r>" % (self.__class__.__name__, self.message) @@ -79,6 +74,25 @@ class _Error(Exception): if PY3: __str__ = __unicode__ + @classmethod + def create_from(cls, other): + return cls( + message=other.message, + cause=other.cause, + context=other.context, + path=other.path, + schema_path=other.schema_path, + validator=other.validator, + validator_value=other.validator_value, + instance=other.instance, + schema=other.schema, + ) + + def _set(self, **kwargs): + for k, v in iteritems(kwargs): + if getattr(self, k) is _unset: + setattr(self, k, v) + class ValidationError(_Error): pass diff --git a/jsonschema/tests/test_exceptions.py b/jsonschema/tests/test_exceptions.py new file mode 100644 index 0000000..b7ecaae --- /dev/null +++ b/jsonschema/tests/test_exceptions.py @@ -0,0 +1,40 @@ +from jsonschema import Draft4Validator, exceptions +from jsonschema.tests.compat import mock, unittest + + +class TestValidationErrorSorting(unittest.TestCase): + def test_shallower_errors_are_better_matches(self): + validator = Draft4Validator( + { + "properties" : { + "foo" : { + "minProperties" : 2, + "properties" : {"bar" : {"type" : "object"}}, + } + } + } + ) + errors = sorted(validator.iter_errors({"foo" : {"bar" : []}})) + self.assertEqual( + [list(error.path) for error in errors], + [["foo"], ["foo", "bar"]], + ) + + def test_global_errors_are_even_better_matches(self): + validator = Draft4Validator( + { + "minProperties" : 2, + "properties" : {"foo" : {"type" : "array"}}, + } + ) + errors = sorted(validator.iter_errors({"foo" : {"bar" : []}})) + self.assertEqual( + [list(error.path) for error in errors], + [[], ["foo"]], + ) + + def test_cannot_sort_errors_of_mixed_types(self): + with self.assertRaises(TypeError): + v = exceptions.ValidationError("Oh", instance=3) + s = exceptions.SchemaError("No!", instance=3) + v < s |