Try to be as explicit as possible on the million different uses of 'validator'.

Closes #175.
This commit is contained in:
Julian Berman 2014-12-07 12:48:03 -05:00
parent fcb178774f
commit add447fbe5
No known key found for this signature in database
GPG Key ID: 3F8D9C8C011729F8
4 changed files with 112 additions and 101 deletions

View File

@ -1,30 +1,37 @@
.. _creating-validators:
================================
Creating or Extending Validators
================================
=======================================
Creating or Extending Validator Classes
=======================================
.. currentmodule:: jsonschema.validators
.. autofunction:: create
Create a new validator (class).
Create a new validator class.
:argument dict meta_schema: the meta schema for the new validator class
:argument dict validators: a mapping from validator names to functions that
validate the given name. Each function should take 4 arguments: a
validator instance, the value of the current validator property in the
instance being validated, the instance, and the schema.
:argument dict validators: a mapping from names to callables, where
each callable will validate the schema property with the given
name.
Each callable should take 4 arguments:
1. a validator instance,
2. the value of the property being validated within the instance
3. the instance
4. the schema
:argument str version: an identifier for the version that this validator
will validate. If provided, the returned validator class will have its
``__name__`` set to include the version, and also will have
:func:`validates` automatically called for the given version.
class will validate. If provided, the returned validator class
will have its ``__name__`` set to include the version, and also
will have :func:`validates` automatically called for the given
version.
:argument dict default_types: a default mapping to use for instances of the
validator when mapping between JSON types to Python types. The default
for this argument is probably fine. Instances of the returned validator
:argument dict default_types: a default mapping to use for instances
of the validator class when mapping between JSON types to Python
types. The default for this argument is probably fine. Instances
can still have their types customized on a per-instance basis.
:returns: a new :class:`jsonschema.IValidator` class
@ -32,48 +39,49 @@ Creating or Extending Validators
.. autofunction:: extend
Create a new validator that extends an existing validator class.
Create a new validator class by extending an existing one.
:argument jsonschema.IValidator validator: an existing validator class
:argument dict validators: a set of new validators to add to the new
validator.
:argument dict validators: a mapping of new validator callables to extend
with, whose structure is as in :func:`create`\ .
.. note::
Any validators with the same name as an existing one will
(silently) replace the old validator entirely.
Any validator callables with the same name as an existing one will
(silently) replace the old validator callable entirely, effectively
overriding any validation done in the "parent" validator class.
If you wish to extend an old validator, call it directly in the
replacing validator function by retrieving it using
``OldValidator.VALIDATORS["the validator"]``.
If you wish to instead extend the behavior of a parent's
validator callable, delegate and call it directly in
the new validator function by retrieving it using
``OldValidator.VALIDATORS["validator_name"]``.
:argument str version: a version for the new validator
:argument str version: a version for the new validator class
:returns: a new :class:`jsonschema.IValidator` class
.. note:: Meta Schemas
The new validator will just keep the old validator's meta schema.
The new validator class will have its parent's meta schema.
If you wish to change or extend the meta schema in the new validator,
modify ``META_SCHEMA`` directly on the returned class.
The meta schema on the new validator will not be a copy, so you'll
probably want to copy it before modifying it to not affect the old
validator.
If you wish to change or extend the meta schema in the new
validator class, modify ``META_SCHEMA`` directly on the returned
class. Note that no implicit copying is done, so a copy should
likely be made before modifying it, in order to not affect the
old validator.
.. autofunction:: validator_for
Retrieve the validator appropriate for validating the given schema.
Retrieve the validator class appropriate for validating the given schema.
Uses the :validator:`$schema` property that should be present in the given
schema to look up the appropriate validator.
schema to look up the appropriate validator class.
:argument schema: the schema to look at
:argument default: the default to return if the appropriate validator
cannot be determined. If unprovided, the default will be to just return
:argument default: the default to return if the appropriate validator class
cannot be determined. If unprovided, the default is to return
:class:`Draft4Validator`

View File

