"""
typing.Protocol classes
for jsonschema interfaces.
"""
# for reference material on Protocols, see
# https://www.python.org/dev/peps/pep-0544/
from __future__
import annotations
from collections.abc
import Callable, Mapping
from typing
import TYPE_CHECKING, Any, ClassVar, Iterable
import sys
# doing these imports with `try ... except ImportError` doesn't pass mypy
# checking because mypy sees `typing._SpecialForm` and
# `typing_extensions._SpecialForm` as incompatible
#
# see:
# https://mypy.readthedocs.io/en/stable/runtime_troubles.html#using-new-additions-to-the-typing-module
# https://github.com/python/mypy/issues/4427
if sys.version_info >= (3, 8):
from typing
import Protocol, runtime_checkable
else:
from typing_extensions
import Protocol, runtime_checkable
# in order for Sphinx to resolve references accurately from type annotations,
# it needs to see names like `jsonschema.TypeChecker`
# therefore, only import at type-checking time (to avoid circular references),
# but use `jsonschema` for any types which will otherwise not be resolvable
if TYPE_CHECKING:
import jsonschema
import jsonschema.validators
from jsonschema.exceptions
import ValidationError
# For code authors working on the validator protocol, these are the three
# use-cases which should be kept in mind:
#
# 1. As a protocol class, it can be used in type annotations to describe the
# available methods and attributes of a validator
# 2. It is the source of autodoc for the validator documentation
# 3. It is runtime_checkable, meaning that it can be used in isinstance()
# checks.
#
# Since protocols are not base classes, isinstance() checking is limited in
# its capabilities. See docs on runtime_checkable for detail
@runtime_checkable
class Validator(Protocol):
"""
The protocol to which all validator classes adhere.
Arguments:
schema:
The schema that the validator object will validate
with.
It
is assumed to be valid,
and providing
an invalid schema can lead to undefined behavior. See
`Validator.check_schema` to validate a schema first.
resolver:
a resolver that will be used to resolve :kw:`$ref`
properties (JSON references).
If unprovided, one will be created.
format_checker:
if provided, a checker which will be used to
assert about
:kw:`format` properties present
in the schema.
If unprovided,
*no* format validation
is done,
and the presence of format
within schemas
is strictly informational. Certain formats
require additional packages to be installed
in order to
assert
against instances. Ensure you
've installed `jsonschema` with
its `extra (optional) dependencies <index:extras>` when
invoking ``pip``.
.. deprecated:: v4.12.0
Subclassing validator classes now explicitly warns this
is not part of
their public API.
"""
#: An object representing the validator's meta schema (the schema that
#: describes valid schemas in the given version).
META_SCHEMA: ClassVar[Mapping]
#: A mapping of validation keywords (`str`\s) to functions that
#: validate the keyword with that name. For more information see
#: `creating-validators`.
VALIDATORS: ClassVar[Mapping]
#: A `jsonschema.TypeChecker` that will be used when validating
#: :kw:`type` keywords in JSON schemas.
TYPE_CHECKER: ClassVar[jsonschema.TypeChecker]
#: A `jsonschema.FormatChecker` that will be used when validating
#: :kw:`format` keywords in JSON schemas.
FORMAT_CHECKER: ClassVar[jsonschema.FormatChecker]
#: A function which given a schema returns its ID.
ID_OF: Callable[[Any], str |
None]
#: The schema that will be used to validate instances
schema: Mapping | bool
def __init__(
self,
schema: Mapping | bool,
resolver: jsonschema.validators.RefResolver |
None =
None,
format_checker: jsonschema.FormatChecker |
None =
None,
) ->
None:
...
@classmethod
def check_schema(cls, schema: Mapping | bool) ->
None:
"""
Validate the given schema against the validator
's `META_SCHEMA`.
Raises:
`jsonschema.exceptions.SchemaError`:
if the schema
is invalid
"""
def is_type(self, instance: Any, type: str) -> bool:
"""
Check
if the instance
is of the given (JSON Schema) type.
Arguments:
instance:
the value to check
type:
the name of a known (JSON Schema) type
Returns:
whether the instance
is of the given type
Raises:
`jsonschema.exceptions.UnknownType`:
if ``type``
is not a known type
"""
def is_valid(self, instance: Any) -> bool:
"""
Check
if the instance
is valid under the current `schema`.
Returns:
whether the instance
is valid
or not
>>> schema = {
"maxItems" : 2}
>>> Draft202012Validator(schema).is_valid([2, 3, 4])
False
"""
def iter_errors(self, instance: Any) -> Iterable[ValidationError]:
r
"""
Lazily
yield each of the validation errors
in the given instance.
>>> schema = {
...
"type" :
"array",
...
"items" : {
"enum" : [1, 2, 3]},
...
"maxItems" : 2,
... }
>>> v = Draft202012Validator(schema)
>>>
for error
in sorted(v.iter_errors([2, 3, 4]), key=str):
... print(error.message)
4
is not one of [1, 2, 3]
[2, 3, 4]
is too long
.. deprecated:: v4.0.0
Calling this function
with a second schema argument
is deprecated.
Use `Validator.evolve` instead.
"""
def validate(self, instance: Any) ->
None:
"""
Check
if the instance
is valid under the current `schema`.
Raises:
`jsonschema.exceptions.ValidationError`:
if the instance
is invalid
>>> schema = {
"maxItems" : 2}
>>> Draft202012Validator(schema).validate([2, 3, 4])
Traceback (most recent call last):
...
ValidationError: [2, 3, 4]
is too long
"""
def evolve(self, **kwargs) ->
"Validator":
"""
Create a new validator like this one, but
with given changes.
Preserves all other attributes, so can be used to e.g. create a
validator
with a different schema but
with the same :kw:`$ref`
resolution behavior.
>>> validator = Draft202012Validator({})
>>> validator.evolve(schema={
"type":
"number"})
Draft202012Validator(schema={
'type':
'number'}, format_checker=
None)
The returned object satisfies the validator protocol, but may
not
be of the same concrete
class!
In particular this occurs
when a :kw:`$ref` occurs to a schema
with a different
:kw:`$schema` than this one (i.e.
for a different draft).
>>> validator.evolve(
... schema={
"$schema": Draft7Validator.META_SCHEMA[
"$id"]}
... )
Draft7Validator(schema=..., format_checker=
None)
"""