summaryrefslogtreecommitdiff
path: root/jsonschema/_validators.py
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2021-08-18 19:12:27 +0100
committerJulian Berman <Julian@GrayVines.com>2021-08-18 19:34:32 +0100
commitee775891043d428c084748dbf435b80401ab64ae (patch)
tree5514e38c9c201c742df76cf1fa0fde3c9b085754 /jsonschema/_validators.py
parent00031cb043763842266877923552e40f0c8f36b5 (diff)
downloadjsonschema-ee775891043d428c084748dbf435b80401ab64ae.tar.gz
Reimplement contains.
Fixes a bug where maxContains was being ignored if minContains was set to 0. Also now short circuits as soon as more than maxContains is reached rather than continuing to validate.
Diffstat (limited to 'jsonschema/_validators.py')
-rw-r--r--jsonschema/_validators.py64
1 files changed, 20 insertions, 44 deletions
diff --git a/jsonschema/_validators.py b/jsonschema/_validators.py
index 2c0df8f..2784c09 100644
--- a/jsonschema/_validators.py
+++ b/jsonschema/_validators.py
@@ -119,55 +119,31 @@ def contains(validator, contains, instance, schema):
if not validator.is_type(instance, "array"):
return
- min_contains = max_contains = None
-
- if "minContains" in schema:
- min_contains = schema["minContains"]
-
- if "maxContains" in schema:
- max_contains = schema["maxContains"]
-
- # minContains set to 0 will ignore contains
- if min_contains == 0:
- return
-
- matches = sum(1 for each in instance if validator.is_valid(each, contains))
-
- if not matches:
- yield ValidationError(
- f"{instance!r} does not contain items matching the given schema",
- )
- return
-
- if min_contains and max_contains is None:
- if matches < min_contains:
- yield ValidationError(
- "Too few items match the given schema "
- f"(expected {min_contains} but only {matches} matched)",
- )
- return
-
- if min_contains is None and max_contains:
- if matches > max_contains:
+ matches = 0
+ min_contains = schema.get("minContains", 1)
+ max_contains = schema.get("maxContains", len(instance))
+
+ for each in instance:
+ if validator.is_valid(each, contains):
+ matches += 1
+ if matches > max_contains:
+ yield ValidationError(
+ "Too many items match the given schema "
+ f"(expected at most {max_contains})",
+ )
+ return
+
+ if matches < min_contains:
+ if not matches:
yield ValidationError(
- "Too many items match the given schema "
- f"(expected at most {max_contains} but {matches} matched)",
+ f"{instance!r} does not contain items "
+ "matching the given schema",
)
- return
-
- if min_contains and max_contains:
- if matches < min_contains:
- only = "only "
- elif matches > max_contains:
- only = ""
else:
- only = None
- if only is not None:
yield ValidationError(
- f"Expected between {min_contains} and {max_contains} items "
- f"to match the given schema but {only}{matches} matched",
+ "Too few items match the given schema (expected at least "
+ f"{min_contains} but only {matches} matched)",
)
- return
def exclusiveMinimum(validator, minimum, instance, schema):