Skip to content

Commit 4ef44a7

Browse files
committed
Add test case with custom sequance type
1 parent 3e5781d commit 4ef44a7

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

jsonschema/_utils.py

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -217,33 +217,27 @@ def uniq(container):
217217
"""
218218
Check if all of a container's elements are unique.
219219
220-
Successively tries first to rely that the elements are hashable, then
221-
falls back on them being sortable, and finally falls back on brute
222-
force.
220+
Successively tries first to rely that the elements are being sortable
221+
and finally falls back on brute force.
223222
"""
224-
225223
try:
226-
return len(set(unbool(i) for i in container)) == len(container)
227-
except TypeError:
228-
try:
229-
sort = sorted(unbool(i) for i in container)
230-
sliced = itertools.islice(sort, 1, None)
231-
232-
for i, j in zip(sort, sliced):
233-
if isinstance(i, list) and isinstance(j, list):
234-
return not list_equal(i, j)
235-
if i == j:
224+
sort = sorted(unbool(i) for i in container)
225+
sliced = itertools.islice(sort, 1, None)
226+
227+
for i, j in zip(sort, sliced):
228+
return not list_equal(list(i), list(j))
229+
230+
except (NotImplementedError, TypeError):
231+
seen = []
232+
for e in container:
233+
e = unbool(e)
234+
235+
for i in seen:
236+
if isinstance(i, dict) and isinstance(e, dict):
237+
if dict_equal(i, e):
238+
return False
239+
elif i == e:
236240
return False
237241

238-
except (NotImplementedError, TypeError):
239-
seen = []
240-
for e in container:
241-
e = unbool(e)
242-
243-
for i in seen:
244-
if isinstance(i, dict) and isinstance(e, dict):
245-
if dict_equal(i, e):
246-
return False
247-
248-
seen.append(e)
242+
seen.append(e)
249243
return True

jsonschema/tests/test_validators.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from collections import deque
1+
from collections import deque, namedtuple
22
from contextlib import contextmanager
33
from decimal import Decimal
44
from io import BytesIO
@@ -1088,6 +1088,42 @@ def test_it_properly_formats_tuples_in_errors(self):
10881088
TupleValidator({"uniqueItems": True}).validate((1, 1))
10891089
self.assertIn("(1, 1) has non-unique elements", str(e.exception))
10901090

1091+
def test_check_redefined_sequence(self):
1092+
"""
1093+
Allow array to validate against another defined sequence type
1094+
"""
1095+
schema = {
1096+
"type": "array",
1097+
"uniqueItems": True
1098+
}
1099+
1100+
MyMapping = namedtuple('MyMapping', 'a, b')
1101+
1102+
Validator = validators.extend(
1103+
self.Validator,
1104+
type_checker=self.Validator.TYPE_CHECKER.redefine(
1105+
"array",
1106+
lambda checker, thing: isinstance(thing, (list, deque)),
1107+
)
1108+
)
1109+
1110+
validator = Validator(schema)
1111+
validator.validate(deque(['a', None, '1', '', True]))
1112+
with self.assertRaises(exceptions.ValidationError):
1113+
validator.validate(deque(['a', 'b', 'a']))
1114+
1115+
validator.validate(deque([[False], [0]]))
1116+
with self.assertRaises(exceptions.ValidationError):
1117+
validator.validate(deque([[False], [False]]))
1118+
1119+
validator.validate([deque([False]), deque([0])])
1120+
with self.assertRaises(exceptions.ValidationError):
1121+
validator.validate([deque([False]), deque([False])])
1122+
1123+
validator.validate([MyMapping('a', 0), MyMapping('a', False)])
1124+
with self.assertRaises(exceptions.ValidationError):
1125+
validator.validate([MyMapping('a', False), MyMapping('a', False)])
1126+
10911127

10921128
class AntiDraft6LeakMixin(object):
10931129
"""

0 commit comments

Comments
 (0)