Skip to content

Commit

Permalink
Merge branch 'fixes-686'
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Julian committed Jul 9, 2021
2 parents 31426f6 + 72d8d08 commit 7b9b5c3
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 181 deletions.
69 changes: 49 additions & 20 deletions jsonschema/_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from collections.abc import MutableMapping
from collections.abc import Mapping, MutableMapping, Sequence
from urllib.parse import urlsplit
import itertools
import json
Expand Down Expand Up @@ -158,10 +158,40 @@ def ensure_list(thing):
return thing


def _mapping_equal(one, two):
"""
Check if two mappings are equal using the semantics of `equal`.
"""
if len(one) != len(two):
return False
return all(
key in two and equal(value, two[key])
for key, value in one.items()
)


def _sequence_equal(one, two):
"""
Check if two sequences are equal using the semantics of `equal`.
"""
if len(one) != len(two):
return False
return all(equal(i, j) for i, j in zip(one, two))


def equal(one, two):
"""
Check if two things are equal, but evade booleans and ints being equal.
Check if two things are equal evading some Python type hierarchy semantics.
Specifically in JSON Schema, evade `bool` inheriting from `int`,
recursing into sequences to do the same.
"""
if isinstance(one, str) or isinstance(two, str):
return one == two
if isinstance(one, Sequence) and isinstance(two, Sequence):
return _sequence_equal(one, two)
if isinstance(one, Mapping) and isinstance(two, Mapping):
return _mapping_equal(one, two)
return unbool(one) == unbool(two)


Expand All @@ -181,25 +211,24 @@ def uniq(container):
"""
Check if all of a container's elements are unique.
Successively tries first to rely that the elements are hashable, then
falls back on them being sortable, and finally falls back on brute
force.
Successively tries first to rely that the elements are being sortable
and finally falls back on brute force.
"""

try:
return len(set(unbool(i) for i in container)) == len(container)
except TypeError:
try:
sort = sorted(unbool(i) for i in container)
sliced = itertools.islice(sort, 1, None)
for i, j in zip(sort, sliced):
if i == j:
return False
except (NotImplementedError, TypeError):
seen = []
for e in container:
e = unbool(e)
if e in seen:
sort = sorted(unbool(i) for i in container)
sliced = itertools.islice(sort, 1, None)

for i, j in zip(sort, sliced):
return not _sequence_equal(i, j)

except (NotImplementedError, TypeError):
seen = []
for e in container:
e = unbool(e)

for i in seen:
if equal(i, e):
return False
seen.append(e)

seen.append(e)
return True
160 changes: 0 additions & 160 deletions jsonschema/tests/test_jsonschema_test_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,36 +145,6 @@ def leap_second(test):
"$ref prevents a sibling id from changing the base uri"
),
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": false} and {"a": 0} are unique',
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": true} and {"a": 1} are unique',
)(test)
),
)

Expand Down Expand Up @@ -240,36 +210,6 @@ def leap_second(test):
subject="refRemote",
case_description="base URI change - change folder in subschema",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": false} and {"a": 0} are unique',
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": true} and {"a": 1} are unique',
)(test)
),
)

Expand Down Expand Up @@ -351,56 +291,6 @@ def leap_second(test):
subject="refRemote",
case_description="base URI change - change folder in subschema",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": false} and {"a": 0} are unique',
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": true} and {"a": 1} are unique',
)(test)
or skip(
message=bug(686),
subject="const",
case_description="const with [false] does not match [0]",
)(test)
or skip(
message=bug(686),
subject="const",
case_description="const with [true] does not match [1]",
)(test)
or skip(
message=bug(686),
subject="const",
case_description='const with {"a": false} does not match {"a": 0}',
)(test)
or skip(
message=bug(686),
subject="const",
case_description='const with {"a": true} does not match {"a": 1}',
)(test)
),
)

Expand Down Expand Up @@ -506,55 +396,5 @@ def leap_second(test):
"validation of binary-encoded media type documents"
),
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="[1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [0] and [false] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description="nested [1] and [true] are unique",
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": false} and {"a": 0} are unique',
)(test)
or skip(
message=bug(686),
subject="uniqueItems",
description='{"a": true} and {"a": 1} are unique',
)(test)
or skip(
message=bug(686),
subject="const",
case_description="const with [false] does not match [0]",
)(test)
or skip(
message=bug(686),
subject="const",
case_description="const with [true] does not match [1]",
)(test)
or skip(
message=bug(686),
subject="const",
case_description='const with {"a": false} does not match {"a": 0}',
)(test)
or skip(
message=bug(686),
subject="const",
case_description='const with {"a": true} does not match {"a": 1}',
)(test)
),
)
Loading

0 comments on commit 7b9b5c3

Please sign in to comment.