Skip to content

Commit c202c48

Browse files
committed
Minor changes addressing PR review issues
1 parent 30bec1a commit c202c48

File tree

8 files changed

+96
-50
lines changed

8 files changed

+96
-50
lines changed

docs/creating.rst

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ Creating or Extending Validator Classes
2929
will have :func:`validates` automatically called for the given
3030
version.
3131

32-
:argument dict default_types: Deprecated. Please use the type_checker
33-
argument instead.
32+
:argument dict default_types:
33+
.. deprecated:: 2.7.0 Please use the type_checker argument instead.
3434

3535
If set, it provides mappings of JSON types to Python types that will
36-
be converted to functions and redefined in this object's TypeChecker
36+
be converted to functions and redefined in this object's
37+
:class:`jsonschema.TypeChecker`.
3738

38-
:argument jsonschema.TypeChecker type_checker: an instance
39-
of :class:`TypeChecker`, whose :meth:`is_type` will be called to
40-
validate the :validator:`type` property If unprovided, a default
41-
:class:`TypeChecker` will be created, with no support types.
39+
:argument jsonschema.TypeChecker type_checker: a type checker. If
40+
unprovided, a :class:`jsonschema.TypeChecker` will created with no
41+
supported types.
4242

4343
:returns: a new :class:`jsonschema.IValidator` class
4444

@@ -65,9 +65,8 @@ Creating or Extending Validator Classes
6565

6666
:argument str version: a version for the new validator class
6767

68-
:argument jsonschema.TypeChecker type_checker: an instance
69-
of :class:`TypeChecker`. If unprovided, the existing
70-
:class:`TypeChecker` will be used.
68+
:argument jsonschema.TypeChecker type_checker: a type checker. If
69+
unprovided, the existing :class:`jsonschema.TypeChecker` will be used.
7170

7271
:returns: a new :class:`jsonschema.IValidator` class
7372

docs/index.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ Contents:
4747
references
4848
creating
4949
faq
50-
types
5150

5251

5352
Indices and tables

docs/types.rst

Lines changed: 0 additions & 23 deletions
This file was deleted.

docs/validate.rst

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ classes should adhere to.
3232
will validate with. It is assumed to be valid, and providing
3333
an invalid schema can lead to undefined behavior. See
3434
:meth:`IValidator.check_schema` to validate a schema first.
35-
:argument types: Deprecated. Instead, create a custom TypeChecker
36-
and extend the validator. See :ref:`validating-types` for details.
35+
:argument types:
36+
.. deprecated:: 2.7.0
37+
Instead, create a custom type checker and extend the validator. See
38+
:ref:`validating-types` for details.
3739

