Skip to content

Validationerror context #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Apr 10, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
54f16a7
Add schema_path attribute to ValidationErrors
gazpachoking Mar 18, 2013
741c275
Add validator_arg, instance, subschema, and context attributes to Val…
gazpachoking Mar 26, 2013
cf20b09
Fix issue with new error properties on nested errors
gazpachoking Mar 29, 2013
77ffe31
Rename some ValidationError attributes
gazpachoking Mar 29, 2013
300f389
Add anyOf test for the new ValidationError properties
gazpachoking Apr 1, 2013
7234ec3
Update the docs for ValidationError with the new attributes
gazpachoking Apr 1, 2013
951ee65
Manually transfer ValidationError attributes to SchemaError
gazpachoking Apr 3, 2013
d493bdb
Use keyword args to set ValidationError details for clarity
gazpachoking Apr 3, 2013
ff74103
Make a method to create SchemaErrors from ValidationErrors
gazpachoking Apr 3, 2013
45e20de
Implement IValidator.extends for subschema validation within validators
gazpachoking Apr 4, 2013
af86042
Update docs for descend method
gazpachoking Apr 4, 2013
1a74234
Add example of using the ValidationError attributes
gazpachoking Apr 4, 2013
832f51c
Don't rely on hash sorting for docs examples
gazpachoking Apr 6, 2013
d3c6f27
Make sure sorted_errors has unambiguous order for all error lists
gazpachoking Apr 6, 2013
ceede42
Make sure unlike types can't get compared in sorted_errors again
gazpachoking Apr 6, 2013
0e49379
Add missing paren in docs
gazpachoking Apr 7, 2013
4fe2a8b
Refactor ValidationError.to_schema_error to _Error.create_from
gazpachoking Apr 7, 2013
cf7056d
Pass all arguments to super in _Error
gazpachoking Apr 7, 2013
16ec13c
Use python 3 style prints in docs
gazpachoking Apr 8, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

doctest_global_setup = "from jsonschema import *"
doctest_global_setup = (
"from __future__ import print_function\n"
"from jsonschema import *"
)


# -- Options for HTML output ---------------------------------------------------
Expand Down
9 changes: 5 additions & 4 deletions docs/creating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Creating or Extending Validators
Creating Validation Errors
--------------------------

Any validating function that recurses into an instance (e.g. ``properties`` or
``items``) must call ``appendleft`` on the :exc:`ValidationError.path`
attribute of the error in order to properly maintain where in the instance the
error occurred.
Any validating function that validates against a subschema should call
:meth:`ValidatorMixin.descend`, rather than :meth:`ValidatorMixin.iter_errors`.
If it recurses into the instance, or schema, it must set the ``path`` or
``schema_path`` in order to properly maintain where in the instance and schema
the error occurred.
91 changes: 89 additions & 2 deletions docs/errors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,102 @@ raised or returned, depending on which method or function is used.

A human readable message explaining the error.

.. attribute:: validator
.. attribute:: validator_keyword
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite the fact that I also like validator_keyword better, I think to avoid the API churn we should leave it as is. It's going to be a pain -- we couldn't remove validator until at least v2.0 and it's just going to annoy for a tiny purity benefit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You da boss. 😄 That's fine by me.


The failed validator.

.. attribute:: validator_value

The value for the failed validator in the schema.

.. attribute:: schema

The full (sub)schema that this error came from.

.. attribute:: schema_path

A deque containing the path to the failed validator within the schema.

.. attribute:: path

A deque containing the path to the offending element (or an empty deque
if the error happened globally).

.. attribute:: instance

The instance that was being validated.

.. attribute:: context

