summaryrefslogtreecommitdiff
path: root/jsonschema/exceptions.py
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2013-10-27 20:38:49 -0400
committerJulian Berman <Julian@GrayVines.com>2013-10-27 20:38:49 -0400
commitb4f098bdccb25b6d124050e4ecda48371c7ccc4a (patch)
treeceb0b10d2aa747759bd595fafe5e20b7fb3bd23a /jsonschema/exceptions.py
parent11b3220eac39292e88df04a8b8a5a142812496fe (diff)
downloadjsonschema-b4f098bdccb25b6d124050e4ecda48371c7ccc4a.tar.gz
Different strategy that's a lot more robust.
Diffstat (limited to 'jsonschema/exceptions.py')
-rw-r--r--jsonschema/exceptions.py40
1 files changed, 17 insertions, 23 deletions
diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions.py
index 8df987d..04a3c0b 100644
--- a/jsonschema/exceptions.py
+++ b/jsonschema/exceptions.py
@@ -7,6 +7,9 @@ from jsonschema import _utils
from jsonschema.compat import PY3, iteritems
+WEAK_MATCHES = frozenset(["anyOf", "oneOf"])
+STRONG_MATCHES = frozenset()
+
_unset = _utils.Unset()
@@ -30,24 +33,6 @@ class _Error(Exception):
return NotImplemented
return self._contents() == other._contents()
- 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
-
- is_deeper = len(self.path) > len(other.path)
- is_weak_matcher = self.validator in ("anyOf", "oneOf")
- other_is_weak_matcher = other.validator in ("anyOf", "oneOf")
- return is_deeper or is_weak_matcher > other_is_weak_matcher
-
def __ne__(self, other):
return not self == other
@@ -159,11 +144,20 @@ class FormatError(Exception):
__str__ = __unicode__
-def best_match(errors):
- first = next(iter(errors), None)
- if first is None:
+def by_relevance(weak=WEAK_MATCHES, strong=STRONG_MATCHES):
+ def relevance(error):
+ validator = error.validator
+ return -len(error.path), validator not in weak, validator in strong
+ return relevance
+
+
+def best_match(errors, key=by_relevance()):
+ errors = iter(errors)
+ best = next(errors, None)
+ if best is None:
return
- best = max(itertools.chain([first], errors))
+ best = max(itertools.chain([best], errors), key=key)
+
while best.context:
- best = min(best.context)
+ best = min(best.context, key=key)
return best