summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarald Nezbeda <hn@nezhar.com>2021-06-17 08:50:14 +0200
committerHarald Nezbeda <hn@nezhar.com>2021-07-19 18:14:31 +0200
commit96b7fe8a2e0827d19637d6a854c5161738e284a4 (patch)
tree1c09a09fbf2d465b6bc4415c8bfa8d74d2414f07
parent753c415866986d413a270c8a199225bdacf62ddb (diff)
downloadjsonschema-96b7fe8a2e0827d19637d6a854c5161738e284a4.tar.gz
Julian/jsonschema#782: Extend contains with minContains and maxContaints, add contains legacy validator
-rw-r--r--jsonschema/_legacy_validators.py10
-rw-r--r--jsonschema/_validators.py55
-rw-r--r--jsonschema/validators.py4
3 files changed, 66 insertions, 3 deletions
diff --git a/jsonschema/_legacy_validators.py b/jsonschema/_legacy_validators.py
index 80f798b..26f1ab1 100644
--- a/jsonschema/_legacy_validators.py
+++ b/jsonschema/_legacy_validators.py
@@ -138,3 +138,13 @@ def type_draft3(validator, types, instance, schema):
yield ValidationError(
_utils.types_msg(instance, types), context=all_errors,
)
+
+
+def contains_draft6_draft7(validator, contains, instance, schema):
+ if not validator.is_type(instance, "array"):
+ return
+
+ if not any(validator.is_valid(element, contains) for element in instance):
+ yield ValidationError(
+ "None of %r are valid under the given schema" % (instance,)
+ )
diff --git a/jsonschema/_validators.py b/jsonschema/_validators.py
index 5a1f56a..0ca215a 100644
--- a/jsonschema/_validators.py
+++ b/jsonschema/_validators.py
@@ -127,10 +127,63 @@ def contains(validator, contains, instance, schema):
if not validator.is_type(instance, "array"):
return
- if not any(validator.is_valid(element, contains) for element in instance):
+ min_contains = max_contains = None
+
+ if 'minContains' in schema:
+ min_contains = schema['minContains']
+ if not validator.is_type(min_contains, "integer"):
+ yield ValidationError(
+ "minContains of %r in not valid under the given schema" % (min_contains,)
+ )
+ return
+
+ if 'maxContains' in schema:
+ max_contains = schema['maxContains']
+ if not validator.is_type(max_contains, "integer"):
+ yield ValidationError(
+ "maxContains of %r is not valid under the given schema" % (instance,)
+ )
+ return
+
+ # minContains set to 0 will ignore contains
+ if min_contains == 0:
+ return
+
+ matches = len(list(filter(lambda x: x, [validator.is_valid(element, contains) for element in instance])))
+
+ # default contains behavior
+ if not matches:
yield ValidationError(
"None of %r are valid under the given schema" % (instance,)
)
+ return
+
+ if min_contains and max_contains is None:
+ if matches < min_contains:
+ yield ValidationError(
+ "Invalid number or matches of %r under the given schema, expected min %d, got %d" % (
+ instance, min_contains, matches
+ )
+ )
+ return
+
+ if min_contains is None and max_contains:
+ if matches > max_contains:
+ yield ValidationError(
+ "Invalid number or matches of %r under the given schema, expected max %d, got %d" % (
+ instance, max_contains, matches
+ )
+ )
+ return
+
+ if min_contains and max_contains:
+ if matches < min_contains or matches > max_contains:
+ yield ValidationError(
+ "Invalid number or matches of %r under the given schema, expected min %d and max %d, got %d" % (
+ instance, min_contains, max_contains, matches
+ )
+ )
+ return
def exclusiveMinimum(validator, minimum, instance, schema):
diff --git a/jsonschema/validators.py b/jsonschema/validators.py
index 3d382b2..dae3ddb 100644
--- a/jsonschema/validators.py
+++ b/jsonschema/validators.py
@@ -358,7 +358,7 @@ Draft6Validator = create(
u"allOf": _validators.allOf,
u"anyOf": _validators.anyOf,
u"const": _validators.const,
- u"contains": _validators.contains,
+ u"contains": _legacy_validators.contains_draft6_draft7,
u"dependencies": _validators.dependencies,
u"enum": _validators.enum,
u"exclusiveMaximum": _validators.exclusiveMaximum,
@@ -397,7 +397,7 @@ Draft7Validator = create(
u"allOf": _validators.allOf,
u"anyOf": _validators.anyOf,
u"const": _validators.const,
- u"contains": _validators.contains,
+ u"contains": _legacy_validators.contains_draft6_draft7,
u"dependencies": _validators.dependencies,
u"enum": _validators.enum,
u"exclusiveMaximum": _validators.exclusiveMaximum,