summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2013-09-22 12:32:33 -0400
committerJulian Berman <Julian@GrayVines.com>2013-10-27 18:35:28 -0400
commit3c6568b2171794aadc8df25dd79a5d491008fb48 (patch)
treeb5df198c872ee6c28d628b120cf73423666627b1
parent11dd8a53a856aba6df76ec8fd2c5cee2e5007236 (diff)
downloadjsonschema-3c6568b2171794aadc8df25dd79a5d491008fb48.tar.gz
Sort errors based on their paths.
-rw-r--r--jsonschema/exceptions.py50
-rw-r--r--jsonschema/tests/test_exceptions.py40
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