@ -36,7 +36,7 @@ raised or returned, depending on which method or function is used.
.. attribute:: validator
The failed `validator
The name of the failed `validator
<http://json-schema.org/latest/json-schema-validation.html#anchor12>`_.
.. attribute:: validator_value
@ -46,8 +46,9 @@ raised or returned, depending on which method or function is used.
.. attribute:: schema
The full schema that this error came from. This is potentially a
subschema from within the schema that was passed into the validator, or
even an entirely different schema if a :validator:`$ref` was followed.
subschema from within the schema that was passed in originally,
or even an entirely different schema if a :validator:`$ref` was
followed.
.. attribute:: relative_schema_path
@ -59,7 +60,7 @@ raised or returned, depending on which method or function is used.
A :class:`collections.deque` containing the path to the failed
validator within the schema, but always relative to the
*original* schema as opposed to any subschema (i.e. the one
originally passed into a validator, *not* :attr:`schema`\).
originally passed into a validator class, *not* :attr:`schema`\).
.. attribute:: schema_path
@ -86,12 +87,12 @@ raised or returned, depending on which method or function is used.
.. attribute:: instance
The instance that was being validated. This will differ from the
instance originally passed into validate if the validator was in the
process of validating a (possibly nested) element within the top-level
instance. The path within the top-level instance (i.e.
:attr:`ValidationError.path`) could be used to find this object, but it
is provided for convenience.
The instance that was being validated. This will differ from
the instance originally passed into :meth:`validate` if the
validator object was in the process of validating a (possibly
nested) element within the top-level instance. The path within
the top-level instance (i.e. :attr:`ValidationError.path`) could
be used to find this object, but it is provided for convenience.
.. attribute:: context
@ -266,8 +267,9 @@ more easily than by just iterating over the error objects.
tree = ErrorTree(v.iter_errors(instance))
As you can see, :class:`ErrorTree` takes an iterable of
:class:`ValidationError`\s when constructing a tree so you can directly pass it
the return value of a validator's :attr:`~IValidator.iter_errors` method.
:class:`ValidationError`\s when constructing a tree so you
can directly pass it the return value of a validator object's
:attr:`~IValidator.iter_errors` method.
:class:`ErrorTree`\s support a number of useful operations. The first one we
might want to perform is to check whether a given element in our instance
@ -303,8 +305,9 @@ them.
>>> print(tree[0].errors["type"].message)
'spam' is not of type 'number'
Of course this means that if we want to know if a given validator failed for a
given index, we check for its presence in :attr:`~ErrorTree.errors`:
Of course this means that if we want to know if a given named
validator failed for a given index, we check for its presence in
:attr:`~ErrorTree.errors`:
.. doctest::
@ -326,10 +329,11 @@ itself. So it appears in the root node of the tree.
That's all you need to know to use error trees.
To summarize, each tree contains child trees that can be accessed by indexing
the tree to get the corresponding child tree for a given index into the
instance. Each tree and child has a :attr:`~ErrorTree.errors` attribute, a
dict, that maps the failed validator to the corresponding validation error.
To summarize, each tree contains child trees that can be accessed by
indexing the tree to get the corresponding child tree for a given index
into the instance. Each tree and child has a :attr:`~ErrorTree.errors`
attribute, a dict, that maps the failed validator name to the
corresponding validation error.
best_match and relevance
@ -425,10 +429,11 @@ to guess the most relevant error in a given bunch.
Create a key function that can be used to sort errors by relevance.
:argument set weak: a collection of validators to consider to be "weak". If
there are two errors at the same level of the instance and one is in
the set of weak validators, the other error will take priority. By
default, :validator:`anyOf` and :validator:`oneOf` are considered weak
validators and will be superceded by other same-level validation
errors.
:argument set strong: a collection of validators to consider to be "strong"
:argument set weak: a collection of validator names to consider to
be "weak". If there are two errors at the same level of the
instance and one is in the set of weak validator names, the
other error will take priority. By default, :validator:`anyOf`
and :validator:`oneOf` are considered weak validators and will
be superceded by other same-level validation errors.
:argument set strong: a collection of validator names to consider to
be "strong"

View File

@ -16,10 +16,10 @@ It's perfectly valid (and perhaps even useful) to have a default that is not
valid under the schema it lives in! So an instance modified by the default
would pass validation the first time, but fail the second!
Still, filling in defaults is a thing that is useful. :mod:`jsonschema` allows
you to :doc:`define your own validators <creating>`, so you can easily create a
:class:`IValidator` that does do default setting. Here's some code to get you
started:
Still, filling in defaults is a thing that is useful. :mod:`jsonschema`
allows you to :doc:`define your own validator classes and callables
<creating>`, so you can easily create a :class:`IValidator` that does do
default setting. Here's some code to get you started:
.. code-block:: python

