diff options
author | Ben Smithers <ben.smithers@bristol.ac.uk> | 2017-12-11 14:38:42 +0000 |
---|---|---|
committer | Ben Smithers <ben.smithers@bristol.ac.uk> | 2017-12-11 14:47:45 +0000 |
commit | c202c48295b63b526f822efcbaf94a6dbf64b8a3 (patch) | |
tree | 0f73bfe7956711441db27e84a23b427f749f8da9 | |
parent | 30bec1a0100d8d8788eef2eb723fab9f60a7d769 (diff) | |
download | jsonschema-c202c48295b63b526f822efcbaf94a6dbf64b8a3.tar.gz |
Minor changes addressing PR review issues
-rw-r--r-- | docs/creating.rst | 19 | ||||
-rw-r--r-- | docs/index.rst | 1 | ||||
-rw-r--r-- | docs/types.rst | 23 | ||||
-rw-r--r-- | docs/validate.rst | 42 | ||||
-rw-r--r-- | jsonschema/_types.py | 16 | ||||
-rw-r--r-- | jsonschema/compat.py | 2 | ||||
-rw-r--r-- | jsonschema/exceptions.py | 13 | ||||
-rw-r--r-- | jsonschema/tests/test_types.py | 30 |
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): |