Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions jsonschema/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
from __future__ import annotations

from collections import defaultdict, deque
from collections import deque
from pprint import pformat
from textwrap import dedent, indent
from typing import TYPE_CHECKING, Any, ClassVar
Expand Down Expand Up @@ -321,12 +321,14 @@ class ErrorTree:

def __init__(self, errors: Iterable[ValidationError] = ()):
self.errors: MutableMapping[str, ValidationError] = {}
self._contents: Mapping[str, ErrorTree] = defaultdict(self.__class__)
self._contents: dict[str | int, ErrorTree] = {}

for error in errors:
container = self
for element in error.path:
container = container[element]
if element not in container._contents:
container._contents[element] = self.__class__()
container = container._contents[element]
container.errors[error.validator] = error

container._instance = error.instance
Expand All @@ -348,7 +350,9 @@ def __getitem__(self, index):
"""
if self._instance is not _unset and index not in self:
self._instance[index]
return self._contents[index]
if index in self._contents:
return self._contents[index]
return self.__class__()

def __setitem__(self, index: str | int, value: ErrorTree):
"""
Expand Down
17 changes: 17 additions & 0 deletions jsonschema/tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,23 @@ def test_repr_empty(self):
tree = exceptions.ErrorTree([])
self.assertEqual(repr(tree), "<ErrorTree (0 total errors)>")

def test_accessing_index_without_error_does_not_pollute_contents(self):
error = exceptions.ValidationError(
"not a number",
validator="type",
path=[0],
instance=["spam", 2],
)
tree = exceptions.ErrorTree([error])
self.assertEqual(list(tree), [0])
self.assertNotIn(1, tree)

# accessing an index with no error should not add it to the tree
tree[1]

self.assertEqual(list(tree), [0])
self.assertNotIn(1, tree)


class TestErrorInitReprStr(TestCase):
def make_error(self, **kwargs):
Expand Down
Loading