View File

@ -23,31 +23,28 @@ The simplest way to validate an instance under a given schema is to use the
The Validator Interface
-----------------------
:mod:`jsonschema` defines an (informal) interface that all validators should
adhere to.
:mod:`jsonschema` defines an (informal) interface that all validator
classes should adhere to.
.. class:: IValidator(schema, types=(), resolver=None, format_checker=None)
:argument dict schema: the schema that the validator will validate with. It
is assumed to be valid, and providing an invalid
schema can lead to undefined behavior. See
:meth:`IValidator.check_schema` to validate a schema
first.
:argument types: Override or extend the list of known types when validating
the :validator:`type` property. Should map strings (type
names) to class objects that will be checked via
:func:`isinstance`. See :ref:`validating-types` for
details.
:argument dict 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
:meth:`IValidator.check_schema` to validate a schema first.
:argument types: Override or extend the list of known types when
validating the :validator:`type` property. Should map strings (type
names) to class objects that will be checked via :func:`isinstance`.
See :ref:`validating-types` for details.
:type types: dict or iterable of 2-tuples
:argument resolver: an instance of :class:`RefResolver` that will be used
to resolve :validator:`$ref` properties (JSON
references). If unprovided, one will be created.
:argument format_checker: an instance of :class:`FormatChecker` whose
:meth:`~conforms` method will be called to check
and see if instances conform to each
:validator:`format` property present in the
schema. If unprovided, no validation will be done
for :validator:`format`.
:argument resolver: an instance of :class:`RefResolver` that will be
used to resolve :validator:`$ref` properties (JSON references). If
unprovided, one will be created.
:argument format_checker: an instance of :class:`FormatChecker`
whose :meth:`~conforms` method will be called to check and see if
instances conform to each :validator:`format` property present
in the schema. If unprovided, no validation will be done for
:validator:`format`.
.. attribute:: DEFAULT_TYPES
@ -61,13 +58,13 @@ adhere to.
.. attribute:: VALIDATORS
A mapping of validators (:class:`str`\s) to functions that validate the
validator property with that name. For more information see
:ref:`creating-validators`.
A mapping of validator names (:class:`str`\s) to functions
that validate the validator property with that name. For more
information see :ref:`creating-validators`.
.. attribute:: schema
The schema that was passed in when initializing the validator.
The schema that was passed in when initializing the object.
.. classmethod:: check_schema(schema)
@ -124,10 +121,11 @@ adhere to.
ValidationError: [2, 3, 4] is too long
All of the :ref:`versioned validators <versioned-validators>` that are included
with :mod:`jsonschema` adhere to the interface, and implementors of validators
that extend or complement the ones included should adhere to it as well. For
more information see :ref:`creating-validators`.
All of the :ref:`versioned validators <versioned-validators>` that
are included with :mod:`jsonschema` adhere to the interface, and
implementors of validator classes that extend or complement the
ones included should adhere to it as well. For more information see
:ref:`creating-validators`.
.. _validating-types:
@ -154,7 +152,7 @@ more general instance checks can introduce significant slowdown, especially
given how common validating these types are.
If you *do* want the generality, or just want to add a few specific additional
types as being acceptible for a validator, :class:`IValidator`\s have a
types as being acceptible for a validator object, :class:`IValidator`\s have a
``types`` argument that can be used to provide additional or new types.
.. code-block:: python
@ -168,20 +166,20 @@ types as being acceptible for a validator, :class:`IValidator`\s have a
)
The list of default Python types for each JSON type is available on each
validator in the :attr:`IValidator.DEFAULT_TYPES` attribute. Note that you
need to specify all types to match if you override one of the existing JSON
types, so you may want to access the set of default types when specifying your
additional type.
validator object in the :attr:`IValidator.DEFAULT_TYPES` attribute. Note
that you need to specify all types to match if you override one of the
existing JSON types, so you may want to access the set of default types
when specifying your additional type.
.. _versioned-validators:
Versioned Validators
--------------------
:mod:`jsonschema` ships with validators for various versions of the JSON Schema
specification. For details on the methods and attributes that each validator
provides see the :class:`IValidator` interface, which each validator
implements.
:mod:`jsonschema` ships with validator classes for various versions of
the JSON Schema specification. For details on the methods and attributes
that each validator class provides see the :class:`IValidator` interface,
which each included validator class implements.
.. autoclass:: Draft3Validator