3840
If used, this overrides or extends the list of known type when
3941
validating the :validator:`type` property. Should map strings (type
@@ -50,10 +52,13 @@ classes should adhere to.
5052

5153
.. attribute:: DEFAULT_TYPES
5254

53-
Deprecated. Under normal usage, this will be an empty dictionary.
55+
.. deprecated:: 2.7.0
56+
Use of this attribute is deprecated in favour of the the new type
57+
checkers.
5458

55-
If set, it provides mappings of JSON types to Python types that will
56-
be converted to functions and redefined in this object's TypeChecker
59+
It provides mappings of JSON types to Python types that will
60+
be converted to functions and redefined in this object's type checker
61+
if one is not provided.
5762

5863
.. attribute:: META_SCHEMA
5964

@@ -135,6 +140,27 @@ implementors of validator classes that extend or complement the
135140
ones included should adhere to it as well. For more information see
136141
:ref:`creating-validators`.
137142

143+
Type Checking
144+
-------------
145+
146+
To handle JSON Schema's :validator:`type` property, a :class:`IValidator` uses
147+
an associated :class:`TypeChecker`. The type checker provides an immutable
148+
mapping between names of types and functions that can test if an instance is
149+
of that type. The defaults are suitable for most users - each of the
150+
predefined Validators (Draft3, Draft4) has a :class:`TypeChecker` that can
151+
correctly handle that draft.
152+
153+
See :ref:`validating-types` for an example of providing a custom type check.
154+
155+
.. autoclass:: TypeChecker
156+
:members:
157+
158+
.. autoexception:: jsonschema.exceptions.UndefinedTypeCheck
159+
160+
Raised when trying to remove a type check that is not known to this
161+
TypeChecker. Internally this is also raised when calling
162+
:meth:`TypeChecker.is_type`, but is caught and re-raised as a
163+
:class:`jsonschema.exceptions.UnknownType` exception.
138164

139165
.. _validating-types:
140166

@@ -166,9 +192,9 @@ existing :class:`TypeChecker` or create a new one. You may then create a new
166192
class MyInteger(object):
167193
pass
168194
169-
def is_my_int(instance):
170-
return Draft3Validator.TYPE_CHECKER.is_type(instance, "number") or \
171-
isinstance(instance, MyInteger)
195+
def is_my_int(checker, instance):
196+
return (Draft3Validator.TYPE_CHECKER.is_type(instance, "number") or
197+
isinstance(instance, MyInteger))
172198
173199
type_checker = Draft3Validator.TYPE_CHECKER.redefine("number", is_my_int)
174200

jsonschema/_types.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def is_type(self, instance, type):
7171
7272
Arguments:
7373
74-
instance (any primitive type, i.e. str, number, bool):
74+
instance (object):
7575
7676
The instance to check
7777
@@ -90,9 +90,11 @@ def is_type(self, instance, type):
9090
if type is unknown to this object.
9191
"""
9292
try:
93-
return self._type_checkers[type](self, instance)
93+
fn = self._type_checkers[type]
9494
except KeyError:
95-
raise UndefinedTypeCheck
95+
raise UndefinedTypeCheck(type)
96+
97+
return fn(self, instance)
9698

9799
def redefine(self, type, fn):
98100
"""
@@ -106,8 +108,10 @@ def redefine(self, type, fn):
106108
107109
fn (callable):
108110
109-
A function taking exactly one parameter, instance,
110-
that checks if instance is of this type.
111+
A function taking exactly two parameters - the type checker
112+
calling the function and the instance to check. The function
113+
should return true if instance is of this type and false
114+
otherwise.
111115
112116
Returns:
113117
@@ -186,7 +190,7 @@ def remove_many(self, types):
186190
try:
187191
del evolver[type_]
188192
except KeyError:
189-
raise UndefinedTypeCheck
193+
raise UndefinedTypeCheck(type_)
190194

191195
return attr.evolve(self, type_checkers=evolver.persistent())
192196

jsonschema/compat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
)
2929
from urllib import unquote # noqa
3030
from urllib2 import urlopen # noqa
31-
str_types = basestring,
31+
str_types = basestring
3232
int_types = int, long
3333
iteritems = operator.methodcaller("iteritems")
3434

jsonschema/exceptions.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,18 @@ class RefResolutionError(Exception):
141141

142142

143143
class UndefinedTypeCheck(Exception):
144-
pass
144+
def __init__(self, type):
145+
self.type = type
146+
147+
def __unicode__(self):
148+
return "Type %r is unknown to this type checker" % self.type
149+
150+
if PY3:
151+
__str__ = __unicode__
152+
else:
153+
def __str__(self):
154+
return unicode(self).encode("utf-8")
155+
145156

146157
class UnknownType(Exception):
147158
def __init__(self, type, instance, schema):

jsonschema/tests/test_types.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ def test_initialised_empty(self):
5959
tc = _types.TypeChecker()
6060
self.assertEqual(len(tc._type_checkers), 0)
6161

62+
def test_checks_can_be_added_at_init(self):
63+
tc = _types.TypeChecker({"integer": _types.is_integer})
64+
self.assertEqual(len(tc._type_checkers), 1)
65+
6266
def test_checks_can_be_added(self):
6367
tc = _types.TypeChecker()
6468
tc = tc.redefine("integer", _types.is_integer)
@@ -114,6 +118,32 @@ def test_many_checks_can_be_removed(self):
114118

115119
self.assertEqual(len(tc._type_checkers), 0)
116120

121+
def test_unknown_type_raises_exception_on_is_type(self):
122+
tc = _types.TypeChecker()
123+
with self.assertRaises(UndefinedTypeCheck) as context:
124+
tc.is_type(4, 'foobar')
125+
126+
self.assertIn('foobar', str(context.exception))
127+
128+
def test_unknown_type_raises_exception_on_remove(self):
129+
tc = _types.TypeChecker()
130+
with self.assertRaises(UndefinedTypeCheck) as context:
131+
tc.remove('foobar')
132+
133+
self.assertIn('foobar', str(context.exception))
134+
135+
def test_type_check_can_raise_key_error(self):
136+
def raises_keyerror(checker, instance):
137+
raise KeyError("internal error")
138+
139+
tc = _types.TypeChecker({"object": raises_keyerror})
140+
141+
with self.assertRaises(KeyError) as context:
142+
tc.is_type(4, "object")
143+
144+
self.assertNotIn("object", str(context.exception))
145+
self.assertIn("internal error", str(context.exception))
146+
117147

118148
class TestCustomTypes(TestCase):
119149

0 commit comments

Comments
 (0)