Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jsonschema/_validators.py: 16%
267 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1from fractions import Fraction
2from urllib.parse import urldefrag, urljoin
3import re
5from jsonschema._utils import (
6 ensure_list,
7 equal,
8 extras_msg,
9 find_additional_properties,
10 find_evaluated_item_indexes_by_schema,
11 find_evaluated_property_keys_by_schema,
12 unbool,
13 uniq,
14)
15from jsonschema.exceptions import FormatError, ValidationError
18def patternProperties(validator, patternProperties, instance, schema):
19 if not validator.is_type(instance, "object"):
20 return
22 for pattern, subschema in patternProperties.items():
23 for k, v in instance.items():
24 if re.search(pattern, k):
25 yield from validator.descend(
26 v, subschema, path=k, schema_path=pattern,
27 )
30def propertyNames(validator, propertyNames, instance, schema):
31 if not validator.is_type(instance, "object"):
32 return
34 for property in instance:
35 yield from validator.descend(instance=property, schema=propertyNames)
38def additionalProperties(validator, aP, instance, schema):
39 if not validator.is_type(instance, "object"):
40 return
42 extras = set(find_additional_properties(instance, schema))
44 if validator.is_type(aP, "object"):
45 for extra in extras:
46 yield from validator.descend(instance[extra], aP, path=extra)
47 elif not aP and extras:
48 if "patternProperties" in schema:
49 if len(extras) == 1:
50 verb = "does"
51 else:
52 verb = "do"
54 joined = ", ".join(repr(each) for each in sorted(extras))
55 patterns = ", ".join(
56 repr(each) for each in sorted(schema["patternProperties"])
57 )
58 error = f"{joined} {verb} not match any of the regexes: {patterns}"
59 yield ValidationError(error)
60 else:
61 error = "Additional properties are not allowed (%s %s unexpected)"
62 yield ValidationError(error % extras_msg(extras))
65def items(validator, items, instance, schema):
66 if not validator.is_type(instance, "array"):
67 return
69 prefix = len(schema.get("prefixItems", []))
70 total = len(instance)
71 if items is False and total > prefix:
72 message = f"Expected at most {prefix} items, but found {total}"
73 yield ValidationError(message)
74 else:
75 for index in range(prefix, total):
76 yield from validator.descend(
77 instance=instance[index],
78 schema=items,
79 path=index,
80 )
83def additionalItems(validator, aI, instance, schema):
84 if (
85 not validator.is_type(instance, "array")
86 or validator.is_type(schema.get("items", {}), "object")
87 ):
88 return
90 len_items = len(schema.get("items", []))
91 if validator.is_type(aI, "object"):
92 for index, item in enumerate(instance[len_items:], start=len_items):
93 yield from validator.descend(item, aI, path=index)
94 elif not aI and len(instance) > len(schema.get("items", [])):
95 error = "Additional items are not allowed (%s %s unexpected)"
96 yield ValidationError(
97 error % extras_msg(instance[len(schema.get("items", [])):]),
98 )
101def const(validator, const, instance, schema):
102 if not equal(instance, const):
103 yield ValidationError(f"{const!r} was expected")
106def contains(validator, contains, instance, schema):
107 if not validator.is_type(instance, "array"):
108 return
110 matches = 0
111 min_contains = schema.get("minContains", 1)
112 max_contains = schema.get("maxContains", len(instance))
114 for each in instance:
115 if validator.evolve(schema=contains).is_valid(each):
116 matches += 1
117 if matches > max_contains:
118 yield ValidationError(
119 "Too many items match the given schema "
120 f"(expected at most {max_contains})",
121 validator="maxContains",
122 validator_value=max_contains,
123 )
124 return
126 if matches < min_contains:
127 if not matches:
128 yield ValidationError(
129 f"{instance!r} does not contain items "
130 "matching the given schema",
131 )
132 else:
133 yield ValidationError(
134 "Too few items match the given schema (expected at least "
135 f"{min_contains} but only {matches} matched)",
136 validator="minContains",
137 validator_value=min_contains,
138 )
141def exclusiveMinimum(validator, minimum, instance, schema):
142 if not validator.is_type(instance, "number"):
143 return
145 if instance <= minimum:
146 yield ValidationError(
147 f"{instance!r} is less than or equal to "
148 f"the minimum of {minimum!r}",
149 )
152def exclusiveMaximum(validator, maximum, instance, schema):
153 if not validator.is_type(instance, "number"):
154 return
156 if instance >= maximum:
157 yield ValidationError(
158 f"{instance!r} is greater than or equal "
159 f"to the maximum of {maximum!r}",
160 )
163def minimum(validator, minimum, instance, schema):
164 if not validator.is_type(instance, "number"):
165 return
167 if instance < minimum:
168 message = f"{instance!r} is less than the minimum of {minimum!r}"
169 yield ValidationError(message)
172def maximum(validator, maximum, instance, schema):
173 if not validator.is_type(instance, "number"):
174 return
176 if instance > maximum:
177 message = f"{instance!r} is greater than the maximum of {maximum!r}"
178 yield ValidationError(message)
181def multipleOf(validator, dB, instance, schema):
182 if not validator.is_type(instance, "number"):
183 return
185 if isinstance(dB, float):
186 quotient = instance / dB
187 try:
188 failed = int(quotient) != quotient
189 except OverflowError:
190 # When `instance` is large and `dB` is less than one,
191 # quotient can overflow to infinity; and then casting to int
192 # raises an error.
193 #
194 # In this case we fall back to Fraction logic, which is
195 # exact and cannot overflow. The performance is also
196 # acceptable: we try the fast all-float option first, and
197 # we know that fraction(dB) can have at most a few hundred
198 # digits in each part. The worst-case slowdown is therefore
199 # for already-slow enormous integers or Decimals.
200 failed = (Fraction(instance) / Fraction(dB)).denominator != 1
201 else:
202 failed = instance % dB
204 if failed:
205 yield ValidationError(f"{instance!r} is not a multiple of {dB}")
208def minItems(validator, mI, instance, schema):
209 if validator.is_type(instance, "array") and len(instance) < mI:
210 yield ValidationError(f"{instance!r} is too short")
213def maxItems(validator, mI, instance, schema):
214 if validator.is_type(instance, "array") and len(instance) > mI:
215 yield ValidationError(f"{instance!r} is too long")
218def uniqueItems(validator, uI, instance, schema):
219 if (
220 uI
221 and validator.is_type(instance, "array")
222 and not uniq(instance)
223 ):
224 yield ValidationError(f"{instance!r} has non-unique elements")
227def pattern(validator, patrn, instance, schema):
228 if (
229 validator.is_type(instance, "string")
230 and not re.search(patrn, instance)
231 ):
232 yield ValidationError(f"{instance!r} does not match {patrn!r}")
235def format(validator, format, instance, schema):
236 if validator.format_checker is not None:
237 try:
238 validator.format_checker.check(instance, format)
239 except FormatError as error:
240 yield ValidationError(error.message, cause=error.cause)
243def minLength(validator, mL, instance, schema):
244 if validator.is_type(instance, "string") and len(instance) < mL:
245 yield ValidationError(f"{instance!r} is too short")
248def maxLength(validator, mL, instance, schema):
249 if validator.is_type(instance, "string") and len(instance) > mL:
250 yield ValidationError(f"{instance!r} is too long")
253def dependentRequired(validator, dependentRequired, instance, schema):
254 if not validator.is_type(instance, "object"):
255 return
257 for property, dependency in dependentRequired.items():
258 if property not in instance:
259 continue
261 for each in dependency:
262 if each not in instance:
263 message = f"{each!r} is a dependency of {property!r}"
264 yield ValidationError(message)
267def dependentSchemas(validator, dependentSchemas, instance, schema):
268 if not validator.is_type(instance, "object"):
269 return
271 for property, dependency in dependentSchemas.items():
272 if property not in instance:
273 continue
274 yield from validator.descend(
275 instance, dependency, schema_path=property,
276 )
279def enum(validator, enums, instance, schema):
280 if instance == 0 or instance == 1:
281 unbooled = unbool(instance)
282 if all(unbooled != unbool(each) for each in enums):
283 yield ValidationError(f"{instance!r} is not one of {enums!r}")
284 elif instance not in enums:
285 yield ValidationError(f"{instance!r} is not one of {enums!r}")
288def ref(validator, ref, instance, schema):
289 resolve = getattr(validator.resolver, "resolve", None)
290 if resolve is None:
291 with validator.resolver.resolving(ref) as resolved:
292 yield from validator.descend(instance, resolved)
293 else:
294 scope, resolved = validator.resolver.resolve(ref)
295 validator.resolver.push_scope(scope)
297 try:
298 yield from validator.descend(instance, resolved)
299 finally:
300 validator.resolver.pop_scope()
303def dynamicRef(validator, dynamicRef, instance, schema):
304 _, fragment = urldefrag(dynamicRef)
306 for url in validator.resolver._scopes_stack:
307 lookup_url = urljoin(url, dynamicRef)
308 with validator.resolver.resolving(lookup_url) as subschema:
309 if ("$dynamicAnchor" in subschema
310 and fragment == subschema["$dynamicAnchor"]):
311 yield from validator.descend(instance, subschema)
312 break
313 else:
314 with validator.resolver.resolving(dynamicRef) as subschema:
315 yield from validator.descend(instance, subschema)
318def type(validator, types, instance, schema):
319 types = ensure_list(types)
321 if not any(validator.is_type(instance, type) for type in types):
322 reprs = ", ".join(repr(type) for type in types)
323 yield ValidationError(f"{instance!r} is not of type {reprs}")
326def properties(validator, properties, instance, schema):
327 if not validator.is_type(instance, "object"):
328 return
330 for property, subschema in properties.items():
331 if property in instance:
332 yield from validator.descend(
333 instance[property],
334 subschema,
335 path=property,
336 schema_path=property,
337 )
340def required(validator, required, instance, schema):
341 if not validator.is_type(instance, "object"):
342 return
343 for property in required:
344 if property not in instance:
345 yield ValidationError(f"{property!r} is a required property")
348def minProperties(validator, mP, instance, schema):
349 if validator.is_type(instance, "object") and len(instance) < mP:
350 yield ValidationError(f"{instance!r} does not have enough properties")
353def maxProperties(validator, mP, instance, schema):
354 if not validator.is_type(instance, "object"):
355 return
356 if validator.is_type(instance, "object") and len(instance) > mP:
357 yield ValidationError(f"{instance!r} has too many properties")
360def allOf(validator, allOf, instance, schema):
361 for index, subschema in enumerate(allOf):
362 yield from validator.descend(instance, subschema, schema_path=index)
365def anyOf(validator, anyOf, instance, schema):
366 all_errors = []
367 for index, subschema in enumerate(anyOf):
368 errs = list(validator.descend(instance, subschema, schema_path=index))
369 if not errs:
370 break
371 all_errors.extend(errs)
372 else:
373 yield ValidationError(
374 f"{instance!r} is not valid under any of the given schemas",
375 context=all_errors,
376 )
379def oneOf(validator, oneOf, instance, schema):
380 subschemas = enumerate(oneOf)
381 all_errors = []
382 for index, subschema in subschemas:
383 errs = list(validator.descend(instance, subschema, schema_path=index))
384 if not errs:
385 first_valid = subschema
386 break
387 all_errors.extend(errs)
388 else:
389 yield ValidationError(
390 f"{instance!r} is not valid under any of the given schemas",
391 context=all_errors,
392 )
394 more_valid = [
395 each for _, each in subschemas
396 if validator.evolve(schema=each).is_valid(instance)
397 ]
398 if more_valid:
399 more_valid.append(first_valid)
400 reprs = ", ".join(repr(schema) for schema in more_valid)
401 yield ValidationError(f"{instance!r} is valid under each of {reprs}")
404def not_(validator, not_schema, instance, schema):
405 if validator.evolve(schema=not_schema).is_valid(instance):
406 message = f"{instance!r} should not be valid under {not_schema!r}"
407 yield ValidationError(message)
410def if_(validator, if_schema, instance, schema):
411 if validator.evolve(schema=if_schema).is_valid(instance):
412 if "then" in schema:
413 then = schema["then"]
414 yield from validator.descend(instance, then, schema_path="then")
415 elif "else" in schema:
416 else_ = schema["else"]
417 yield from validator.descend(instance, else_, schema_path="else")
420def unevaluatedItems(validator, unevaluatedItems, instance, schema):
421 if not validator.is_type(instance, "array"):
422 return
423 evaluated_item_indexes = find_evaluated_item_indexes_by_schema(
424 validator, instance, schema,
425 )
426 unevaluated_items = [
427 item for index, item in enumerate(instance)
428 if index not in evaluated_item_indexes
429 ]
430 if unevaluated_items:
431 error = "Unevaluated items are not allowed (%s %s unexpected)"
432 yield ValidationError(error % extras_msg(unevaluated_items))
435def unevaluatedProperties(validator, unevaluatedProperties, instance, schema):
436 if not validator.is_type(instance, "object"):
437 return
438 evaluated_keys = find_evaluated_property_keys_by_schema(
439 validator, instance, schema,
440 )
441 unevaluated_keys = []
442 for property in instance:
443 if property not in evaluated_keys:
444 for _ in validator.descend(
445 instance[property],
446 unevaluatedProperties,
447 path=property,
448 schema_path=property,
449 ):
450 # FIXME: Include context for each unevaluated property
451 # indicating why it's invalid under the subschema.
452 unevaluated_keys.append(property)
454 if unevaluated_keys:
455 if unevaluatedProperties is False:
456 error = "Unevaluated properties are not allowed (%s %s unexpected)"
457 yield ValidationError(error % extras_msg(unevaluated_keys))
458 else:
459 error = (
460 "Unevaluated properties are not valid under "
461 "the given schema (%s %s unevaluated and invalid)"
462 )
463 yield ValidationError(error % extras_msg(unevaluated_keys))
466def prefixItems(validator, prefixItems, instance, schema):
467 if not validator.is_type(instance, "array"):
468 return
470 for (index, item), subschema in zip(enumerate(instance), prefixItems):
471 yield from validator.descend(
472 instance=item,
473 schema=subschema,
474 schema_path=index,
475 path=index,
476 )