diff --git a/jsonschema/_utils.py b/jsonschema/_utils.py index ceb880198..9d7f281e2 100644 --- a/jsonschema/_utils.py +++ b/jsonschema/_utils.py @@ -1,4 +1,3 @@ -import itertools import json import pkgutil import re @@ -175,38 +174,29 @@ def equal(one, two): def unbool(element, true=object(), false=object()): """ A hack to make True and 1 and False and 0 unique for ``uniq``. + + Recurses through an arbitrarily deep object and unique-ifies True/1 and + False/0. Also converts arrays/objects into immutable/hashable alternatives. + We have to copy the items anyway to avoid unexpected mutations, so we might + as well make the imminent equality check simpler. """ if element is True: return true elif element is False: return false + elif isinstance(element, list) or isinstance(element, tuple): + return tuple(map(unbool, element)) + elif isinstance(element, dict): + # Convert dicts to frozensets of 2-tuples. For equality checks, that's + # a reasonable hashable alternative to dicts. + return frozenset(map(unbool, element.items())) return element 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. """ - 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: - return False - seen.append(e) - return True + return len(set(unbool(i) for i in container)) == len(container) diff --git a/jsonschema/tests/test_jsonschema_test_suite.py b/jsonschema/tests/test_jsonschema_test_suite.py index c978391f1..3bf277c1a 100644 --- a/jsonschema/tests/test_jsonschema_test_suite.py +++ b/jsonschema/tests/test_jsonschema_test_suite.py @@ -87,26 +87,6 @@ def narrow_unicode_build(test): # pragma: no cover subject="host-name", description="ends with hyphen", )(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) ), ) @@ -161,26 +141,6 @@ def narrow_unicode_build(test): # pragma: no cover subject="hostname", description="ends with hyphen", )(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) ), ) @@ -234,26 +194,6 @@ def narrow_unicode_build(test): # pragma: no cover subject="hostname", description="ends with hyphen", )(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) ), ) @@ -327,26 +267,6 @@ def narrow_unicode_build(test): # pragma: no cover "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) ), )