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
4 changed files with 112 additions and 101 deletions

View File

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

View File

@@ -36,7 +36,7 @@ raised or returned, depending on which method or function is used.
.. attribute:: validator .. attribute:: validator
The failed `validator The name of the failed `validator
<http://json-schema.org/latest/json-schema-validation.html#anchor12>`_. <http://json-schema.org/latest/json-schema-validation.html#anchor12>`_.
.. attribute:: validator_value .. attribute:: validator_value
@@ -46,8 +46,9 @@ raised or returned, depending on which method or function is used.
.. attribute:: schema .. attribute:: schema
The full schema that this error came from. This is potentially a The full schema that this error came from. This is potentially a
subschema from within the schema that was passed into the validator, or subschema from within the schema that was passed in originally,
even an entirely different schema if a :validator:`$ref` was followed. or even an entirely different schema if a :validator:`$ref` was
followed.
.. attribute:: relative_schema_path .. 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 A :class:`collections.deque` containing the path to the failed
validator within the schema, but always relative to the validator within the schema, but always relative to the
*original* schema as opposed to any subschema (i.e. the one *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 .. attribute:: schema_path
@@ -86,12 +87,12 @@ raised or returned, depending on which method or function is used.
.. attribute:: instance .. attribute:: instance
The instance that was being validated. This will differ from the The instance that was being validated. This will differ from
instance originally passed into validate if the validator was in the the instance originally passed into :meth:`validate` if the
process of validating a (possibly nested) element within the top-level validator object was in the process of validating a (possibly
instance. The path within the top-level instance (i.e. nested) element within the top-level instance. The path within
:attr:`ValidationError.path`) could be used to find this object, but it the top-level instance (i.e. :attr:`ValidationError.path`) could
is provided for convenience. be used to find this object, but it is provided for convenience.
.. attribute:: context .. attribute:: context
@@ -266,8 +267,9 @@ more easily than by just iterating over the error objects.
tree = ErrorTree(v.iter_errors(instance)) tree = ErrorTree(v.iter_errors(instance))
As you can see, :class:`ErrorTree` takes an iterable of As you can see, :class:`ErrorTree` takes an iterable of
:class:`ValidationError`\s when constructing a tree so you can directly pass it :class:`ValidationError`\s when constructing a tree so you
the return value of a validator's :attr:`~IValidator.iter_errors` method. 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 :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 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) >>> print(tree[0].errors["type"].message)
'spam' is not of type 'number' 'spam' is not of type 'number'
Of course this means that if we want to know if a given validator failed for a Of course this means that if we want to know if a given named
given index, we check for its presence in :attr:`~ErrorTree.errors`: validator failed for a given index, we check for its presence in
:attr:`~ErrorTree.errors`:
.. doctest:: .. 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. That's all you need to know to use error trees.
To summarize, each tree contains child trees that can be accessed by indexing To summarize, each tree contains child trees that can be accessed by
the tree to get the corresponding child tree for a given index into the indexing the tree to get the corresponding child tree for a given index
instance. Each tree and child has a :attr:`~ErrorTree.errors` attribute, a into the instance. Each tree and child has a :attr:`~ErrorTree.errors`
dict, that maps the failed validator to the corresponding validation error. attribute, a dict, that maps the failed validator name to the
corresponding validation error.
best_match and relevance 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. 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 :argument set weak: a collection of validator names to consider to
there are two errors at the same level of the instance and one is in be "weak". If there are two errors at the same level of the
the set of weak validators, the other error will take priority. By instance and one is in the set of weak validator names, the
default, :validator:`anyOf` and :validator:`oneOf` are considered weak other error will take priority. By default, :validator:`anyOf`
validators and will be superceded by other same-level validation and :validator:`oneOf` are considered weak validators and will
errors. be superceded by other same-level validation errors.
:argument set strong: a collection of validators to consider to be "strong" :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 valid under the schema it lives in! So an instance modified by the default
would pass validation the first time, but fail the second! would pass validation the first time, but fail the second!
Still, filling in defaults is a thing that is useful. :mod:`jsonschema` allows Still, filling in defaults is a thing that is useful. :mod:`jsonschema`
you to :doc:`define your own validators <creating>`, so you can easily create a allows you to :doc:`define your own validator classes and callables
:class:`IValidator` that does do default setting. Here's some code to get you <creating>`, so you can easily create a :class:`IValidator` that does do
started: default setting. Here's some code to get you started:
.. code-block:: python .. 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 The Validator Interface
----------------------- -----------------------
:mod:`jsonschema` defines an (informal) interface that all validators should :mod:`jsonschema` defines an (informal) interface that all validator
adhere to. classes should adhere to.
.. class:: IValidator(schema, types=(), resolver=None, format_checker=None) .. class:: IValidator(schema, types=(), resolver=None, format_checker=None)
:argument dict schema: the schema that the validator will validate with. It :argument dict schema: the schema that the validator object
is assumed to be valid, and providing an invalid will validate with. It is assumed to be valid, and providing
schema can lead to undefined behavior. See an invalid schema can lead to undefined behavior. See
:meth:`IValidator.check_schema` to validate a schema :meth:`IValidator.check_schema` to validate a schema first.
first. :argument types: Override or extend the list of known types when
:argument types: Override or extend the list of known types when validating validating the :validator:`type` property. Should map strings (type
the :validator:`type` property. Should map strings (type names) to class objects that will be checked via :func:`isinstance`.
names) to class objects that will be checked via See :ref:`validating-types` for details.
:func:`isinstance`. See :ref:`validating-types` for
details.
:type types: dict or iterable of 2-tuples :type types: dict or iterable of 2-tuples
:argument resolver: an instance of :class:`RefResolver` that will be used :argument resolver: an instance of :class:`RefResolver` that will be
to resolve :validator:`$ref` properties (JSON used to resolve :validator:`$ref` properties (JSON references). If
references). If unprovided, one will be created. unprovided, one will be created.
:argument format_checker: an instance of :class:`FormatChecker` whose :argument format_checker: an instance of :class:`FormatChecker`
:meth:`~conforms` method will be called to check whose :meth:`~conforms` method will be called to check and see if
and see if instances conform to each instances conform to each :validator:`format` property present
:validator:`format` property present in the in the schema. If unprovided, no validation will be done for
schema. If unprovided, no validation will be done :validator:`format`.
for :validator:`format`.
.. attribute:: DEFAULT_TYPES .. attribute:: DEFAULT_TYPES
@@ -61,13 +58,13 @@ adhere to.
.. attribute:: VALIDATORS .. attribute:: VALIDATORS
A mapping of validators (:class:`str`\s) to functions that validate the A mapping of validator names (:class:`str`\s) to functions
validator property with that name. For more information see that validate the validator property with that name. For more
:ref:`creating-validators`. information see :ref:`creating-validators`.
.. attribute:: schema .. 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) .. classmethod:: check_schema(schema)
@@ -124,10 +121,11 @@ adhere to.
ValidationError: [2, 3, 4] is too long ValidationError: [2, 3, 4] is too long
All of the :ref:`versioned validators <versioned-validators>` that are included All of the :ref:`versioned validators <versioned-validators>` that
with :mod:`jsonschema` adhere to the interface, and implementors of validators are included with :mod:`jsonschema` adhere to the interface, and
that extend or complement the ones included should adhere to it as well. For implementors of validator classes that extend or complement the
more information see :ref:`creating-validators`. ones included should adhere to it as well. For more information see
:ref:`creating-validators`.
.. _validating-types: .. _validating-types:
@@ -154,7 +152,7 @@ more general instance checks can introduce significant slowdown, especially
given how common validating these types are. given how common validating these types are.
If you *do* want the generality, or just want to add a few specific additional 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. ``types`` argument that can be used to provide additional or new types.
.. code-block:: python .. 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 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 validator object in the :attr:`IValidator.DEFAULT_TYPES` attribute. Note
need to specify all types to match if you override one of the existing JSON that you need to specify all types to match if you override one of the
types, so you may want to access the set of default types when specifying your existing JSON types, so you may want to access the set of default types
additional type. when specifying your additional type.
.. _versioned-validators: .. _versioned-validators:
Versioned Validators Versioned Validators
-------------------- --------------------
:mod:`jsonschema` ships with validators for various versions of the JSON Schema :mod:`jsonschema` ships with validator classes for various versions of
specification. For details on the methods and attributes that each validator the JSON Schema specification. For details on the methods and attributes
provides see the :class:`IValidator` interface, which each validator that each validator class provides see the :class:`IValidator` interface,
implements. which each included validator class implements.
.. autoclass:: Draft3Validator .. autoclass:: Draft3Validator