about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/jsonschema/_legacy_keywords.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/jsonschema/_legacy_keywords.py')
-rw-r--r--.venv/lib/python3.12/site-packages/jsonschema/_legacy_keywords.py449
1 files changed, 449 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/jsonschema/_legacy_keywords.py b/.venv/lib/python3.12/site-packages/jsonschema/_legacy_keywords.py
new file mode 100644
index 00000000..c691589f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/jsonschema/_legacy_keywords.py
@@ -0,0 +1,449 @@
+import re
+
+from referencing.jsonschema import lookup_recursive_ref
+
+from jsonschema import _utils
+from jsonschema.exceptions import ValidationError
+
+
+def ignore_ref_siblings(schema):
+    """
+    Ignore siblings of ``$ref`` if it is present.
+
+    Otherwise, return all keywords.
+
+    Suitable for use with `create`'s ``applicable_validators`` argument.
+    """
+    ref = schema.get("$ref")
+    if ref is not None:
+        return [("$ref", ref)]
+    else:
+        return schema.items()
+
+
+def dependencies_draft3(validator, dependencies, instance, schema):
+    if not validator.is_type(instance, "object"):
+        return
+
+    for property, dependency in dependencies.items():
+        if property not in instance:
+            continue
+
+        if validator.is_type(dependency, "object"):
+            yield from validator.descend(
+                instance, dependency, schema_path=property,
+            )
+        elif validator.is_type(dependency, "string"):
+            if dependency not in instance:
+                message = f"{dependency!r} is a dependency of {property!r}"
+                yield ValidationError(message)
+        else:
+            for each in dependency:
+                if each not in instance:
+                    message = f"{each!r} is a dependency of {property!r}"
+                    yield ValidationError(message)
+
+
+def dependencies_draft4_draft6_draft7(
+    validator,
+    dependencies,
+    instance,
+    schema,
+):
+    """
+    Support for the ``dependencies`` keyword from pre-draft 2019-09.
+
+    In later drafts, the keyword was split into separate
+    ``dependentRequired`` and ``dependentSchemas`` validators.
+    """
+    if not validator.is_type(instance, "object"):
+        return
+
+    for property, dependency in dependencies.items():
+        if property not in instance:
+            continue
+
+        if validator.is_type(dependency, "array"):
+            for each in dependency:
+                if each not in instance:
+                    message = f"{each!r} is a dependency of {property!r}"
+                    yield ValidationError(message)
+        else:
+            yield from validator.descend(
+                instance, dependency, schema_path=property,
+            )
+
+
+def disallow_draft3(validator, disallow, instance, schema):
+    for disallowed in _utils.ensure_list(disallow):
+        if validator.evolve(schema={"type": [disallowed]}).is_valid(instance):
+            message = f"{disallowed!r} is disallowed for {instance!r}"
+            yield ValidationError(message)
+
+
+def extends_draft3(validator, extends, instance, schema):
+    if validator.is_type(extends, "object"):
+        yield from validator.descend(instance, extends)
+        return
+    for index, subschema in enumerate(extends):
+        yield from validator.descend(instance, subschema, schema_path=index)
+
+
+def items_draft3_draft4(validator, items, instance, schema):
+    if not validator.is_type(instance, "array"):
+        return
+
+    if validator.is_type(items, "object"):
+        for index, item in enumerate(instance):
+            yield from validator.descend(item, items, path=index)
+    else:
+        for (index, item), subschema in zip(enumerate(instance), items):
+            yield from validator.descend(
+                item, subschema, path=index, schema_path=index,
+            )
+
+
+def additionalItems(validator, aI, instance, schema):
+    if (
+        not validator.is_type(instance, "array")
+        or validator.is_type(schema.get("items", {}), "object")
+    ):
+        return
+
+    len_items = len(schema.get("items", []))
+    if validator.is_type(aI, "object"):
+        for index, item in enumerate(instance[len_items:], start=len_items):
+            yield from validator.descend(item, aI, path=index)
+    elif not aI and len(instance) > len(schema.get("items", [])):
+        error = "Additional items are not allowed (%s %s unexpected)"
+        yield ValidationError(
+            error % _utils.extras_msg(instance[len(schema.get("items", [])):]),
+        )
+
+
+def items_draft6_draft7_draft201909(validator, items, instance, schema):
+    if not validator.is_type(instance, "array"):
+        return
+
+    if validator.is_type(items, "array"):
+        for (index, item), subschema in zip(enumerate(instance), items):
+            yield from validator.descend(
+                item, subschema, path=index, schema_path=index,
+            )
+    else:
+        for index, item in enumerate(instance):
+            yield from validator.descend(item, items, path=index)
+
+
+def minimum_draft3_draft4(validator, minimum, instance, schema):
+    if not validator.is_type(instance, "number"):
+        return
+
+    if schema.get("exclusiveMinimum", False):
+        failed = instance <= minimum
+        cmp = "less than or equal to"
+    else:
+        failed = instance < minimum
+        cmp = "less than"
+
+    if failed:
+        message = f"{instance!r} is {cmp} the minimum of {minimum!r}"
+        yield ValidationError(message)
+
+
+def maximum_draft3_draft4(validator, maximum, instance, schema):
+    if not validator.is_type(instance, "number"):
+        return
+
+    if schema.get("exclusiveMaximum", False):
+        failed = instance >= maximum
+        cmp = "greater than or equal to"
+    else:
+        failed = instance > maximum
+        cmp = "greater than"
+
+    if failed:
+        message = f"{instance!r} is {cmp} the maximum of {maximum!r}"
+        yield ValidationError(message)
+
+
+def properties_draft3(validator, properties, instance, schema):
+    if not validator.is_type(instance, "object"):
+        return
+
+    for property, subschema in properties.items():
+        if property in instance:
+            yield from validator.descend(
+                instance[property],
+                subschema,
+                path=property,
+                schema_path=property,
+            )
+        elif subschema.get("required", False):
+            error = ValidationError(f"{property!r} is a required property")
+            error._set(
+                validator="required",
+                validator_value=subschema["required"],
+                instance=instance,
+                schema=schema,
+            )
+            error.path.appendleft(property)
+            error.schema_path.extend([property, "required"])
+            yield error
+
+
+def type_draft3(validator, types, instance, schema):
+    types = _utils.ensure_list(types)
+
+    all_errors = []
+    for index, type in enumerate(types):
+        if validator.is_type(type, "object"):
+            errors = list(validator.descend(instance, type, schema_path=index))
+            if not errors:
+                return
+            all_errors.extend(errors)
+        elif validator.is_type(instance, type):
+                return
+
+    reprs = []
+    for type in types:
+        try:
+            reprs.append(repr(type["name"]))
+        except Exception:  # noqa: BLE001
+            reprs.append(repr(type))
+    yield ValidationError(
+        f"{instance!r} is not of type {', '.join(reprs)}",
+        context=all_errors,
+    )
+
+
+def contains_draft6_draft7(validator, contains, instance, schema):
+    if not validator.is_type(instance, "array"):
+        return
+
+    if not any(
+        validator.evolve(schema=contains).is_valid(element)
+        for element in instance
+    ):
+        yield ValidationError(
+            f"None of {instance!r} are valid under the given schema",
+        )
+
+
+def recursiveRef(validator, recursiveRef, instance, schema):
+    resolved = lookup_recursive_ref(validator._resolver)
+    yield from validator.descend(
+        instance,
+        resolved.contents,
+        resolver=resolved.resolver,
+    )
+
+
+def find_evaluated_item_indexes_by_schema(validator, instance, schema):
+    """
+    Get all indexes of items that get evaluated under the current schema.
+
+    Covers all keywords related to unevaluatedItems: items, prefixItems, if,
+    then, else, contains, unevaluatedItems, allOf, oneOf, anyOf
+    """
+    if validator.is_type(schema, "boolean"):
+        return []
+    evaluated_indexes = []
+
+    ref = schema.get("$ref")
+    if ref is not None:
+        resolved = validator._resolver.lookup(ref)
+        evaluated_indexes.extend(
+            find_evaluated_item_indexes_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    if "$recursiveRef" in schema:
+        resolved = lookup_recursive_ref(validator._resolver)
+        evaluated_indexes.extend(
+            find_evaluated_item_indexes_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    if "items" in schema:
+        if "additionalItems" in schema:
+            return list(range(len(instance)))
+
+        if validator.is_type(schema["items"], "object"):
+            return list(range(len(instance)))
+        evaluated_indexes += list(range(len(schema["items"])))
+
+    if "if" in schema:
+        if validator.evolve(schema=schema["if"]).is_valid(instance):
+            evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                validator, instance, schema["if"],
+            )
+            if "then" in schema:
+                evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                    validator, instance, schema["then"],
+                )
+        elif "else" in schema:
+            evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                validator, instance, schema["else"],
+            )
+
+    for keyword in ["contains", "unevaluatedItems"]:
+        if keyword in schema:
+            for k, v in enumerate(instance):
+                if validator.evolve(schema=schema[keyword]).is_valid(v):
+                    evaluated_indexes.append(k)
+
+    for keyword in ["allOf", "oneOf", "anyOf"]:
+        if keyword in schema:
+            for subschema in schema[keyword]:
+                errs = next(validator.descend(instance, subschema), None)
+                if errs is None:
+                    evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                        validator, instance, subschema,
+                    )
+
+    return evaluated_indexes
+
+
+def unevaluatedItems_draft2019(validator, unevaluatedItems, instance, schema):
+    if not validator.is_type(instance, "array"):
+        return
+    evaluated_item_indexes = find_evaluated_item_indexes_by_schema(
+        validator, instance, schema,
+    )
+    unevaluated_items = [
+        item for index, item in enumerate(instance)
+        if index not in evaluated_item_indexes
+    ]
+    if unevaluated_items:
+        error = "Unevaluated items are not allowed (%s %s unexpected)"
+        yield ValidationError(error % _utils.extras_msg(unevaluated_items))
+
+
+def find_evaluated_property_keys_by_schema(validator, instance, schema):
+    if validator.is_type(schema, "boolean"):
+        return []
+    evaluated_keys = []
+
+    ref = schema.get("$ref")
+    if ref is not None:
+        resolved = validator._resolver.lookup(ref)
+        evaluated_keys.extend(
+            find_evaluated_property_keys_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    if "$recursiveRef" in schema:
+        resolved = lookup_recursive_ref(validator._resolver)
+        evaluated_keys.extend(
+            find_evaluated_property_keys_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    for keyword in [
+        "properties", "additionalProperties", "unevaluatedProperties",
+    ]:
+        if keyword in schema:
+            schema_value = schema[keyword]
+            if validator.is_type(schema_value, "boolean") and schema_value:
+                evaluated_keys += instance.keys()
+
+            elif validator.is_type(schema_value, "object"):
+                for property in schema_value:
+                    if property in instance:
+                        evaluated_keys.append(property)
+
+    if "patternProperties" in schema:
+        for property in instance:
+            for pattern in schema["patternProperties"]:
+                if re.search(pattern, property):
+                    evaluated_keys.append(property)
+
+    if "dependentSchemas" in schema:
+        for property, subschema in schema["dependentSchemas"].items():
+            if property not in instance:
+                continue
+            evaluated_keys += find_evaluated_property_keys_by_schema(
+                validator, instance, subschema,
+            )
+
+    for keyword in ["allOf", "oneOf", "anyOf"]:
+        if keyword in schema:
+            for subschema in schema[keyword]:
+                errs = next(validator.descend(instance, subschema), None)
+                if errs is None:
+                    evaluated_keys += find_evaluated_property_keys_by_schema(
+                        validator, instance, subschema,
+                    )
+
+    if "if" in schema:
+        if validator.evolve(schema=schema["if"]).is_valid(instance):
+            evaluated_keys += find_evaluated_property_keys_by_schema(
+                validator, instance, schema["if"],
+            )
+            if "then" in schema:
+                evaluated_keys += find_evaluated_property_keys_by_schema(
+                    validator, instance, schema["then"],
+                )
+        elif "else" in schema:
+            evaluated_keys += find_evaluated_property_keys_by_schema(
+                validator, instance, schema["else"],
+            )
+
+    return evaluated_keys
+
+
+def unevaluatedProperties_draft2019(validator, uP, instance, schema):
+    if not validator.is_type(instance, "object"):
+        return
+    evaluated_keys = find_evaluated_property_keys_by_schema(
+        validator, instance, schema,
+    )
+    unevaluated_keys = []
+    for property in instance:
+        if property not in evaluated_keys:
+            for _ in validator.descend(
+                instance[property],
+                uP,
+                path=property,
+                schema_path=property,
+            ):
+                # FIXME: Include context for each unevaluated property
+                #        indicating why it's invalid under the subschema.
+                unevaluated_keys.append(property)  # noqa: PERF401
+
+    if unevaluated_keys:
+        if uP is False:
+            error = "Unevaluated properties are not allowed (%s %s unexpected)"
+            extras = sorted(unevaluated_keys, key=str)
+            yield ValidationError(error % _utils.extras_msg(extras))
+        else:
+            error = (
+                "Unevaluated properties are not valid under "
+                "the given schema (%s %s unevaluated and invalid)"
+            )
+            yield ValidationError(error % _utils.extras_msg(unevaluated_keys))