Hello community,
here is the log from the commit of package python3-jsonschema for
openSUSE:Factory checked in at 2014-05-02 14:02:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-jsonschema (Old)
and /work/SRC/openSUSE:Factory/.python3-jsonschema.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-jsonschema"
Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-jsonschema/python3-jsonschema.changes
2013-06-25 18:00:14.000000000 +0200
+++
/work/SRC/openSUSE:Factory/.python3-jsonschema.new/python3-jsonschema.changes
2014-05-02 14:02:37.000000000 +0200
@@ -1,0 +2,13 @@
+Mon Apr 28 10:11:29 UTC 2014 - [email protected]
+
+- Update to version 2.3.0:
+ * Added by_relevance and best_match (#91)
+ * Fixed ``format`` to allow adding formats for non-strings (#125)
+ * Fixed the ``uri`` format to reject URI references (#131)
+ * Compile the host name regex (#127)
+ * Allow arbitrary objects to be types (#129)
+ * Support RFC 3339 datetimes in conformance with the spec
+ * Fixed error paths for additionalItems + items (#122)
+ * Fixed wording for min / maxProperties (#117)
+
+-------------------------------------------------------------------
Old:
----
jsonschema-2.0.0.tar.gz
New:
----
jsonschema-2.3.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python3-jsonschema.spec ++++++
--- /var/tmp/diff_new_pack.5CkoQw/_old 2014-05-02 14:02:38.000000000 +0200
+++ /var/tmp/diff_new_pack.5CkoQw/_new 2014-05-02 14:02:38.000000000 +0200
@@ -17,7 +17,7 @@
Name: python3-jsonschema
-Version: 2.0.0
+Version: 2.3.0
Release: 0
Summary: An implementation of JSON-Schema validation for Python
License: MIT
++++++ jsonschema-2.0.0.tar.gz -> jsonschema-2.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/CHANGELOG.rst
new/jsonschema-2.3.0/CHANGELOG.rst
--- old/jsonschema-2.0.0/CHANGELOG.rst 2013-05-21 15:36:50.000000000 +0200
+++ new/jsonschema-2.3.0/CHANGELOG.rst 2013-11-03 01:52:27.000000000 +0100
@@ -1,3 +1,24 @@
+v2.3.0
+------
+
+* Added by_relevance and best_match (#91)
+* Fixed ``format`` to allow adding formats for non-strings (#125)
+* Fixed the ``uri`` format to reject URI references (#131)
+
+v2.2.0
+------
+
+* Compile the host name regex (#127)
+* Allow arbitrary objects to be types (#129)
+
+v2.1.0
+------
+
+* Support RFC 3339 datetimes in conformance with the spec
+* Fixed error paths for additionalItems + items (#122)
+* Fixed wording for min / maxProperties (#117)
+
+
v2.0.0
------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/PKG-INFO
new/jsonschema-2.3.0/PKG-INFO
--- old/jsonschema-2.0.0/PKG-INFO 2013-05-21 15:41:34.000000000 +0200
+++ new/jsonschema-2.3.0/PKG-INFO 2013-11-03 02:06:30.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: jsonschema
-Version: 2.0.0
+Version: 2.3.0
Summary: An implementation of JSON Schema validation for Python
Home-page: http://github.com/Julian/jsonschema
Author: Julian Berman
@@ -57,21 +57,33 @@
Release Notes
-------------
- ``v2.0.0`` adds a better interface for creating and extending
validators in the
- form of ``jsonschema.validators.create`` and
``jsonschema.validators.extend``.
- The documentation is still a bit lacking in this area but it's getting
there.
- See the tests in ``jsonschema.tests.test_validators`` and the source
code if
- you'd like to try it out now. ``ValidatorMixin`` has been removed.
-
- Practically speaking, this affects validators that subclassed a
built-in
- validator and extended a validator function (presumably with an upcall
via
- ``super``), as the correct way to do so is now to call
- ``TheValidator.VALIDATORS["extended_validator_fn"]`` directly in a new
- validator function (and of course to use ``create``). Examples
hopefully coming
- soon if more clarification is needed. Patches welcome of course.
+ ``v2.3.0`` removes the (improper) limitation of ``format`` to strings.
It also
+ adds the `jsonschema.exceptions.best_match
<https://python-jsonschema.readthedocs.org/en/latest/errors/#best-match-and-by-relevance>`_
+ function which can be used to guess at the best matching single
validation
+ error for a given instance.
- It also fixes a number of issues with ref resolution, one for array
indices
- (#95) and one for improper handling of unknown URI schemes (#102).
+
+ .. code-block:: python
+
+ >>> from jsonschema.validators import Draft4Validator
+ >>> from jsonschema.exceptions import best_match
+
+ >>> schema = {
+ ... "properties" : {
+ ... "foo" : {"type" : "string"},
+ ... "bar" : {"properties" : {"baz": {"type": "string"}}},
+ ... },
+ ... }
+ >>> instance = {"foo" : 12, "bar": {"baz" : 19}}
+ >>>
print(best_match(Draft4Validator(schema).iter_errors(instance)).path)
+ deque(['foo'])
+
+
+ where the error closer to the top of the instance in ``foo`` was
selected
+ as being more relevant.
+
+ Also, URI references are now properly rejected by the URI format
validator
+ (i.e., it now only accepts full URIs, as defined in the specification).
Running the Test Suite
@@ -95,7 +107,8 @@
Community
---------
- There's a `mailing list
<https://groups.google.com/forum/#!forum/jsonschema>`_ for this implementation
on Google Groups.
+ There's a `mailing list
<https://groups.google.com/forum/#!forum/jsonschema>`_
+ for this implementation on Google Groups.
Please join, and feel free to send questions there.
@@ -113,6 +126,10 @@
You can also generally find me on Freenode (nick: ``tos9``) in various
channels, including ``#python``.
+ If you feel overwhelmingly grateful, you can woo me with beer money on
+ `Gittip <https://www.gittip.com/Julian/>`_ or via Google Wallet with
the email
+ in my GitHub profile.
+
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/README.rst
new/jsonschema-2.3.0/README.rst
--- old/jsonschema-2.0.0/README.rst 2013-05-21 15:36:23.000000000 +0200
+++ new/jsonschema-2.3.0/README.rst 2013-11-03 01:53:04.000000000 +0100
@@ -49,21 +49,33 @@
Release Notes
-------------
-``v2.0.0`` adds a better interface for creating and extending validators in the
-form of ``jsonschema.validators.create`` and ``jsonschema.validators.extend``.
-The documentation is still a bit lacking in this area but it's getting there.
-See the tests in ``jsonschema.tests.test_validators`` and the source code if
-you'd like to try it out now. ``ValidatorMixin`` has been removed.
-
-Practically speaking, this affects validators that subclassed a built-in
-validator and extended a validator function (presumably with an upcall via
-``super``), as the correct way to do so is now to call
-``TheValidator.VALIDATORS["extended_validator_fn"]`` directly in a new
-validator function (and of course to use ``create``). Examples hopefully coming
-soon if more clarification is needed. Patches welcome of course.
+``v2.3.0`` removes the (improper) limitation of ``format`` to strings. It also
+adds the `jsonschema.exceptions.best_match
<https://python-jsonschema.readthedocs.org/en/latest/errors/#best-match-and-by-relevance>`_
+function which can be used to guess at the best matching single validation
+error for a given instance.
-It also fixes a number of issues with ref resolution, one for array indices
-(#95) and one for improper handling of unknown URI schemes (#102).
+
+.. code-block:: python
+
+ >>> from jsonschema.validators import Draft4Validator
+ >>> from jsonschema.exceptions import best_match
+
+ >>> schema = {
+ ... "properties" : {
+ ... "foo" : {"type" : "string"},
+ ... "bar" : {"properties" : {"baz": {"type": "string"}}},
+ ... },
+ ... }
+ >>> instance = {"foo" : 12, "bar": {"baz" : 19}}
+ >>> print(best_match(Draft4Validator(schema).iter_errors(instance)).path)
+ deque(['foo'])
+
+
+where the error closer to the top of the instance in ``foo`` was selected
+as being more relevant.
+
+Also, URI references are now properly rejected by the URI format validator
+(i.e., it now only accepts full URIs, as defined in the specification).
Running the Test Suite
@@ -87,7 +99,8 @@
Community
---------
-There's a `mailing list <https://groups.google.com/forum/#!forum/jsonschema>`_
for this implementation on Google Groups.
+There's a `mailing list <https://groups.google.com/forum/#!forum/jsonschema>`_
+for this implementation on Google Groups.
Please join, and feel free to send questions there.
@@ -104,3 +117,7 @@
You can also generally find me on Freenode (nick: ``tos9``) in various
channels, including ``#python``.
+
+If you feel overwhelmingly grateful, you can woo me with beer money on
+`Gittip <https://www.gittip.com/Julian/>`_ or via Google Wallet with the email
+in my GitHub profile.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/json/README.md
new/jsonschema-2.3.0/json/README.md
--- old/jsonschema-2.0.0/json/README.md 2013-05-21 00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/json/README.md 2013-10-28 02:05:58.000000000 +0100
@@ -52,9 +52,8 @@
Coverage
--------
-Currently, draft 3 should have essentially full coverage for the core schema.
-
-The beginnings of draft 4 are underway.
+Draft 3 and 4 should have full coverage. If you see anything missing or think
+there is a useful test missing, please send a pull request or open an issue.
Who Uses the Test Suite
-----------------------
@@ -67,7 +66,11 @@
* [direct-schema (javascript)](https://github.com/IreneKnapp/direct-schema)
* [jsonschema (javascript)](https://github.com/tdegrunt/jsonschema)
* [JaySchema (javascript)](https://github.com/natesilva/jayschema)
+ * [z-schema (javascript)](https://github.com/zaggino/z-schema)
* [jesse (Erlang)](https://github.com/klarna/jesse)
+ * [json-schema (PHP)](https://github.com/justinrainbow/json-schema)
+ * [gojsonschema (Go)](https://github.com/sigu-399/gojsonschema)
+ * [json_schema (Dart)](https://github.com/patefacio/json_schema)
If you use it as well, please fork and send a pull request adding yourself to
the list :).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/json/bin/jsonschema_suite
new/jsonschema-2.3.0/json/bin/jsonschema_suite
--- old/jsonschema-2.0.0/json/bin/jsonschema_suite 2013-05-21
00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/json/bin/jsonschema_suite 2013-10-28
02:05:58.000000000 +0100
@@ -32,6 +32,10 @@
import jsonschema
except ImportError:
jsonschema = None
+else:
+ validators = getattr(
+ jsonschema.validators, "validators", jsonschema.validators
+ )
ROOT_DIR = os.path.join(
@@ -138,8 +142,8 @@
@unittest.skipIf(jsonschema is None, "Validation library not present!")
def test_all_schemas_are_valid(self):
for schema in os.listdir(SUITE_ROOT_DIR):
- schema_validator = jsonschema.validators.get(schema)
- if schema_validator:
+ schema_validator = validators.get(schema)
+ if schema_validator is not None:
test_files = collect(os.path.join(SUITE_ROOT_DIR, schema))
for case in cases(test_files):
try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jsonschema-2.0.0/json/tests/draft3/additionalProperties.json
new/jsonschema-2.3.0/json/tests/draft3/additionalProperties.json
--- old/jsonschema-2.0.0/json/tests/draft3/additionalProperties.json
2013-05-21 00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/json/tests/draft3/additionalProperties.json
2013-10-28 02:05:58.000000000 +0100
@@ -4,6 +4,7 @@
"additionalProperties being false does not allow other properties",
"schema": {
"properties": {"foo": {}, "bar": {}},
+ "patternProperties": { "^v": {} },
"additionalProperties": false
},
"tests": [
@@ -21,6 +22,11 @@
"description": "ignores non-objects",
"data": [1, 2, 3],
"valid": true
+ },
+ {
+ "description": "patternProperties are not additional
properties",
+ "data": {"foo":1, "vroom": 2},
+ "valid": true
}
]
},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jsonschema-2.0.0/json/tests/draft3/optional/format.json
new/jsonschema-2.3.0/json/tests/draft3/optional/format.json
--- old/jsonschema-2.0.0/json/tests/draft3/optional/format.json 2013-05-21
00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/json/tests/draft3/optional/format.json 2013-10-28
02:05:58.000000000 +0100
@@ -28,6 +28,11 @@
"description": "an invalid date-time string",
"data": "06/19/1963 08:30:06 PST",
"valid": false
+ },
+ {
+ "description": "only RFC3339 not all of ISO 8601 are valid",
+ "data": "2013-350T01:01:01",
+ "valid": false
}
]
},
@@ -76,6 +81,11 @@
"description": "an invalid URI",
"data": "\\\\WINDOWS\\fileshare",
"valid": false
+ },
+ {
+ "description": "an invalid URI though valid URI reference",
+ "data": "abc",
+ "valid": false
}
]
},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jsonschema-2.0.0/json/tests/draft4/additionalProperties.json
new/jsonschema-2.3.0/json/tests/draft4/additionalProperties.json
--- old/jsonschema-2.0.0/json/tests/draft4/additionalProperties.json
2013-05-21 00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/json/tests/draft4/additionalProperties.json
2013-10-28 02:05:58.000000000 +0100
@@ -4,6 +4,7 @@
"additionalProperties being false does not allow other properties",
"schema": {
"properties": {"foo": {}, "bar": {}},
+ "patternProperties": { "^v": {} },
"additionalProperties": false
},
"tests": [
@@ -21,6 +22,11 @@
"description": "ignores non-objects",
"data": [1, 2, 3],
"valid": true
+ },
+ {
+ "description": "patternProperties are not additional
properties",
+ "data": {"foo":1, "vroom": 2},
+ "valid": true
}
]
},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jsonschema-2.0.0/json/tests/draft4/optional/format.json
new/jsonschema-2.3.0/json/tests/draft4/optional/format.json
--- old/jsonschema-2.0.0/json/tests/draft4/optional/format.json 2013-05-21
00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/json/tests/draft4/optional/format.json 2013-10-28
02:05:58.000000000 +0100
@@ -12,6 +12,11 @@
"description": "an invalid date-time string",
"data": "06/19/1963 08:30:06 PST",
"valid": false
+ },
+ {
+ "description": "only RFC3339 not all of ISO 8601 are valid",
+ "data": "2013-350T01:01:01",
+ "valid": false
}
]
},
@@ -28,6 +33,11 @@
"description": "an invalid URI",
"data": "\\\\WINDOWS\\fileshare",
"valid": false
+ },
+ {
+ "description": "an invalid URI though valid URI reference",
+ "data": "abc",
+ "valid": false
}
]
},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/jsonschema/__init__.py
new/jsonschema-2.3.0/jsonschema/__init__.py
--- old/jsonschema-2.0.0/jsonschema/__init__.py 2013-05-21 15:32:14.000000000
+0200
+++ new/jsonschema-2.3.0/jsonschema/__init__.py 2013-11-03 01:08:57.000000000
+0100
@@ -10,17 +10,17 @@
"""
from jsonschema.exceptions import (
- FormatError, RefResolutionError, SchemaError, ValidationError
+ ErrorTree, FormatError, RefResolutionError, SchemaError, ValidationError
)
from jsonschema._format import (
FormatChecker, draft3_format_checker, draft4_format_checker,
)
from jsonschema.validators import (
- ErrorTree, Draft3Validator, Draft4Validator, RefResolver, validate
+ Draft3Validator, Draft4Validator, RefResolver, validate
)
-__version__ = "2.0.0"
+__version__ = "2.3.0"
# flake8: noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/jsonschema/_format.py
new/jsonschema-2.3.0/jsonschema/_format.py
--- old/jsonschema-2.0.0/jsonschema/_format.py 2013-05-21 00:47:55.000000000
+0200
+++ new/jsonschema-2.3.0/jsonschema/_format.py 2013-10-30 15:34:34.000000000
+0100
@@ -2,6 +2,7 @@
import re
import socket
+from jsonschema.compat import str_types
from jsonschema.exceptions import FormatError
@@ -64,17 +65,19 @@
"""
- if format in self.checkers:
- func, raises = self.checkers[format]
- result, cause = None, None
- try:
- result = func(instance)
- except raises as e:
- cause = e
- if not result:
- raise FormatError(
- "%r is not a %r" % (instance, format), cause=cause,
- )
+ if format not in self.checkers:
+ return
+
+ func, raises = self.checkers[format]
+ result, cause = None, None
+ try:
+ result = func(instance)
+ except raises as e:
+ cause = e
+ if not result:
+ raise FormatError(
+ "%r is not a %r" % (instance, format), cause=cause,
+ )
def conforms(self, instance, format):
"""
@@ -115,24 +118,33 @@
@_checks_drafts("email")
def is_email(instance):
+ if not isinstance(instance, str_types):
+ return True
return "@" in instance
-_checks_drafts(draft3="ip-address", draft4="ipv4", raises=socket.error)(
- socket.inet_aton
-)
+@_checks_drafts(draft3="ip-address", draft4="ipv4", raises=socket.error)
+def is_ipv4(instance):
+ if not isinstance(instance, str_types):
+ return True
+ return socket.inet_aton(instance)
if hasattr(socket, "inet_pton"):
@_checks_drafts("ipv6", raises=socket.error)
def is_ipv6(instance):
+ if not isinstance(instance, str_types):
+ return True
return socket.inet_pton(socket.AF_INET6, instance)
+_host_name_re = re.compile(r"^[A-Za-z0-9][A-Za-z0-9\.\-]{1,255}$")
+
@_checks_drafts(draft3="host-name", draft4="hostname")
def is_host_name(instance):
- pattern = "^[A-Za-z0-9][A-Za-z0-9\.\-]{1,255}$"
- if not re.match(pattern, instance):
+ if not isinstance(instance, str_types):
+ return True
+ if not _host_name_re.match(instance):
return False
components = instance.split(".")
for component in components:
@@ -148,28 +160,50 @@
else:
@_checks_drafts("uri", raises=ValueError)
def is_uri(instance):
- return rfc3987.parse(instance, rule="URI_reference")
+ if not isinstance(instance, str_types):
+ return True
+ return rfc3987.parse(instance, rule="URI")
try:
- import isodate
+ import strict_rfc3339
except ImportError:
- pass
+ try:
+ import isodate
+ except ImportError:
+ pass
+ else:
+ @_checks_drafts("date-time", raises=(ValueError, isodate.ISO8601Error))
+ def is_date(instance):
+ if not isinstance(instance, str_types):
+ return True
+ return isodate.parse_datetime(instance)
else:
- _err = (ValueError, isodate.ISO8601Error)
- _checks_drafts("date-time", raises=_err)(isodate.parse_datetime)
+ @_checks_drafts("date-time")
+ def is_date(instance):
+ if not isinstance(instance, str_types):
+ return True
+ return strict_rfc3339.validate_rfc3339(instance)
-_checks_drafts("regex", raises=re.error)(re.compile)
+@_checks_drafts("regex", raises=re.error)
+def is_regex(instance):
+ if not isinstance(instance, str_types):
+ return True
+ return re.compile(instance)
@_checks_drafts(draft3="date", raises=ValueError)
def is_date(instance):
+ if not isinstance(instance, str_types):
+ return True
return datetime.datetime.strptime(instance, "%Y-%m-%d")
@_checks_drafts(draft3="time", raises=ValueError)
def is_time(instance):
+ if not isinstance(instance, str_types):
+ return True
return datetime.datetime.strptime(instance, "%H:%M:%S")
@@ -184,7 +218,10 @@
@_checks_drafts(draft3="color", raises=(ValueError, TypeError))
def is_css21_color(instance):
- if instance.lower() in webcolors.css21_names_to_hex:
+ if (
+ not isinstance(instance, str_types) or
+ instance.lower() in webcolors.css21_names_to_hex
+ ):
return True
return is_css_color_code(instance)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/jsonschema/_validators.py
new/jsonschema-2.3.0/jsonschema/_validators.py
--- old/jsonschema-2.0.0/jsonschema/_validators.py 2013-05-21
00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/jsonschema/_validators.py 2013-10-28
13:04:39.000000000 +0100
@@ -59,8 +59,9 @@
):
return
+ len_items = len(schema.get("items", []))
if validator.is_type(aI, "object"):
- for index, item in enumerate(instance[len(schema.get("items", [])):]):
+ for index, item in enumerate(instance[len_items:], start=len_items):
for error in validator.descend(item, aI, path=index):
yield error
elif not aI and len(instance) > len(schema.get("items", [])):
@@ -149,10 +150,7 @@
def format(validator, format, instance, schema):
- if (
- validator.format_checker is not None and
- validator.is_type(instance, "string")
- ):
+ if validator.format_checker is not None:
try:
validator.format_checker.check(instance, format)
except FormatError as error:
@@ -214,7 +212,7 @@
if not errors:
return
all_errors.extend(errors)
- elif validator.is_type(type, "string"):
+ else:
if validator.is_type(instance, type):
return
else:
@@ -299,14 +297,16 @@
def minProperties_draft4(validator, mP, instance, schema):
if validator.is_type(instance, "object") and len(instance) < mP:
- yield ValidationError("%r is too short" % (instance,))
+ yield ValidationError(
+ "%r does not have enough properties" % (instance,)
+ )
def maxProperties_draft4(validator, mP, instance, schema):
if not validator.is_type(instance, "object"):
return
if validator.is_type(instance, "object") and len(instance) > mP:
- yield ValidationError("%r is too short" % (instance,))
+ yield ValidationError("%r has too many properties" % (instance,))
def allOf_draft4(validator, allOf, instance, schema):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/jsonschema/exceptions.py
new/jsonschema-2.3.0/jsonschema/exceptions.py
--- old/jsonschema-2.0.0/jsonschema/exceptions.py 2013-05-21
00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/jsonschema/exceptions.py 2013-10-30
13:09:11.000000000 +0100
@@ -1,4 +1,5 @@
import collections
+import itertools
import pprint
import textwrap
@@ -6,6 +7,9 @@
from jsonschema.compat import PY3, iteritems
+WEAK_MATCHES = frozenset(["anyOf", "oneOf"])
+STRONG_MATCHES = frozenset()
+
_unset = _utils.Unset()
@@ -24,25 +28,6 @@
self.instance = instance
self.schema = schema
- @classmethod
- def create_from(cls, other):
- return cls(
- message=other.message,
- cause=other.cause,
- context=other.context,
- path=other.path,
- schema_path=other.schema_path,
- validator=other.validator,
- validator_value=other.validator_value,
- instance=other.instance,
- schema=other.schema,
- )
-
- def _set(self, **kwargs):
- for k, v in iteritems(kwargs):
- if getattr(self, k) is _unset:
- setattr(self, k, v)
-
def __repr__(self):
return "<%s: %r>" % (self.__class__.__name__, self.message)
@@ -79,6 +64,23 @@
if PY3:
__str__ = __unicode__
+ @classmethod
+ def create_from(cls, other):
+ return cls(**other._contents())
+
+ def _set(self, **kwargs):
+ for k, v in iteritems(kwargs):
+ if getattr(self, k) is _unset:
+ setattr(self, k, v)
+
+ def _contents(self):
+ return dict(
+ (attr, getattr(self, attr)) for attr in (
+ "message", "cause", "context", "path", "schema_path",
+ "validator", "validator_value", "instance", "schema"
+ )
+ )
+
class ValidationError(_Error):
pass
@@ -93,7 +95,29 @@
class UnknownType(Exception):
- pass
+ def __init__(self, type, instance, schema):
+ self.type = type
+ self.instance = instance
+ self.schema = schema
+
+ def __str__(self):
+ return unicode(self).encode("utf-8")
+
+ def __unicode__(self):
+ pschema = pprint.pformat(self.schema, width=72)
+ pinstance = pprint.pformat(self.instance, width=72)
+ return textwrap.dedent("""
+ Unknown type %r for validator with schema:
+ %s
+
+ While checking instance:
+ %s
+ """.rstrip()
+ ) % (self.type, _utils.indent(pschema), _utils.indent(pinstance))
+
+ if PY3:
+ __str__ = __unicode__
+
class FormatError(Exception):
@@ -110,3 +134,98 @@
if PY3:
__str__ = __unicode__
+
+
+class ErrorTree(object):
+ """
+ ErrorTrees make it easier to check which validations failed.
+
+ """
+
+ _instance = _unset
+
+ def __init__(self, errors=()):
+ self.errors = {}
+ self._contents = collections.defaultdict(self.__class__)
+
+ for error in errors:
+ container = self
+ for element in error.path:
+ container = container[element]
+ container.errors[error.validator] = error
+
+ self._instance = error.instance
+
+ def __contains__(self, index):
+ """
+ Check whether ``instance[index]`` has any errors.
+
+ """
+
+ return index in self._contents
+
+ def __getitem__(self, index):
+ """
+ Retrieve the child tree one level down at the given ``index``.
+
+ If the index is not in the instance that this tree corresponds to and
+ is not known by this tree, whatever error would be raised by
+ ``instance.__getitem__`` will be propagated (usually this is some
+ subclass of :class:`LookupError`.
+
+ """
+
+ if self._instance is not _unset and index not in self:
+ self._instance[index]
+ return self._contents[index]
+
+ def __setitem__(self, index, value):
+ self._contents[index] = value
+
+ def __iter__(self):
+ """
+ Iterate (non-recursively) over the indices in the instance with errors.
+
+ """
+
+ return iter(self._contents)
+
+ def __len__(self):
+ """
+ Same as :attr:`total_errors`.
+
+ """
+
+ return self.total_errors
+
+ def __repr__(self):
+ return "<%s (%s total errors)>" % (self.__class__.__name__, len(self))
+
+ @property
+ def total_errors(self):
+ """
+ The total number of errors in the entire tree, including children.
+
+ """
+
+ child_errors = sum(len(tree) for _, tree in iteritems(self._contents))
+ return len(self.errors) + child_errors
+
+
+def by_relevance(weak=WEAK_MATCHES, strong=STRONG_MATCHES):
+ def relevance(error):
+ validator = error.validator
+ return -len(error.path), validator not in weak, validator in strong
+ return relevance
+
+
+def best_match(errors, key=by_relevance()):
+ errors = iter(errors)
+ best = next(errors, None)
+ if best is None:
+ return
+ best = max(itertools.chain([best], errors), key=key)
+
+ while best.context:
+ best = min(best.context, key=key)
+ return best
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/jsonschema/tests/test_exceptions.py
new/jsonschema-2.3.0/jsonschema/tests/test_exceptions.py
--- old/jsonschema-2.0.0/jsonschema/tests/test_exceptions.py 1970-01-01
01:00:00.000000000 +0100
+++ new/jsonschema-2.3.0/jsonschema/tests/test_exceptions.py 2013-10-30
15:32:59.000000000 +0100
@@ -0,0 +1,270 @@
+from jsonschema import Draft4Validator, exceptions
+from jsonschema.tests.compat import mock, unittest
+
+
+class TestBestMatch(unittest.TestCase):
+ def best_match(self, errors):
+ errors = list(errors)
+ best = exceptions.best_match(errors)
+ reversed_best = exceptions.best_match(reversed(errors))
+ self.assertEqual(
+ best,
+ reversed_best,
+ msg="Didn't return a consistent best match!\n"
+ "Got: {0}\n\nThen: {1}".format(best, reversed_best),
+ )
+ return best
+
+ def test_shallower_errors_are_better_matches(self):
+ validator = Draft4Validator(
+ {
+ "properties" : {
+ "foo" : {
+ "minProperties" : 2,
+ "properties" : {"bar" : {"type" : "object"}},
+ }
+ }
+ }
+ )
+ best = self.best_match(validator.iter_errors({"foo" : {"bar" : []}}))
+ self.assertEqual(best.validator, "minProperties")
+
+ def test_oneOf_and_anyOf_are_weak_matches(self):
+ """
+ A property you *must* match is probably better than one you have to
+ match a part of.
+
+ """
+
+ validator = Draft4Validator(
+ {
+ "minProperties" : 2,
+ "anyOf" : [{"type" : "string"}, {"type" : "number"}],
+ "oneOf" : [{"type" : "string"}, {"type" : "number"}],
+ }
+ )
+ best = self.best_match(validator.iter_errors({}))
+ self.assertEqual(best.validator, "minProperties")
+
+ def test_if_the_most_relevant_error_is_anyOf_it_is_traversed(self):
+ """
+ If the most relevant error is an anyOf, then we traverse its context
+ and select the otherwise *least* relevant error, since in this case
+ that means the most specific, deep, error inside the instance.
+
+ I.e. since only one of the schemas must match, we look for the most
+ relevant one.
+
+ """
+
+ validator = Draft4Validator(
+ {
+ "properties" : {
+ "foo" : {
+ "anyOf" : [
+ {"type" : "string"},
+ {"properties" : {"bar" : {"type" : "array"}}},
+ ],
+ },
+ },
+ },
+ )
+ best = self.best_match(validator.iter_errors({"foo" : {"bar" : 12}}))
+ self.assertEqual(best.validator_value, "array")
+
+ def test_if_the_most_relevant_error_is_oneOf_it_is_traversed(self):
+ """
+ If the most relevant error is an oneOf, then we traverse its context
+ and select the otherwise *least* relevant error, since in this case
+ that means the most specific, deep, error inside the instance.
+
+ I.e. since only one of the schemas must match, we look for the most
+ relevant one.
+
+ """
+
+ validator = Draft4Validator(
+ {
+ "properties" : {
+ "foo" : {
+ "oneOf" : [
+ {"type" : "string"},
+ {"properties" : {"bar" : {"type" : "array"}}},
+ ],
+ },
+ },
+ },
+ )
+ best = self.best_match(validator.iter_errors({"foo" : {"bar" : 12}}))
+ self.assertEqual(best.validator_value, "array")
+
+ def test_if_the_most_relevant_error_is_allOf_it_is_traversed(self):
+ """
+ Now, if the error is allOf, we traverse but select the *most* relevant
+ error from the context, because all schemas here must match anyways.
+
+ """
+
+ validator = Draft4Validator(
+ {
+ "properties" : {
+ "foo" : {
+ "allOf" : [
+ {"type" : "string"},
+ {"properties" : {"bar" : {"type" : "array"}}},
+ ],
+ },
+ },
+ },
+ )
+ best = self.best_match(validator.iter_errors({"foo" : {"bar" : 12}}))
+ self.assertEqual(best.validator_value, "string")
+
+ def test_nested_context_for_oneOf(self):
+ validator = Draft4Validator(
+ {
+ "properties" : {
+ "foo" : {
+ "oneOf" : [
+ {"type" : "string"},
+ {
+ "oneOf" : [
+ {"type" : "string"},
+ {
+ "properties" : {
+ "bar" : {"type" : "array"}
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ },
+ )
+ best = self.best_match(validator.iter_errors({"foo" : {"bar" : 12}}))
+ self.assertEqual(best.validator_value, "array")
+
+ def test_one_error(self):
+ validator = Draft4Validator({"minProperties" : 2})
+ error, = validator.iter_errors({})
+ self.assertEqual(
+ exceptions.best_match(validator.iter_errors({})).validator,
+ "minProperties",
+ )
+
+ def test_no_errors(self):
+ validator = Draft4Validator({})
+ self.assertIsNone(exceptions.best_match(validator.iter_errors({})))
+
+
+class TestByRelevance(unittest.TestCase):
+ def test_short_paths_are_better_matches(self):
+ shallow = exceptions.ValidationError("Oh no!", path=["baz"])
+ deep = exceptions.ValidationError("Oh yes!", path=["foo", "bar"])
+ match = max([shallow, deep], key=exceptions.by_relevance())
+ self.assertIs(match, shallow)
+
+ match = max([deep, shallow], key=exceptions.by_relevance())
+ self.assertIs(match, shallow)
+
+ def test_global_errors_are_even_better_matches(self):
+ shallow = exceptions.ValidationError("Oh no!", path=[])
+ deep = exceptions.ValidationError("Oh yes!", path=["foo"])
+
+ errors = sorted([shallow, deep], key=exceptions.by_relevance())
+ self.assertEqual(
+ [list(error.path) for error in errors],
+ [["foo"], []],
+ )
+
+ errors = sorted([deep, shallow], key=exceptions.by_relevance())
+ self.assertEqual(
+ [list(error.path) for error in errors],
+ [["foo"], []],
+ )
+
+ def test_weak_validators_are_lower_priority(self):
+ weak = exceptions.ValidationError("Oh no!", path=[], validator="a")
+ normal = exceptions.ValidationError("Oh yes!", path=[], validator="b")
+
+ best_match = exceptions.by_relevance(weak="a")
+
+ match = max([weak, normal], key=best_match)
+ self.assertIs(match, normal)
+
+ match = max([normal, weak], key=best_match)
+ self.assertIs(match, normal)
+
+ def test_strong_validators_are_higher_priority(self):
+ weak = exceptions.ValidationError("Oh no!", path=[], validator="a")
+ normal = exceptions.ValidationError("Oh yes!", path=[], validator="b")
+ strong = exceptions.ValidationError("Oh fine!", path=[], validator="c")
+
+ best_match = exceptions.by_relevance(weak="a", strong="c")
+
+ match = max([weak, normal, strong], key=best_match)
+ self.assertIs(match, strong)
+
+ match = max([strong, normal, weak], key=best_match)
+ self.assertIs(match, strong)
+
+
+class TestErrorTree(unittest.TestCase):
+ def test_it_knows_how_many_total_errors_it_contains(self):
+ errors = [mock.MagicMock() for _ in range(8)]
+ tree = exceptions.ErrorTree(errors)
+ self.assertEqual(tree.total_errors, 8)
+
+ def test_it_contains_an_item_if_the_item_had_an_error(self):
+ errors = [exceptions.ValidationError("a message", path=["bar"])]
+ tree = exceptions.ErrorTree(errors)
+ self.assertIn("bar", tree)
+
+ def test_it_does_not_contain_an_item_if_the_item_had_no_error(self):
+ errors = [exceptions.ValidationError("a message", path=["bar"])]
+ tree = exceptions.ErrorTree(errors)
+ self.assertNotIn("foo", tree)
+
+ def test_validators_that_failed_appear_in_errors_dict(self):
+ error = exceptions.ValidationError("a message", validator="foo")
+ tree = exceptions.ErrorTree([error])
+ self.assertEqual(tree.errors, {"foo" : error})
+
+ def test_it_creates_a_child_tree_for_each_nested_path(self):
+ errors = [
+ exceptions.ValidationError("a bar message", path=["bar"]),
+ exceptions.ValidationError("a bar -> 0 message", path=["bar", 0]),
+ ]
+ tree = exceptions.ErrorTree(errors)
+ self.assertIn(0, tree["bar"])
+ self.assertNotIn(1, tree["bar"])
+
+ def test_children_have_their_errors_dicts_built(self):
+ e1, e2 = (
+ exceptions.ValidationError("1", validator="foo", path=["bar", 0]),
+ exceptions.ValidationError("2", validator="quux", path=["bar", 0]),
+ )
+ tree = exceptions.ErrorTree([e1, e2])
+ self.assertEqual(tree["bar"][0].errors, {"foo" : e1, "quux" : e2})
+
+ def test_it_does_not_contain_subtrees_that_are_not_in_the_instance(self):
+ error = exceptions.ValidationError("123", validator="foo", instance=[])
+ tree = exceptions.ErrorTree([error])
+
+ with self.assertRaises(IndexError):
+ tree[0]
+
+ def test_if_its_in_the_tree_anyhow_it_does_not_raise_an_error(self):
+ """
+ If a validator is dumb (like :validator:`required` in draft 3) and
+ refers to a path that isn't in the instance, the tree still properly
+ returns a subtree for that path.
+
+ """
+
+ error = exceptions.ValidationError(
+ "a message", validator="foo", instance={}, path=["foo"],
+ )
+ tree = exceptions.ErrorTree([error])
+ self.assertIsInstance(tree["foo"], exceptions.ErrorTree)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jsonschema-2.0.0/jsonschema/tests/test_jsonschema_test_suite.py
new/jsonschema-2.3.0/jsonschema/tests/test_jsonschema_test_suite.py
--- old/jsonschema-2.0.0/jsonschema/tests/test_jsonschema_test_suite.py
2013-05-21 00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/jsonschema/tests/test_jsonschema_test_suite.py
2013-10-28 13:04:13.000000000 +0100
@@ -3,7 +3,7 @@
Tests comprehensive correctness of each draft's validator.
-See https://github.com/jsonschema/JSON-Schema-Test-Suite for details.
+See https://github.com/json-schema/JSON-Schema-Test-Suite for details.
"""
@@ -139,13 +139,15 @@
def missing_format(checker):
def missing_format(case):
format = case["schema"].get("format")
- if format not in checker.checkers or (
- # datetime.datetime is overzealous about typechecking in <=1.9
+ if format not in checker.checkers:
+ return "Format checker {0!r} not found.".format(format)
+ elif (
format == "date-time" and
pypy_version_info is not None and
pypy_version_info[:2] <= (1, 9)
):
- return "Format checker not found."
+ # datetime.datetime is overzealous about typechecking in <=1.9
+ return "datetime.datetime is broken on this version of PyPy."
return missing_format
@@ -178,6 +180,24 @@
# Make sure original cause is attached
self.assertIs(cm.exception.cause, cause)
+ def test_it_validates_formats_of_any_type(self):
+ checker = mock.Mock(spec=FormatChecker)
+ validator = self.validator_class(
+ {"format" : "foo"}, format_checker=checker,
+ )
+
+ validator.validate([1, 2, 3])
+
+ checker.check.assert_called_once_with([1, 2, 3], "foo")
+
+ cause = ValueError()
+ checker.check.side_effect = FormatError('aoeu', cause=cause)
+
+ with self.assertRaises(ValidationError) as cm:
+ validator.validate([1, 2, 3])
+ # Make sure original cause is attached
+ self.assertIs(cm.exception.cause, cause)
+
@load_json_cases("draft3/*.json", ignore_glob="draft3/refRemote.json")
@load_json_cases(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/jsonschema/tests/test_validators.py
new/jsonschema-2.3.0/jsonschema/tests/test_validators.py
--- old/jsonschema-2.0.0/jsonschema/tests/test_validators.py 2013-05-21
15:33:15.000000000 +0200
+++ new/jsonschema-2.3.0/jsonschema/tests/test_validators.py 2013-10-30
15:18:15.000000000 +0100
@@ -8,7 +8,7 @@
from jsonschema.compat import PY3
from jsonschema.tests.compat import mock, unittest
from jsonschema.validators import (
- RefResolutionError, UnknownType, ErrorTree, Draft3Validator,
+ RefResolutionError, UnknownType, Draft3Validator,
Draft4Validator, RefResolver, create, extend, validator_for, validate,
)
@@ -424,6 +424,23 @@
self.assertEqual(list(e5.path), [1, "bar", "baz"])
self.assertEqual(list(e6.path), [1, "foo"])
+ self.assertEqual(list(e1.schema_path), ["type"])
+ self.assertEqual(list(e2.schema_path), ["items", "type"])
+ self.assertEqual(
+ list(e3.schema_path), ["items", "properties", "bar", "type"],
+ )
+ self.assertEqual(
+ list(e4.schema_path),
+ ["items", "properties", "bar", "properties", "bar", "required"],
+ )
+ self.assertEqual(
+ list(e5.schema_path),
+ ["items", "properties", "bar", "properties", "baz", "minItems"]
+ )
+ self.assertEqual(
+ list(e6.schema_path), ["items", "properties", "foo", "enum"],
+ )
+
self.assertEqual(e1.validator, "type")
self.assertEqual(e2.validator, "type")
self.assertEqual(e3.validator, "type")
@@ -483,68 +500,22 @@
self.assertEqual(e1.validator, "type")
self.assertEqual(e2.validator, "minimum")
+ def test_additionalItems_with_items(self):
+ instance = ["foo", "bar", 1]
+ schema = {
+ "items": [{}],
+ "additionalItems" : {"type": "integer", "minimum": 5}
+ }
-class TestErrorTree(unittest.TestCase):
- def setUp(self):
- self.validator = Draft3Validator({})
-
- def test_it_knows_how_many_total_errors_it_contains(self):
- errors = [mock.MagicMock() for _ in range(8)]
- tree = ErrorTree(errors)
- self.assertEqual(tree.total_errors, 8)
-
- def test_it_contains_an_item_if_the_item_had_an_error(self):
- errors = [ValidationError("a message", path=["bar"])]
- tree = ErrorTree(errors)
- self.assertIn("bar", tree)
-
- def test_it_does_not_contain_an_item_if_the_item_had_no_error(self):
- errors = [ValidationError("a message", path=["bar"])]
- tree = ErrorTree(errors)
- self.assertNotIn("foo", tree)
-
- def test_validators_that_failed_appear_in_errors_dict(self):
- error = ValidationError("a message", validator="foo")
- tree = ErrorTree([error])
- self.assertEqual(tree.errors, {"foo" : error})
-
- def test_it_creates_a_child_tree_for_each_nested_path(self):
- errors = [
- ValidationError("a bar message", path=["bar"]),
- ValidationError("a bar -> 0 message", path=["bar", 0]),
- ]
- tree = ErrorTree(errors)
- self.assertIn(0, tree["bar"])
- self.assertNotIn(1, tree["bar"])
-
- def test_children_have_their_errors_dicts_built(self):
- e1, e2 = (
- ValidationError("message 1", validator="foo", path=["bar", 0]),
- ValidationError("message 2", validator="quux", path=["bar", 0]),
- )
- tree = ErrorTree([e1, e2])
- self.assertEqual(tree["bar"][0].errors, {"foo" : e1, "quux" : e2})
-
- def test_it_does_not_contain_subtrees_that_are_not_in_the_instance(self):
- error = ValidationError("a message", validator="foo", instance=[])
- tree = ErrorTree([error])
-
- with self.assertRaises(IndexError):
- tree[0]
-
- def test_if_its_in_the_tree_anyhow_it_does_not_raise_an_error(self):
- """
- If a validator is dumb (like :validator:`required` in draft 3) and
- refers to a path that isn't in the instance, the tree still properly
- returns a subtree for that path.
+ validator = Draft3Validator(schema)
+ errors = validator.iter_errors(instance)
+ e1, e2 = sorted_errors(errors)
- """
+ self.assertEqual(list(e1.path), [1])
+ self.assertEqual(list(e2.path), [2])
- error = ValidationError(
- "a message", validator="foo", instance={}, path=["foo"],
- )
- tree = ErrorTree([error])
- self.assertIsInstance(tree["foo"], ErrorTree)
+ self.assertEqual(e1.validator, "type")
+ self.assertEqual(e2.validator, "minimum")
class ValidatorTestMixin(object):
@@ -621,11 +592,38 @@
self.assertTrue(self.validator.is_type(True, "boolean"))
self.assertTrue(self.validator.is_valid(True, {"type": "any"}))
+ def test_non_string_custom_types(self):
+ schema = {'type': [None]}
+ cls = self.validator_class(schema, types={None: type(None)})
+ cls.validate(None, schema)
+
class TestDraft4Validator(ValidatorTestMixin, unittest.TestCase):
validator_class = Draft4Validator
+class TestBuiltinFormats(unittest.TestCase):
+ """
+ The built-in (specification-defined) formats do not raise type errors.
+
+ If an instance or value is not a string, it should be ignored.
+
+ """
+
+
+for format in FormatChecker.checkers:
+ def test(self, format=format):
+ v = Draft4Validator({"format": format}, format_checker=FormatChecker())
+ v.validate(123)
+
+ name = "test_{0}_ignores_non_strings".format(format)
+ if not PY3:
+ name = name.encode("utf-8")
+ test.__name__ = name
+ setattr(TestBuiltinFormats, name, test)
+ del test # Ugh py.test. Stop discovering top level tests.
+
+
class TestValidatorFor(unittest.TestCase):
def test_draft_3(self):
schema = {"$schema" : "http://json-schema.org/draft-03/schema"}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/jsonschema/validators.py
new/jsonschema-2.3.0/jsonschema/validators.py
--- old/jsonschema-2.0.0/jsonschema/validators.py 2013-05-21
15:39:23.000000000 +0200
+++ new/jsonschema-2.3.0/jsonschema/validators.py 2013-10-30
22:01:04.000000000 +0100
@@ -1,6 +1,5 @@
from __future__ import division, unicode_literals
-import collections
import contextlib
import json
import numbers
@@ -15,6 +14,7 @@
PY3, Sequence, urljoin, urlsplit, urldefrag, unquote, urlopen,
str_types, int_types, iteritems,
)
+from jsonschema.exceptions import ErrorTree # Backwards compatibility # noqa
from jsonschema.exceptions import RefResolutionError, SchemaError, UnknownType
@@ -118,7 +118,7 @@
def is_type(self, instance, type):
if type not in self._types:
- raise UnknownType(type)
+ raise UnknownType(type, instance, self.schema)
pytypes = self._types[type]
# bool inherits from int, so ensure bools aren't reported as ints
@@ -379,82 +379,6 @@
return result
-class ErrorTree(object):
- """
- ErrorTrees make it easier to check which validations failed.
-
- """
-
- _instance = _unset
-
- def __init__(self, errors=()):
- self.errors = {}
- self._contents = collections.defaultdict(self.__class__)
-
- for error in errors:
- container = self
- for element in error.path:
- container = container[element]
- container.errors[error.validator] = error
-
- self._instance = error.instance
-
- def __contains__(self, index):
- """
- Check whether ``instance[index]`` has any errors.
-
- """
-
- return index in self._contents
-
- def __getitem__(self, index):
- """
- Retrieve the child tree one level down at the given ``index``.
-
- If the index is not in the instance that this tree corresponds to and
- is not known by this tree, whatever error would be raised by
- ``instance.__getitem__`` will be propagated (usually this is some
- subclass of :class:`LookupError`.
-
- """
-
- if self._instance is not _unset and index not in self:
- self._instance[index]
- return self._contents[index]
-
- def __setitem__(self, index, value):
- self._contents[index] = value
-
- def __iter__(self):
- """
- Iterate (non-recursively) over the indices in the instance with errors.
-
- """
-
- return iter(self._contents)
-
- def __len__(self):
- """
- Same as :attr:`total_errors`.
-
- """
-
- return self.total_errors
-
- def __repr__(self):
- return "<%s (%s total errors)>" % (self.__class__.__name__, len(self))
-
- @property
- def total_errors(self):
- """
- The total number of errors in the entire tree, including children.
-
- """
-
- child_errors = sum(len(tree) for _, tree in iteritems(self._contents))
- return len(self.errors) + child_errors
-
-
def validator_for(schema, default=_unset):
if default is _unset:
default = Draft4Validator
@@ -462,6 +386,46 @@
def validate(instance, schema, cls=None, *args, **kwargs):
+ """
+ Validate an instance under the given schema.
+
+ >>> validate([2, 3, 4], {"maxItems" : 2})
+ Traceback (most recent call last):
+ ...
+ ValidationError: [2, 3, 4] is too long
+
+ :func:`validate` will first verify that the provided schema is itself
+ valid, since not doing so can lead to less obvious error messages and fail
+ in less obvious or consistent ways. If you know you have a valid schema
+ already or don't care, you might prefer using the
+ :meth:`~IValidator.validate` method directly on a specific validator
+ (e.g. :meth:`Draft4Validator.validate`).
+
+
+ :argument instance: the instance to validate
+ :argument schema: the schema to validate with
+ :argument cls: an :class:`IValidator` class that will be used to validate
+ the instance.
+
+ If the ``cls`` argument is not provided, two things will happen in
+ accordance with the specification. First, if the schema has a
+ :validator:`$schema` property containing a known meta-schema [#]_ then the
+ proper validator will be used. The specification recommends that all
+ schemas contain :validator:`$schema` properties for this reason. If no
+ :validator:`$schema` property is found, the default validator class is
+ :class:`Draft4Validator`.
+
+ Any other provided positional and keyword arguments will be passed on when
+ instantiating the ``cls``.
+
+ :raises:
+ :exc:`ValidationError` if the instance is invalid
+
+ :exc:`SchemaError` if the schema itself is invalid
+
+ .. rubric:: Footnotes
+ .. [#] known by a validator registered with :func:`validates`
+ """
if cls is None:
cls = validator_for(schema)
cls.check_schema(schema)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jsonschema-2.0.0/tox.ini new/jsonschema-2.3.0/tox.ini
--- old/jsonschema-2.0.0/tox.ini 2013-05-21 00:47:55.000000000 +0200
+++ new/jsonschema-2.3.0/tox.ini 2013-10-28 02:05:58.000000000 +0100
@@ -3,12 +3,21 @@
[testenv]
commands =
- py.test -s jsonschema
+ py.test [] -s jsonschema
{envpython} -m doctest README.rst
deps =
{[testenv:notpy33]deps}
{[testenv:py33]deps}
+[testenv:coverage]
+commands =
+ coverage run --source jsonschema [] {envbindir}/py.test
+ coverage html
+deps =
+ {[testenv:notpy33]deps}
+ {[testenv:py33]deps}
+ coverage
+
[testenv:docs]
basepython = python
changedir = docs
@@ -16,15 +25,12 @@
lxml
sphinx
commands =
- sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
+ sphinx-build [] -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
[testenv:style]
deps = flake8
commands =
- flake8 --max-complexity 10 jsonschema
-
-[flake8]
-ignore = E203,E302,E303,E701,F811
+ flake8 [] --max-complexity 10 jsonschema
[testenv:py26]
deps =
@@ -35,7 +41,7 @@
[testenv:py33]
commands =
- py.test -s jsonschema
+ py.test [] -s jsonschema
{envpython} -m doctest README.rst
sphinx-build -b doctest docs {envtmpdir}/html
deps =
@@ -52,8 +58,14 @@
[testenv:all]
deps =
- isodate
lxml
pytest
sphinx
+ strict-rfc3339
webcolors
+
+[flake8]
+ignore = E203,E302,E303,E701,F811
+
+[pytest]
+addopts = -r s
--
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]