diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions.py index 478e59c53..46f1ce0ec 100644 --- a/jsonschema/exceptions.py +++ b/jsonschema/exceptions.py @@ -86,7 +86,7 @@ def absolute_path(self): return self.relative_path path = deque(self.relative_path) - path.extendleft(parent.absolute_path) + path.extendleft(reversed(parent.absolute_path)) return path @property @@ -96,7 +96,7 @@ def absolute_schema_path(self): return self.relative_schema_path path = deque(self.relative_schema_path) - path.extendleft(parent.absolute_schema_path) + path.extendleft(reversed(parent.absolute_schema_path)) return path def _set(self, **kwargs): diff --git a/jsonschema/tests/test_validators.py b/jsonschema/tests/test_validators.py index f8692388e..4bd3c5474 100644 --- a/jsonschema/tests/test_validators.py +++ b/jsonschema/tests/test_validators.py @@ -425,6 +425,71 @@ def test_multiple_nesting(self): self.assertEqual(e5.validator, "minItems") self.assertEqual(e6.validator, "enum") + def test_recursive(self): + schema = { + "definitions": { + "node": { + "anyOf": [{ + "type": "object", + "required": ["name", "children"], + "properties": { + "name": { + "type": "string", + }, + "children": { + "type": "object", + "patternProperties": { + "^.*$": { + "$ref": "#/definitions/node", + }, + }, + }, + }, + }], + }, + }, + "type": "object", + "required": ["root"], + "properties": { + "root": {"$ref": "#/definitions/node"}, + } + } + + instance = { + "root": { + "name": "root", + "children": { + "a": { + "name": "a", + "children": { + "ab": { + "name": "ab", + # missing "children" + } + } + }, + }, + }, + } + validator = Draft4Validator(schema) + + e, = validator.iter_errors(instance) + self.assertEqual(e.absolute_path, deque(["root"])) + self.assertEqual(e.absolute_schema_path, deque(['properties', 'root', 'anyOf'])) + + e1, = e.context + self.assertEqual(e1.absolute_path, deque(['root', 'children', 'a'])) + self.assertEqual(e1.absolute_schema_path, + deque(['properties', 'root', 'anyOf', 0, 'properties', + 'children', 'patternProperties', '^.*$', 'anyOf'])) + + e2, = e1.context + self.assertEqual(e2.absolute_path, deque(['root', 'children', 'a', 'children', 'ab'])) + self.assertEqual(e2.absolute_schema_path, + deque(['properties', 'root', 'anyOf', 0, 'properties', + 'children', 'patternProperties', '^.*$', 'anyOf', 0, 'properties', + 'children', 'patternProperties', '^.*$', 'anyOf'])) + def test_additionalProperties(self): instance = {"bar": "bar", "foo": 2} schema = {