summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Smithers <ben.smithers@bristol.ac.uk>2017-12-11 14:38:42 +0000
committerBen Smithers <ben.smithers@bristol.ac.uk>2017-12-11 14:47:45 +0000
commitc202c48295b63b526f822efcbaf94a6dbf64b8a3 (patch)
tree0f73bfe7956711441db27e84a23b427f749f8da9
parent30bec1a0100d8d8788eef2eb723fab9f60a7d769 (diff)
downloadjsonschema-c202c48295b63b526f822efcbaf94a6dbf64b8a3.tar.gz
Minor changes addressing PR review issues
-rw-r--r--docs/creating.rst19
-rw-r--r--docs/index.rst1
-rw-r--r--docs/types.rst23
-rw-r--r--docs/validate.rst42
-rw-r--r--jsonschema/_types.py16
-rw-r--r--jsonschema/compat.py2
-rw-r--r--jsonschema/exceptions.py13
-rw-r--r--jsonschema/tests/test_types.py30
8 files changed, 96 insertions, 50 deletions
diff --git a/docs/creating.rst b/docs/creating.rst
index 0a65fd9..bf49f77 100644
--- a/docs/creating.rst
+++ b/docs/creating.rst
@@ -29,16 +29,16 @@ Creating or Extending Validator Classes
will have :func:`validates` automatically called for the given
version.
- :argument dict default_types: Deprecated. Please use the type_checker
- argument instead.
+ :argument dict default_types:
+ .. deprecated:: 2.7.0 Please use the type_checker argument instead.
If set, it provides mappings of JSON types to Python types that will
- be converted to functions and redefined in this object's TypeChecker
+ be converted to functions and redefined in this object's
+ :class:`jsonschema.TypeChecker`.
- :argument jsonschema.TypeChecker type_checker: an instance
- of :class:`TypeChecker`, whose :meth:`is_type` will be called to
- validate the :validator:`type` property If unprovided, a default
- :class:`TypeChecker` will be created, with no support types.
+ :argument jsonschema.TypeChecker type_checker: a type checker. If
+ unprovided, a :class:`jsonschema.TypeChecker` will created with no
+ supported types.
:returns: a new :class:`jsonschema.IValidator` class
@@ -65,9 +65,8 @@ Creating or Extending Validator Classes
:argument str version: a version for the new validator class
- :argument jsonschema.TypeChecker type_checker: an instance
- of :class:`TypeChecker`. If unprovided, the existing
- :class:`TypeChecker` will be used.
+ :argument jsonschema.TypeChecker type_checker: a type checker. If
+ unprovided, the existing :class:`jsonschema.TypeChecker` will be used.
:returns: a new :class:`jsonschema.IValidator` class
diff --git a/docs/index.rst b/docs/index.rst
index e97278f..93dc058 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -47,7 +47,6 @@ Contents:
references
creating
faq
- types
Indices and tables
diff --git a/docs/types.rst b/docs/types.rst
deleted file mode 100644
index 006060e..0000000
--- a/docs/types.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-.. currentmodule:: jsonschema
-
-=============
-Type Checking
-=============
-
-Each :class:`IValidator` has an associated :class:`TypeChecker`. The
-TypeChecker provides an immutable mapping between names of types and
-functions that can test if an instance is of that type. The defaults are
-suitable for most users - each of the predefined Validators (Draft3, Draft4)
-has a :class:`TypeChecker` that can correctly handle that draft.
-
-See :ref:`validating-types` for an example of providing a custom type check.
-
-.. autoclass:: TypeChecker
- :members:
-
-.. autoexception:: jsonschema.exceptions.UndefinedTypeCheck
-
- Raised when trying to remove a type check that is not known to this
- TypeChecker. Internally this is also raised when calling
- :meth:`TypeChecker.is_type`, but is caught and re-raised as a
- :class:`jsonschema.exceptions.UnknownType` exception.
diff --git a/docs/validate.rst b/docs/validate.rst
index 83ee8dc..cded8fb 100644
--- a/docs/validate.rst
+++ b/docs/validate.rst
@@ -32,8 +32,10 @@ classes should adhere to.
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: Deprecated. Instead, create a custom TypeChecker
- and extend the validator. See :ref:`validating-types` for details.
+ :argument types:
+ .. deprecated:: 2.7.0
+ Instead, create a custom type checker and extend the validator. See
+ :ref:`validating-types` for details.
If used, this overrides or extends the list of known type when
validating the :validator:`type` property. Should map strings (type
@@ -50,10 +52,13 @@ classes should adhere to.
.. attribute:: DEFAULT_TYPES
- Deprecated. Under normal usage, this will be an empty dictionary.
+ .. deprecated:: 2.7.0
+ Use of this attribute is deprecated in favour of the the new type
+ checkers.
- If set, it provides mappings of JSON types to Python types that will
- be converted to functions and redefined in this object's TypeChecker
+ It provides mappings of JSON types to Python types that will
+ be converted to functions and redefined in this object's type checker
+ if one is not provided.
.. attribute:: META_SCHEMA
@@ -135,6 +140,27 @@ implementors of validator classes that extend or complement the
ones included should adhere to it as well. For more information see
:ref:`creating-validators`.
+Type Checking
+-------------
+
+To handle JSON Schema's :validator:`type` property, a :class:`IValidator` uses
+an associated :class:`TypeChecker`. The type checker provides an immutable
+mapping between names of types and functions that can test if an instance is
+of that type. The defaults are suitable for most users - each of the
+predefined Validators (Draft3, Draft4) has a :class:`TypeChecker` that can
+correctly handle that draft.
+
+See :ref:`validating-types` for an example of providing a custom type check.
+
+.. autoclass:: TypeChecker
+ :members:
+
+.. autoexception:: jsonschema.exceptions.UndefinedTypeCheck
+
+ Raised when trying to remove a type check that is not known to this
+ TypeChecker. Internally this is also raised when calling
+ :meth:`TypeChecker.is_type`, but is caught and re-raised as a
+ :class:`jsonschema.exceptions.UnknownType` exception.
.. _validating-types:
@@ -166,9 +192,9 @@ existing :class:`TypeChecker` or create a new one. You may then create a new
class MyInteger(object):
pass
- def is_my_int(instance):
- return Draft3Validator.TYPE_CHECKER.is_type(instance, "number") or \
- isinstance(instance, MyInteger)
+ def is_my_int(checker, instance):
+ return (Draft3Validator.TYPE_CHECKER.is_type(instance, "number") or
+ isinstance(instance, MyInteger))
type_checker = Draft3Validator.TYPE_CHECKER.redefine("number", is_my_int)
diff --git a/jsonschema/_types.py b/jsonschema/_types.py
index 2ddcf3d..ad75ff3 100644
--- a/jsonschema/_types.py
+++ b/jsonschema/_types.py
@@ -71,7 +71,7 @@ class TypeChecker(object):
Arguments:
- instance (any primitive type, i.e. str, number, bool):
+ instance (object):
The instance to check
@@ -90,9 +90,11 @@ class TypeChecker(object):
if type is unknown to this object.
"""
try:
- return self._type_checkers[type](self, instance)
+ fn = self._type_checkers[type]
except KeyError:
- raise UndefinedTypeCheck
+ raise UndefinedTypeCheck(type)
+
+ return fn(self, instance)
def redefine(self, type, fn):
"""
@@ -106,8 +108,10 @@ class TypeChecker(object):
fn (callable):
- A function taking exactly one parameter, instance,
- that checks if instance is of this type.
+ A function taking exactly two parameters - the type checker
+ calling the function and the instance to check. The function
+ should return true if instance is of this type and false
+ otherwise.
Returns:
@@ -186,7 +190,7 @@ class TypeChecker(object):
try:
del evolver[type_]
except KeyError:
- raise UndefinedTypeCheck
+ raise UndefinedTypeCheck(type_)
return attr.evolve(self, type_checkers=evolver.persistent())
diff --git a/jsonschema/compat.py b/jsonschema/compat.py
index 2dd607d..ff91fe6 100644
--- a/jsonschema/compat.py
+++ b/jsonschema/compat.py
@@ -28,7 +28,7 @@ else:
)
from urllib import unquote # noqa
from urllib2 import urlopen # noqa
- str_types = basestring,
+ str_types = basestring
int_types = int, long
iteritems = operator.methodcaller("iteritems")
diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions.py
index c6ef8c1..d10f246 100644
--- a/jsonschema/exceptions.py
+++ b/jsonschema/exceptions.py
@@ -141,7 +141,18 @@ class RefResolutionError(Exception):
class UndefinedTypeCheck(Exception):
- pass
+ def __init__(self, type):
+ self.type = type
+
+ def __unicode__(self):
+ return "Type %r is unknown to this type checker" % self.type
+
+ if PY3:
+ __str__ = __unicode__
+ else:
+ def __str__(self):
+ return unicode(self).encode("utf-8")
+
class UnknownType(Exception):
def __init__(self, type, instance, schema):
diff --git a/jsonschema/tests/test_types.py b/jsonschema/tests/test_types.py
index b2747b3..c1a5a48 100644
--- a/jsonschema/tests/test_types.py
+++ b/jsonschema/tests/test_types.py
@@ -59,6 +59,10 @@ class TestTypeChecker(TestCase):
tc = _types.TypeChecker()
self.assertEqual(len(tc._type_checkers), 0)
+ def test_checks_can_be_added_at_init(self):
+ tc = _types.TypeChecker({"integer": _types.is_integer})
+ self.assertEqual(len(tc._type_checkers), 1)
+
def test_checks_can_be_added(self):
tc = _types.TypeChecker()
tc = tc.redefine("integer", _types.is_integer)
@@ -114,6 +118,32 @@ class TestTypeChecker(TestCase):
self.assertEqual(len(tc._type_checkers), 0)
+ def test_unknown_type_raises_exception_on_is_type(self):
+ tc = _types.TypeChecker()
+ with self.assertRaises(UndefinedTypeCheck) as context:
+ tc.is_type(4, 'foobar')
+
+ self.assertIn('foobar', str(context.exception))
+
+ def test_unknown_type_raises_exception_on_remove(self):
+ tc = _types.TypeChecker()
+ with self.assertRaises(UndefinedTypeCheck) as context:
+ tc.remove('foobar')
+
+ self.assertIn('foobar', str(context.exception))
+
+ def test_type_check_can_raise_key_error(self):
+ def raises_keyerror(checker, instance):
+ raise KeyError("internal error")
+
+ tc = _types.TypeChecker({"object": raises_keyerror})
+
+ with self.assertRaises(KeyError) as context:
+ tc.is_type(4, "object")
+
+ self.assertNotIn("object", str(context.exception))
+ self.assertIn("internal error", str(context.exception))
+
class TestCustomTypes(TestCase):