Skip to content

Commit 7b9b5c3

Browse files
committed
Merge branch 'fixes-686'
* fixes-686: Simplify the implementations of the equal checks. Test only through _util.equal. Fix the DeprecationWarning from importing abcs from collections. Extend sequance and mapping check Add test case with custom sequance type Add test for list_equal and dict_equal #686: Fixes unique and equal checks
2 parents 31426f6 + 72d8d08 commit 7b9b5c3

File tree

4 files changed

+249
-181
lines changed

4 files changed

+249
-181
lines changed

jsonschema/_utils.py

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from collections.abc import MutableMapping
1+
from collections.abc import Mapping, MutableMapping, Sequence
22
from urllib.parse import urlsplit
33
import itertools
44
import json
@@ -158,10 +158,40 @@ def ensure_list(thing):
158158
return thing
159159

160160

161+
def _mapping_equal(one, two):
162+
"""
163+
Check if two mappings are equal using the semantics of `equal`.
164+
"""
165+
if len(one) != len(two):
166+
return False
167+
return all(
168+
key in two and equal(value, two[key])
169+
for key, value in one.items()
170+
)
171+
172+
173+
def _sequence_equal(one, two):
174+
"""
175+
Check if two sequences are equal using the semantics of `equal`.
176+
"""
177+
if len(one) != len(two):
178+
return False
179+
return all(equal(i, j) for i, j in zip(one, two))
180+
181+
161182
def equal(one, two):
162183
"""
163-
Check if two things are equal, but evade booleans and ints being equal.
184+
Check if two things are equal evading some Python type hierarchy semantics.
185+
186+
Specifically in JSON Schema, evade `bool` inheriting from `int`,
187+
recursing into sequences to do the same.
164188
"""
189+
if isinstance(one, str) or isinstance(two, str):
190+
return one == two
191+
if isinstance(one, Sequence) and isinstance(two, Sequence):
192+
return _sequence_equal(one, two)
193+
if isinstance(one, Mapping) and isinstance(two, Mapping):
194+
return _mapping_equal(one, two)
165195
return unbool(one) == unbool(two)
166196

167197

@@ -181,25 +211,24 @@ def uniq(container):
181211
"""
182212
Check if all of a container's elements are unique.
183213
184-
Successively tries first to rely that the elements are hashable, then
185-
falls back on them being sortable, and finally falls back on brute
186-
force.
214+
Successively tries first to rely that the elements are being sortable
215+
and finally falls back on brute force.
187216
"""
188-
189217
try:
190-
return len(set(unbool(i) for i in container)) == len(container)
191-
except TypeError:
192-
try:
193-
sort = sorted(unbool(i) for i in container)
194-
sliced = itertools.islice(sort, 1, None)
195-
for i, j in zip(sort, sliced):
196-
if i == j:
197-
return False
198-
except (NotImplementedError, TypeError):
199-
seen = []
200-
for e in container:
201-
e = unbool(e)
202-
if e in seen:
218+
sort = sorted(unbool(i) for i in container)
219+
sliced = itertools.islice(sort, 1, None)
220+
221+
for i, j in zip(sort, sliced):
222+
return not _sequence_equal(i, j)
223+
224+
except (NotImplementedError, TypeError):
225+
seen = []
226+
for e in container:
227+
e = unbool(e)
228+
229+
for i in seen:
230+
if equal(i, e):
203231
return False
204-
seen.append(e)
232+
233+
seen.append(e)
205234
return True

jsonschema/tests/test_jsonschema_test_suite.py

Lines changed: 0 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -145,36 +145,6 @@ def leap_second(test):
145145
"$ref prevents a sibling id from changing the base uri"
146146
),
147147
)(test)
148-
or skip(
149-
message=bug(686),
150-
subject="uniqueItems",
151-
description="[0] and [false] are unique",
152-
)(test)
153-
or skip(
154-
message=bug(686),
155-
subject="uniqueItems",
156-
description="[1] and [true] are unique",
157-
)(test)
158-
or skip(
159-
message=bug(686),
160-
subject="uniqueItems",
161-
description="nested [0] and [false] are unique",
162-
)(test)
163-
or skip(
164-
message=bug(686),
165-
subject="uniqueItems",
166-
description="nested [1] and [true] are unique",
167-
)(test)
168-
or skip(
169-
message=bug(686),
170-
subject="uniqueItems",
171-
description='{"a": false} and {"a": 0} are unique',
172-
)(test)
173-
or skip(
174-
message=bug(686),
175-
subject="uniqueItems",
176-
description='{"a": true} and {"a": 1} are unique',
177-
)(test)
178148
),
179149
)
180150

