summaryrefslogtreecommitdiff
path: root/jsonschema/_legacy_validators.py
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2022-08-20 14:51:18 +0300
committerJulian Berman <Julian@GrayVines.com>2022-08-20 14:53:50 +0300
commit1e6b983569f51dde52d55da2b43cb2f592232318 (patch)
tree120a65658b205e7b1ac5082d8ce9c8880baf6a94 /jsonschema/_legacy_validators.py
parent79195f21d85334a16571d1660a4280397730894a (diff)
downloadjsonschema-1e6b983569f51dde52d55da2b43cb2f592232318.tar.gz
Fix unevaluatedItems on draft2019.
This was trivial, other than needing to copy paste the function which anyhow needs removal. It only didn't work previously because of the items -> prefixItems rename in draft2020.
Diffstat (limited to 'jsonschema/_legacy_validators.py')
-rw-r--r--jsonschema/_legacy_validators.py78
1 files changed, 78 insertions, 0 deletions
diff --git a/jsonschema/_legacy_validators.py b/jsonschema/_legacy_validators.py
index fa45053..fa9daf4 100644
--- a/jsonschema/_legacy_validators.py
+++ b/jsonschema/_legacy_validators.py
@@ -226,3 +226,81 @@ def recursiveRef(validator, recursiveRef, instance, schema):
# see it.
subschema
return []
+
+
+def find_evaluated_item_indexes_by_schema(validator, instance, schema):
+ """
+ Get all indexes of items that get evaluated under the current schema
+
+ Covers all keywords related to unevaluatedItems: items, prefixItems, if,
+ then, else, contains, unevaluatedItems, allOf, oneOf, anyOf
+ """
+ if validator.is_type(schema, "boolean"):
+ return []
+ evaluated_indexes = []
+
+ if "additionalItems" in schema:
+ return list(range(0, len(instance)))
+
+ if "$ref" in schema:
+ scope, resolved = validator.resolver.resolve(schema["$ref"])
+ validator.resolver.push_scope(scope)
+
+ try:
+ evaluated_indexes += find_evaluated_item_indexes_by_schema(
+ validator, instance, resolved,
+ )
+ finally:
+ validator.resolver.pop_scope()
+
+ if "items" in schema:
+ if validator.is_type(schema["items"], "object"):
+ return list(range(0, len(instance)))
+ evaluated_indexes += list(range(0, len(schema["items"])))
+
+ if "if" in schema:
+ if validator.evolve(schema=schema["if"]).is_valid(instance):
+ evaluated_indexes += find_evaluated_item_indexes_by_schema(
+ validator, instance, schema["if"],
+ )
+ if "then" in schema:
+ evaluated_indexes += find_evaluated_item_indexes_by_schema(
+ validator, instance, schema["then"],
+ )
+ else:
+ if "else" in schema:
+ evaluated_indexes += find_evaluated_item_indexes_by_schema(
+ validator, instance, schema["else"],
+ )
+
+ for keyword in ["contains", "unevaluatedItems"]:
+ if keyword in schema:
+ for k, v in enumerate(instance):
+ if validator.evolve(schema=schema[keyword]).is_valid(v):
+ evaluated_indexes.append(k)
+
+ for keyword in ["allOf", "oneOf", "anyOf"]:
+ if keyword in schema:
+ for subschema in schema[keyword]:
+ errs = list(validator.descend(instance, subschema))
+ if not errs:
+ evaluated_indexes += find_evaluated_item_indexes_by_schema(
+ validator, instance, subschema,
+ )
+
+ return evaluated_indexes
+
+
+def unevaluatedItems_draft2019(validator, unevaluatedItems, instance, schema):
+ if not validator.is_type(instance, "array"):
+ return
+ evaluated_item_indexes = find_evaluated_item_indexes_by_schema(
+ validator, instance, schema,
+ )
+ unevaluated_items = [
+ item for index, item in enumerate(instance)
+ if index not in evaluated_item_indexes
+ ]
+ if unevaluated_items:
+ error = "Unevaluated items are not allowed (%s %s unexpected)"
+ yield ValidationError(error % _utils.extras_msg(unevaluated_items))