Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jsonschema/_legacy_keywords.py: 9%
238 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
1import re
3from referencing.jsonschema import lookup_recursive_ref
5from jsonschema import _utils
6from jsonschema.exceptions import ValidationError
9def ignore_ref_siblings(schema):
10 """
11 Ignore siblings of ``$ref`` if it is present.
13 Otherwise, return all keywords.
15 Suitable for use with `create`'s ``applicable_validators`` argument.
16 """
17 ref = schema.get("$ref")
18 if ref is not None:
19 return [("$ref", ref)]
20 else:
21 return schema.items()
24def dependencies_draft3(validator, dependencies, instance, schema):
25 if not validator.is_type(instance, "object"):
26 return
28 for property, dependency in dependencies.items():
29 if property not in instance:
30 continue
32 if validator.is_type(dependency, "object"):
33 yield from validator.descend(
34 instance, dependency, schema_path=property,
35 )
36 elif validator.is_type(dependency, "string"):
37 if dependency not in instance:
38 message = f"{dependency!r} is a dependency of {property!r}"
39 yield ValidationError(message)
40 else:
41 for each in dependency:
42 if each not in instance:
43 message = f"{each!r} is a dependency of {property!r}"
44 yield ValidationError(message)
47def dependencies_draft4_draft6_draft7(
48 validator,
49 dependencies,
50 instance,
51 schema,
52):
53 """
54 Support for the ``dependencies`` keyword from pre-draft 2019-09.
56 In later drafts, the keyword was split into separate
57 ``dependentRequired`` and ``dependentSchemas`` validators.
58 """
59 if not validator.is_type(instance, "object"):
60 return
62 for property, dependency in dependencies.items():
63 if property not in instance:
64 continue
66 if validator.is_type(dependency, "array"):
67 for each in dependency:
68 if each not in instance:
69 message = f"{each!r} is a dependency of {property!r}"
70 yield ValidationError(message)
71 else:
72 yield from validator.descend(
73 instance, dependency, schema_path=property,
74 )
77def disallow_draft3(validator, disallow, instance, schema):
78 for disallowed in _utils.ensure_list(disallow):
79 if validator.evolve(schema={"type": [disallowed]}).is_valid(instance):
80 message = f"{disallowed!r} is disallowed for {instance!r}"
81 yield ValidationError(message)
84def extends_draft3(validator, extends, instance, schema):
85 if validator.is_type(extends, "object"):
86 yield from validator.descend(instance, extends)
87 return
88 for index, subschema in enumerate(extends):
89 yield from validator.descend(instance, subschema, schema_path=index)
92def items_draft3_draft4(validator, items, instance, schema):
93 if not validator.is_type(instance, "array"):
94 return
96 if validator.is_type(items, "object"):
97 for index, item in enumerate(instance):
98 yield from validator.descend(item, items, path=index)
99 else:
100 for (index, item), subschema in zip(enumerate(instance), items):
101 yield from validator.descend(
102 item, subschema, path=index, schema_path=index,
103 )
106def additionalItems(validator, aI, instance, schema):
107 if (
108 not validator.is_type(instance, "array")
109 or validator.is_type(schema.get("items", {}), "object")
110 ):
111 return
113 len_items = len(schema.get("items", []))
114 if validator.is_type(aI, "object"):
115 for index, item in enumerate(instance[len_items:], start=len_items):
116 yield from validator.descend(item, aI, path=index)
117 elif not aI and len(instance) > len(schema.get("items", [])):
118 error = "Additional items are not allowed (%s %s unexpected)"
119 yield ValidationError(
120 error % _utils.extras_msg(instance[len(schema.get("items", [])):]),
121 )
124def items_draft6_draft7_draft201909(validator, items, instance, schema):
125 if not validator.is_type(instance, "array"):
126 return
128 if validator.is_type(items, "array"):
129 for (index, item), subschema in zip(enumerate(instance), items):
130 yield from validator.descend(
131 item, subschema, path=index, schema_path=index,
132 )
133 else:
134 for index, item in enumerate(instance):
135 yield from validator.descend(item, items, path=index)
138def minimum_draft3_draft4(validator, minimum, instance, schema):
139 if not validator.is_type(instance, "number"):
140 return
142 if schema.get("exclusiveMinimum", False):
143 failed = instance <= minimum
144 cmp = "less than or equal to"
145 else:
146 failed = instance < minimum
147 cmp = "less than"
149 if failed:
150 message = f"{instance!r} is {cmp} the minimum of {minimum!r}"
151 yield ValidationError(message)
154def maximum_draft3_draft4(validator, maximum, instance, schema):
155 if not validator.is_type(instance, "number"):
156 return
158 if schema.get("exclusiveMaximum", False):
159 failed = instance >= maximum
160 cmp = "greater than or equal to"
161 else:
162 failed = instance > maximum
163 cmp = "greater than"
165 if failed:
166 message = f"{instance!r} is {cmp} the maximum of {maximum!r}"
167 yield ValidationError(message)
170def properties_draft3(validator, properties, instance, schema):
171 if not validator.is_type(instance, "object"):
172 return
174 for property, subschema in properties.items():
175 if property in instance:
176 yield from validator.descend(
177 instance[property],
178 subschema,
179 path=property,
180 schema_path=property,
181 )
182 elif subschema.get("required", False):
183 error = ValidationError(f"{property!r} is a required property")
184 error._set(
185 validator="required",
186 validator_value=subschema["required"],
187 instance=instance,
188 schema=schema,
189 )
190 error.path.appendleft(property)
191 error.schema_path.extend([property, "required"])
192 yield error
195def type_draft3(validator, types, instance, schema):
196 types = _utils.ensure_list(types)
198 all_errors = []
199 for index, type in enumerate(types):
200 if validator.is_type(type, "object"):
201 errors = list(validator.descend(instance, type, schema_path=index))
202 if not errors:
203 return
204 all_errors.extend(errors)
205 else:
206 if validator.is_type(instance, type):
207 return
208 else:
209 reprs = []
210 for type in types:
211 try:
212 reprs.append(repr(type["name"]))
213 except Exception:
214 reprs.append(repr(type))
215 yield ValidationError(
216 f"{instance!r} is not of type {', '.join(reprs)}",
217 context=all_errors,
218 )
221def contains_draft6_draft7(validator, contains, instance, schema):
222 if not validator.is_type(instance, "array"):
223 return
225 if not any(
226 validator.evolve(schema=contains).is_valid(element)
227 for element in instance
228 ):
229 yield ValidationError(
230 f"None of {instance!r} are valid under the given schema",
231 )
234def recursiveRef(validator, recursiveRef, instance, schema):
235 resolved = lookup_recursive_ref(validator._resolver)
236 yield from validator.descend(
237 instance,
238 resolved.contents,
239 resolver=resolved.resolver,
240 )
243def find_evaluated_item_indexes_by_schema(validator, instance, schema):
244 """
245 Get all indexes of items that get evaluated under the current schema.
247 Covers all keywords related to unevaluatedItems: items, prefixItems, if,
248 then, else, contains, unevaluatedItems, allOf, oneOf, anyOf
249 """
250 if validator.is_type(schema, "boolean"):
251 return []
252 evaluated_indexes = []
254 ref = schema.get("$ref")
255 if ref is not None:
256 resolved = validator._resolver.lookup(ref)
257 evaluated_indexes.extend(
258 find_evaluated_item_indexes_by_schema(
259 validator.evolve(
260 schema=resolved.contents,
261 _resolver=resolved.resolver,
262 ),
263 instance,
264 resolved.contents,
265 ),
266 )
268 if "$recursiveRef" in schema:
269 resolved = lookup_recursive_ref(validator._resolver)
270 evaluated_indexes.extend(
271 find_evaluated_item_indexes_by_schema(
272 validator.evolve(
273 schema=resolved.contents,
274 _resolver=resolved.resolver,
275 ),
276 instance,
277 resolved.contents,
278 ),
279 )
281 if "items" in schema:
282 if "additionalItems" in schema:
283 return list(range(0, len(instance)))
285 if validator.is_type(schema["items"], "object"):
286 return list(range(0, len(instance)))
287 evaluated_indexes += list(range(0, len(schema["items"])))
289 if "if" in schema:
290 if validator.evolve(schema=schema["if"]).is_valid(instance):
291 evaluated_indexes += find_evaluated_item_indexes_by_schema(
292 validator, instance, schema["if"],
293 )
294 if "then" in schema:
295 evaluated_indexes += find_evaluated_item_indexes_by_schema(
296 validator, instance, schema["then"],
297 )
298 else:
299 if "else" in schema:
300 evaluated_indexes += find_evaluated_item_indexes_by_schema(
301 validator, instance, schema["else"],
302 )
304 for keyword in ["contains", "unevaluatedItems"]:
305 if keyword in schema:
306 for k, v in enumerate(instance):
307 if validator.evolve(schema=schema[keyword]).is_valid(v):
308 evaluated_indexes.append(k)
310 for keyword in ["allOf", "oneOf", "anyOf"]:
311 if keyword in schema:
312 for subschema in schema[keyword]:
313 errs = next(validator.descend(instance, subschema), None)
314 if errs is None:
315 evaluated_indexes += find_evaluated_item_indexes_by_schema(
316 validator, instance, subschema,
317 )
319 return evaluated_indexes
322def unevaluatedItems_draft2019(validator, unevaluatedItems, instance, schema):
323 if not validator.is_type(instance, "array"):
324 return
325 evaluated_item_indexes = find_evaluated_item_indexes_by_schema(
326 validator, instance, schema,
327 )
328 unevaluated_items = [
329 item for index, item in enumerate(instance)
330 if index not in evaluated_item_indexes
331 ]
332 if unevaluated_items:
333 error = "Unevaluated items are not allowed (%s %s unexpected)"
334 yield ValidationError(error % _utils.extras_msg(unevaluated_items))
337def find_evaluated_property_keys_by_schema(validator, instance, schema):
338 if validator.is_type(schema, "boolean"):
339 return []
340 evaluated_keys = []
342 ref = schema.get("$ref")
343 if ref is not None:
344 resolved = validator._resolver.lookup(ref)
345 evaluated_keys.extend(
346 find_evaluated_property_keys_by_schema(
347 validator.evolve(
348 schema=resolved.contents,
349 _resolver=resolved.resolver,
350 ),
351 instance,
352 resolved.contents,
353 ),
354 )
356 if "$recursiveRef" in schema:
357 resolved = lookup_recursive_ref(validator._resolver)
358 evaluated_keys.extend(
359 find_evaluated_property_keys_by_schema(
360 validator.evolve(
361 schema=resolved.contents,
362 _resolver=resolved.resolver,
363 ),
364 instance,
365 resolved.contents,
366 ),
367 )
369 for keyword in [
370 "properties", "additionalProperties", "unevaluatedProperties",
371 ]:
372 if keyword in schema:
373 schema_value = schema[keyword]
374 if validator.is_type(schema_value, "boolean") and schema_value:
375 evaluated_keys += instance.keys()
377 elif validator.is_type(schema_value, "object"):
378 for property in schema_value:
379 if property in instance:
380 evaluated_keys.append(property)
382 if "patternProperties" in schema:
383 for property in instance:
384 for pattern in schema["patternProperties"]:
385 if re.search(pattern, property):
386 evaluated_keys.append(property)
388 if "dependentSchemas" in schema:
389 for property, subschema in schema["dependentSchemas"].items():
390 if property not in instance:
391 continue
392 evaluated_keys += find_evaluated_property_keys_by_schema(
393 validator, instance, subschema,
394 )
396 for keyword in ["allOf", "oneOf", "anyOf"]:
397 if keyword in schema:
398 for subschema in schema[keyword]:
399 errs = next(validator.descend(instance, subschema), None)
400 if errs is None:
401 evaluated_keys += find_evaluated_property_keys_by_schema(
402 validator, instance, subschema,
403 )
405 if "if" in schema:
406 if validator.evolve(schema=schema["if"]).is_valid(instance):
407 evaluated_keys += find_evaluated_property_keys_by_schema(
408 validator, instance, schema["if"],
409 )
410 if "then" in schema:
411 evaluated_keys += find_evaluated_property_keys_by_schema(
412 validator, instance, schema["then"],
413 )
414 else:
415 if "else" in schema:
416 evaluated_keys += find_evaluated_property_keys_by_schema(
417 validator, instance, schema["else"],
418 )
420 return evaluated_keys
423def unevaluatedProperties_draft2019(validator, uP, instance, schema):
424 if not validator.is_type(instance, "object"):
425 return
426 evaluated_keys = find_evaluated_property_keys_by_schema(
427 validator, instance, schema,
428 )
429 unevaluated_keys = []
430 for property in instance:
431 if property not in evaluated_keys:
432 for _ in validator.descend(
433 instance[property],
434 uP,
435 path=property,
436 schema_path=property,
437 ):
438 # FIXME: Include context for each unevaluated property
439 # indicating why it's invalid under the subschema.
440 unevaluated_keys.append(property)
442 if unevaluated_keys:
443 if uP is False:
444 error = "Unevaluated properties are not allowed (%s %s unexpected)"
445 extras = sorted(unevaluated_keys, key=str)
446 yield ValidationError(error % _utils.extras_msg(extras))
447 else:
448 error = (
449 "Unevaluated properties are not valid under "
450 "the given schema (%s %s unevaluated and invalid)"
451 )
452 yield ValidationError(error % _utils.extras_msg(unevaluated_keys))