Skip to content

Commit e19671c

Browse files
committed
#782: Extend contains with minContains and maxContaints, add contains legacy validator
1 parent 63bf275 commit e19671c

File tree

3 files changed

+66
-3
lines changed

3 files changed

+66
-3
lines changed

jsonschema/_legacy_validators.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,13 @@ def type_draft3(validator, types, instance, schema):
138138
yield ValidationError(
139139
_utils.types_msg(instance, types), context=all_errors,
140140
)
141+
142+
143+
def contains_draft6_draft7(validator, contains, instance, schema):
144+
if not validator.is_type(instance, "array"):
145+
return
146+
147+
if not any(validator.is_valid(element, contains) for element in instance):
148+
yield ValidationError(
149+
"None of %r are valid under the given schema" % (instance,)
150+
)

jsonschema/_validators.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,63 @@ def contains(validator, contains, instance, schema):
137137
if not validator.is_type(instance, "array"):
138138
return
139139

140-
if not any(validator.is_valid(element, contains) for element in instance):
140+
min_contains = max_contains = None
141+
142+
if 'minContains' in schema:
143+
min_contains = schema['minContains']
144+
if not validator.is_type(min_contains, "integer"):
145+
yield ValidationError(
146+
"minContains of %r in not valid under the given schema" % (min_contains,)
147+
)
148+
return
149+
150+
if 'maxContains' in schema:
151+
max_contains = schema['maxContains']
152+
if not validator.is_type(max_contains, "integer"):
153+
yield ValidationError(
154+
"maxContains of %r is not valid under the given schema" % (instance,)
155+
)
156+
return
157+
158+
# minContains set to 0 will ignore contains
159+
if min_contains == 0:
160+
return
161+
162+
matches = len(list(filter(lambda x: x, [validator.is_valid(element, contains) for element in instance])))
163+
164+
# default contains behavior
165+
if not matches:
141166
yield ValidationError(
142167
"None of %r are valid under the given schema" % (instance,)
143168
)
169+
return
170+
171+
if min_contains and max_contains is None:
172+
if matches < min_contains:
173+
yield ValidationError(
174+
"Invalid number or matches of %r under the given schema, expected min %d, got %d" % (
175+
instance, min_contains, matches
176+
)
177+
)
178+
return
179+
180+
if min_contains is None and max_contains:
181+
if matches > max_contains:
182+
yield ValidationError(
183+
"Invalid number or matches of %r under the given schema, expected max %d, got %d" % (
184+
instance, max_contains, matches
185+
)
186+
)
187+
return
188+
189+
if min_contains and max_contains:
190+
if matches < min_contains or matches > max_contains:
191+
yield ValidationError(
192+
"Invalid number or matches of %r under the given schema, expected min %d and max %d, got %d" % (
193+
instance, min_contains, max_contains, matches
194+
)
195+
)
196+
return
144197

145198

146199
def exclusiveMinimum(validator, minimum, instance, schema):

jsonschema/validators.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ def extend(validator, validators=(), version=None, type_checker=None):
358358
u"allOf": _validators.allOf,
359359
u"anyOf": _validators.anyOf,
360360
u"const": _validators.const,
361-
u"contains": _validators.contains,
361+
u"contains": _legacy_validators.contains_draft6_draft7,
362362
u"dependencies": _validators.dependencies,
363363
u"enum": _validators.enum,
364364
u"exclusiveMaximum": _validators.exclusiveMaximum,
@@ -397,7 +397,7 @@ def extend(validator, validators=(), version=None, type_checker=None):
397397
u"allOf": _validators.allOf,
398398
u"anyOf": _validators.anyOf,
399399
u"const": _validators.const,
400-
u"contains": _validators.contains,
400+
u"contains": _legacy_validators.contains_draft6_draft7,
401401
u"dependencies": _validators.dependencies,
402402
u"enum": _validators.enum,
403403
u"exclusiveMaximum": _validators.exclusiveMaximum,

0 commit comments

Comments
 (0)