diff options
author | Harald Nezbeda <hn@nezhar.com> | 2021-06-17 08:50:14 +0200 |
---|---|---|
committer | Harald Nezbeda <hn@nezhar.com> | 2021-07-19 18:14:31 +0200 |
commit | 96b7fe8a2e0827d19637d6a854c5161738e284a4 (patch) | |
tree | 1c09a09fbf2d465b6bc4415c8bfa8d74d2414f07 | |
parent | 753c415866986d413a270c8a199225bdacf62ddb (diff) | |
download | jsonschema-96b7fe8a2e0827d19637d6a854c5161738e284a4.tar.gz |
Julian/jsonschema#782: Extend contains with minContains and maxContaints, add contains legacy validator
-rw-r--r-- | jsonschema/_legacy_validators.py | 10 | ||||
-rw-r--r-- | jsonschema/_validators.py | 55 | ||||
-rw-r--r-- | jsonschema/validators.py | 4 |
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, |