From 36810ff4f5501474e0d2027e4debc9672071e5f0 Mon Sep 17 00:00:00 2001 From: Harald Nezbeda Date: Mon, 14 Jun 2021 12:17:02 +0200 Subject: [PATCH] Julian/jsonschema#686: Fixes unique and equal checks --- jsonschema/_utils.py | 48 +++++- .../tests/test_jsonschema_test_suite.py | 160 ------------------ 2 files changed, 46 insertions(+), 162 deletions(-) diff --git a/jsonschema/_utils.py b/jsonschema/_utils.py index 21d8931e7..2b46d100e 100644 --- a/jsonschema/_utils.py +++ b/jsonschema/_utils.py @@ -158,10 +158,46 @@ def ensure_list(thing): return thing +def dict_equal(one, two): + """ + Check if two dicts are the same using `equal` + """ + if len(one.keys()) != len(two.keys()): + return False + + for key in one: + if key not in two: + return False + if not equal(one[key], two[key]): + return False + + return True + + +def list_equal(one, two): + """ + Check if two lists are the same using `equal` + """ + if len(one) != len(two): + return False + + for i in range(0, len(one)): + if not equal(one[i], two[i]): + return False + + return True + + def equal(one, two): """ Check if two things are equal, but evade booleans and ints being equal. """ + if isinstance(one, list) and isinstance(two, list): + return list_equal(one, two) + + if isinstance(one, dict) and isinstance(two, dict): + return dict_equal(one, two) + return unbool(one) == unbool(two) @@ -192,14 +228,22 @@ def uniq(container): try: sort = sorted(unbool(i) for i in container) sliced = itertools.islice(sort, 1, None) + for i, j in zip(sort, sliced): + if isinstance(i, list) and isinstance(j, list): + return not list_equal(i, j) if i == j: return False + except (NotImplementedError, TypeError): seen = [] for e in container: e = unbool(e) - if e in seen: - return False + + for i in seen: + if isinstance(i, dict) and isinstance(e, dict): + if dict_equal(i, e): + return False + seen.append(e) return True diff --git a/jsonschema/tests/test_jsonschema_test_suite.py b/jsonschema/tests/test_jsonschema_test_suite.py index 4a75cdc07..40e3d8592 100644 --- a/jsonschema/tests/test_jsonschema_test_suite.py +++ b/jsonschema/tests/test_jsonschema_test_suite.py @@ -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) ), ) @@ -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) ), ) @@ -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) ), ) @@ -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) ), )