@@ -240,36 +210,6 @@ def leap_second(test):
240210
subject="refRemote",
241211
case_description="base URI change - change folder in subschema",
242212
)(test)
243-
or skip(
244-
message=bug(686),
245-
subject="uniqueItems",
246-
description="[0] and [false] are unique",
247-
)(test)
248-
or skip(
249-
message=bug(686),
250-
subject="uniqueItems",
251-
description="[1] and [true] are unique",
252-
)(test)
253-
or skip(
254-
message=bug(686),
255-
subject="uniqueItems",
256-
description="nested [0] and [false] are unique",
257-
)(test)
258-
or skip(
259-
message=bug(686),
260-
subject="uniqueItems",
261-
description="nested [1] and [true] are unique",
262-
)(test)
263-
or skip(
264-
message=bug(686),
265-
subject="uniqueItems",
266-
description='{"a": false} and {"a": 0} are unique',
267-
)(test)
268-
or skip(
269-
message=bug(686),
270-
subject="uniqueItems",
271-
description='{"a": true} and {"a": 1} are unique',
272-
)(test)
273213
),
274214
)
275215

@@ -351,56 +291,6 @@ def leap_second(test):
351291
subject="refRemote",
352292
case_description="base URI change - change folder in subschema",
353293
)(test)
354-
or skip(
355-
message=bug(686),
356-
subject="uniqueItems",
357-
description="[0] and [false] are unique",
358-
)(test)
359-
or skip(
360-
message=bug(686),
361-
subject="uniqueItems",
362-
description="[1] and [true] are unique",
363-
)(test)
364-
or skip(
365-
message=bug(686),
366-
subject="uniqueItems",
367-
description="nested [0] and [false] are unique",
368-
)(test)
369-
or skip(
370-
message=bug(686),
371-
subject="uniqueItems",
372-
description="nested [1] and [true] are unique",
373-
)(test)
374-
or skip(
375-
message=bug(686),
376-
subject="uniqueItems",
377-
description='{"a": false} and {"a": 0} are unique',
378-
)(test)
379-
or skip(
380-
message=bug(686),
381-
subject="uniqueItems",
382-
description='{"a": true} and {"a": 1} are unique',
383-
)(test)
384-
or skip(
385-
message=bug(686),
386-
subject="const",
387-
case_description="const with [false] does not match [0]",
388-
)(test)
389-
or skip(
390-
message=bug(686),
391-
subject="const",
392-
case_description="const with [true] does not match [1]",
393-
)(test)
394-
or skip(
395-
message=bug(686),
396-
subject="const",
397-
case_description='const with {"a": false} does not match {"a": 0}',
398-
)(test)
399-
or skip(
400-
message=bug(686),
401-
subject="const",
402-
case_description='const with {"a": true} does not match {"a": 1}',
403-
)(test)
404294
),
405295
)
406296

@@ -506,55 +396,5 @@ def leap_second(test):
506396
"validation of binary-encoded media type documents"
507397
),
508398
)(test)
509-
or skip(
510-
message=bug(686),
511-
subject="uniqueItems",
512-
description="[0] and [false] are unique",
513-
)(test)
514-
or skip(
515-
message=bug(686),
516-
subject="uniqueItems",
517-
description="[1] and [true] are unique",
518-
)(test)
519-
or skip(
520-
message=bug(686),
521-
subject="uniqueItems",
522-
description="nested [0] and [false] are unique",
523-
)(test)
524-
or skip(
525-
message=bug(686),
526-
subject="uniqueItems",
527-
description="nested [1] and [true] are unique",
528-
)(test)
529-
or skip(
530-
message=bug(686),
531-
subject="uniqueItems",
532-
description='{"a": false} and {"a": 0} are unique',
533-
)(test)
534-
or skip(
535-
message=bug(686),
536-
subject="uniqueItems",
537-
description='{"a": true} and {"a": 1} are unique',
538-
)(test)
539-
or skip(
540-
message=bug(686),
541-
subject="const",
542-
case_description="const with [false] does not match [0]",
543-
)(test)
544-
or skip(
545-
message=bug(686),
546-
subject="const",
547-
case_description="const with [true] does not match [1]",
548-
)(test)
549-
or skip(
550-
message=bug(686),
551-
subject="const",
552-
case_description='const with {"a": false} does not match {"a": 0}',
553-
)(test)
554-
or skip(
555-
message=bug(686),
556-
subject="const",
557-
case_description='const with {"a": true} does not match {"a": 1}',
558-
)(test)
559399
),
560400
)

0 commit comments

Comments
 (0)