If the error was caused by errors in subschemas, the list of errors
from the subschemas will be available on this property. The
``schema_path`` and ``path`` of these errors will be relative to the
parent error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be helpful if we also added one more (very short) prose section to this file showing an example using all these new attributes. Say something that used anyOf or one of those validators and pulled off this information from it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I added a bit on this, not sure if it's what you had in mind, documentation is not my strong suit. :P

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't actually need an attribute for the instance do we? The caller knows what they passed in, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep it, the instance you pass in may be a deeply nested structure, the instance on the error is the one that was passed into the validator that failed. You could trace it out using the path within the instance you passed in, I just put it there because it seems much more convenient to see what actual failed the specific validator without having to find it in the original instance.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK we should make that clear.
On Apr 9, 2013 11:22 PM, "Chase Sterling" [email protected] wrote:

In docs/errors.rst:

 .. attribute:: path

     A deque containing the path to the offending element (or an empty deque
     if the error happened globally).
  • .. attribute:: instance
  •    The instance that was being validated.
    
  • .. attribute:: context
  •    If the error was caused by errors in subschemas, the list of errors
    
  •    from the subschemas will be available on this property. The
    
  •    `schema_path` and `path` of these errors will be relative to the
    
  •    parent error.
    

I think we should keep it, the instance you pass in may be a deeply nested
structure, the instance on the error is the one that was passed into the
validator that failed. You could trace it out using the path within the
instance you passed in, I just put it there because it seems much more
convenient to see what actual failed the specific validator without having
to find it in the original instance.


Reply to this email directly or view it on GitHubhttps://github.com//pull/86/files#r3727202
.

These attributes can be clarified with a short example:

.. code-block:: python

>>> from jsonschema import Draft4Validator
>>> schema = {
... "items": {
... "anyOf": [
... {"type": "string", "maxLength": 2},
... {"type": "integer", "minimum": 5}
... ]
... }
... }
>>> instance = [{}, 3, "foo"]
>>> v = Draft4Validator(schema)
>>> errors = sorted(v.iter_errors(instance), key=lambda e: e.path)

The error messages in this situation are not very helpful on their own:

.. code-block:: python

>>> for e in errors:
... print(e.message)
The instance is not valid under any of the given schemas
The instance is not valid under any of the given schemas
The instance is not valid under any of the given schemas

If we look at the :attr:`ValidationError.path` attribute, we can find out which
elements in the instance we are validating are causing each of the errors. In
this example, :attr:`ValidationError.path` will have only one element, which
will be the index in our list.

.. code-block:: python

>>> for e in errors:
... print(list(e.path))
[0]
[1]
[2]

Since our schema contained nested subschemas, it can be helpful to look at
the specific part of the instance and subschema that caused each of the errors.
This can be seen with the :attr:`ValidationError.instance` and
:attr:`ValidationError.schema` attributes.

With validators like ``anyOf``, the :attr:`ValidationError.context`` attribute
can be used to see the sub-errors which caused the failure. Since these errors
actually came from two separate subschemas, so it can be helpful to look at the
:attr:`ValidationError.schema_path` attribute as well to see where exactly in
the schema each of these errors come from. In the case of sub-errors from the
:attr:`ValidationError.context` attribute, this path will be relative to the
:attr:`ValidationError.schema_path` of the parent error.

.. code-block:: python

>>> for e in errors:
... for sube in sorted(e.context, key=lambda e: e.schema_path):
... print(list(sube.schema_path), sube)
[0, 'type'] {} is not of type 'string'
[1, 'type'] {} is not of type 'integer'
[0, 'type'] 3 is not of type 'string'
[1, 'minimum'] 3.0 is less than the minimum of 5
[0, 'maxLength'] 'foo' is too long
[1, 'type'] 'foo' is not of type 'integer'

In case an invalid schema itself is encountered, a :exc:`SchemaError` is
raised.
Expand Down Expand Up @@ -62,7 +149,7 @@ For clarity's sake, the given instance has three errors under this schema:

>>> v = Draft3Validator(schema)
>>> for error in sorted(v.iter_errors(["spam", 2]), key=str):
... print error
... print(error)
'spam' is not of type 'number'
'spam' is not one of [1, 2, 3]
['spam', 2] is too short
Expand Down
Loading