summaryrefslogtreecommitdiff
path: root/jsonschema/exceptions.py
diff options
context:
space:
mode:
Diffstat (limited to 'jsonschema/exceptions.py')
-rw-r--r--jsonschema/exceptions.py59
1 files changed, 40 insertions, 19 deletions
diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions.py
index e94907d..26fafbe 100644
--- a/jsonschema/exceptions.py
+++ b/jsonschema/exceptions.py
@@ -1,4 +1,5 @@
import collections
+import itertools
import pprint
import textwrap
@@ -6,6 +7,9 @@ from jsonschema import _utils
from jsonschema.compat import PY3, iteritems
+WEAK_MATCHES = frozenset(["anyOf", "oneOf"])
+STRONG_MATCHES = frozenset()
+
_unset = _utils.Unset()
@@ -24,25 +28,6 @@ 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 __repr__(self):
return "<%s: %r>" % (self.__class__.__name__, self.message)
@@ -79,6 +64,23 @@ class _Error(Exception):
if PY3:
__str__ = __unicode__
+ @classmethod
+ def create_from(cls, other):
+ return cls(**other._contents())
+
+ def _set(self, **kwargs):
+ for k, v in iteritems(kwargs):
+ if getattr(self, k) is _unset:
+ setattr(self, k, v)
+
+ def _contents(self):
+ return dict(
+ (attr, getattr(self, attr)) for attr in (
+ "message", "cause", "context", "path", "schema_path",
+ "validator", "validator_value", "instance", "schema"
+ )
+ )
+
class ValidationError(_Error):
pass
@@ -132,3 +134,22 @@ class FormatError(Exception):
if PY3:
__str__ = __unicode__
+
+
+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([best], errors), key=key)
+
+ while best.context:
+ best = min(best.context, key=key)
+ return best