summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Berman <Julian+git@GrayVines.com>2011-12-30 14:03:01 -0500
committerJulian Berman <Julian+git@GrayVines.com>2011-12-30 14:03:01 -0500
commit5d68fa84ee198942100579707b9929436475681d (patch)
tree660415490e9e63f5d0a4e2c46efd250995704412
parentb18bb96b9bd74a1e52c607bd4ae6dcf924e7caf1 (diff)
downloadjsonschema-5d68fa84ee198942100579707b9929436475681d.tar.gz
Py2.5+ Support.
-rw-r--r--jsonschema.py93
-rw-r--r--tests.py156
2 files changed, 144 insertions, 105 deletions
diff --git a/jsonschema.py b/jsonschema.py
index 30bde35..980ec63 100644
--- a/jsonschema.py
+++ b/jsonschema.py
@@ -1,17 +1,31 @@
-from __future__ import division, unicode_literals
+from __future__ import division, with_statement
-import numbers
+import operator
import re
+import sys
import types
+# 2.5 support
+try:
+ next
+except NameError:
+ _none = object()
+ def next(iterator, default=_none):
+ try:
+ return iterator.next()
+ except StopIteration:
+ if default is not _none:
+ return default
+ raise
+
_PYTYPES = {
- "array" : list, "boolean" : bool, "integer" : int,
- "null" : types.NoneType, "number" : numbers.Number,
- "object" : dict, "string" : basestring
+ u"array" : list, u"boolean" : bool, u"integer" : int,
+ u"null" : types.NoneType, u"number" : (int, float),
+ u"object" : dict, u"string" : basestring,
}
-_PYTYPES["any"] = tuple(_PYTYPES.values())
+_PYTYPES[u"any"] = tuple(_PYTYPES.values())
class SchemaError(Exception):
@@ -26,9 +40,9 @@ class Validator(object):
# required and dependencies are handled in validate_properties
# exclusive Minium and Maximum are handled in validate_minimum
- SKIPPED = {
- "dependencies", "required", "exclusiveMinimum", "exclusiveMaximum"
- }
+ SKIPPED = set([
+ u"dependencies", u"required", u"exclusiveMinimum", u"exclusiveMaximum"
+ ])
def _error(self, msg):
raise ValidationError(msg)
@@ -45,10 +59,12 @@ class Validator(object):
if k in self.SKIPPED:
continue
- validator = getattr(self, "validate_%s" % (k,), None)
+ validator = getattr(self, u"validate_%s" % (k,), None)
if validator is None:
- raise SchemaError("'%s' is not a known schema property" % (k,))
+ raise SchemaError(
+ u"'%s' is not a known schema property" % (k,)
+ )
validator(v, instance, schema)
@@ -67,7 +83,7 @@ class Validator(object):
type = _PYTYPES.get(type)
if type is None:
- raise SchemaError("'%s' is not a known type" % (type,))
+ raise SchemaError(u"'%s' is not a known type" % (type,))
# isinstance(a_bool, int) will make us even sadder here, so
# let's be even dirtier than we would otherwise be.
@@ -75,16 +91,16 @@ class Validator(object):
elif (
isinstance(instance, type) and
(not isinstance(instance, bool) or
- type is bool or types == ["any"])
+ type is bool or types == [u"any"])
):
return
else:
- self._error("'%s' is not of type %s" % (instance, types))
+ self._error(u"'%s' is not of type %s" % (instance, types))
def validate_properties(self, properties, instance, schema):
for property, subschema in properties.iteritems():
if property in instance:
- dependencies = _(subschema.get("dependencies", []))
+ dependencies = _(subschema.get(u"dependencies", []))
if isinstance(dependencies, dict):
self.validate(instance, dependencies)
else:
@@ -92,12 +108,12 @@ class Validator(object):
first = next(missing, None)
if first is not None:
self._error(
- "'%s' is a dependency of '%s'" % (first, property)
+ u"'%s' is a dependency of '%s'" % (first, property)
)
self.validate(instance[property], subschema)
- elif subschema.get("required", False):
- self._error("'%s' is a required property" % (property,))
+ elif subschema.get(u"required", False):
+ self._error(u"'%s' is a required property" % (property,))
def validate_patternProperties(self, patternProperties, instance, schema):
for pattern, subschema in patternProperties.iteritems():
@@ -106,13 +122,14 @@ class Validator(object):
self.validate(v, subschema)
def validate_additionalProperties(self, aP, instance, schema):
- extras = instance.viewkeys() - schema.get("properties", {}).viewkeys()
+ # no viewkeys in <2.7, and pypy seems to fail on vk - vk anyhow, so...
+ extras = set(instance) - set(schema.get(u"properties", {}))
if isinstance(aP, dict):
for extra in extras:
self.validate(instance[extra], aP)
elif not aP and extras:
- self._error("Additional properties are not allowed")
+ self._error(u"Additional properties are not allowed")
def validate_items(self, items, instance, schema):
if isinstance(items, dict):
@@ -127,53 +144,57 @@ class Validator(object):
for item in instance[len(schema):]:
self.validate(item, aI)
elif not aI and len(instance) > len(schema):
- self._error("Additional items are not allowed")
+ self._error(u"Additional items are not allowed")
def validate_minimum(self, minimum, instance, schema):
- if schema.get("exclusiveMinimum", False):
+ if schema.get(u"exclusiveMinimum", False):
failed = instance <= minimum
- cmp = "less than or equal to"
+ cmp = u"less than or equal to"
else:
failed = instance < minimum
- cmp = "less than"
+ cmp = u"less than"
if failed:
- self._error("%s is %s the minimum (%s)" % (instance, cmp, minimum))
+ self._error(
+ u"%s is %s the minimum of %s" % (instance, cmp, minimum)
+ )
def validate_maximum(self, maximum, instance, schema):
- if schema.get("exclusiveMaximum", False):
+ if schema.get(u"exclusiveMaximum", False):
failed = instance >= maximum
- cmp = "greater than or equal to"
+ cmp = u"greater than or equal to"
else:
failed = instance > maximum
- cmp = "greater than"
+ cmp = u"greater than"
if failed:
- self._error("%s is %s the maximum (%s)" % (instance, cmp, maximum))
+ self._error(
+ u"%s is %s the maximum of %s" % (instance, cmp, maximum)
+ )
def validate_minItems(self, mI, instance, schema):
if len(instance) < mI:
- self._error("'%s' is too short" % (instance,))
+ self._error(u"'%s' is too short" % (instance,))
def validate_maxItems(self, mI, instance, schema):
if len(instance) > mI:
- self._error("'%s' is too long" % (instance,))
+ self._error(u"'%s' is too long" % (instance,))
def validate_pattern(self, pattern, instance, schema):
if not re.match(pattern, instance):
- self._error("'%s' does not match '%s'" % (instance, pattern))
+ self._error(u"'%s' does not match '%s'" % (instance, pattern))
def validate_minLength(self, mL, instance, schema):
if len(instance) < mL:
- self._error("'%s' is too short" % (instance,))
+ self._error(u"'%s' is too short" % (instance,))
def validate_maxLength(self, mL, instance, schema):
if len(instance) > mL:
- self._error("'%s' is too long" % (instance,))
+ self._error(u"'%s' is too long" % (instance,))
def validate_enum(self, enums, instance, schema):
if instance not in enums:
- self._error("'%s' is not one of %s" % (instance, enums))
+ self._error(u"'%s' is not one of %s" % (instance, enums))
def validate_divisibleBy(self, dB, instance, schema):
if isinstance(dB, float):
@@ -182,7 +203,7 @@ class Validator(object):
failed = instance % dB
if failed:
- self._error("%s is not divisible by %s" % (instance, dB))
+ self._error(u"%s is not divisible by %s" % (instance, dB))
def _(thing):
diff --git a/tests.py b/tests.py
index bf1d002..ba8061f 100644
--- a/tests.py
+++ b/tests.py
@@ -1,6 +1,11 @@
-from __future__ import unicode_literals
+from __future__ import with_statement
-import unittest
+import sys
+
+if (sys.version_info[0], sys.version_info[1]) < (2, 7):
+ import unittest2 as unittest
+else:
+ import unittest
from jsonschema import ValidationError, validate
@@ -18,85 +23,87 @@ class TestValidate(unittest.TestCase):
self.validate_test(valids=valids, invalids=invalids, type=type)
def test_type_integer(self):
- self.type_test("integer", [1], [1.1, "foo", {}, [], True, None])
+ self.type_test(u"integer", [1], [1.1, u"foo", {}, [], True, None])
def test_type_number(self):
- self.type_test("number", [1, 1.1], ["foo", {}, [], True, None])
+ self.type_test(u"number", [1, 1.1], [u"foo", {}, [], True, None])
def test_type_string(self):
- self.type_test("string", ["foo", b"foo"], [1, 1.1, {}, [], True, None])
+ self.type_test(
+ u"string", [u"foo", "foo"], [1, 1.1, {}, [], True, None]
+ )
def test_type_object(self):
- self.type_test("object", [{}], [1, 1.1, "foo", [], True, None])
+ self.type_test(u"object", [{}], [1, 1.1, u"foo", [], True, None])
def test_type_array(self):
- self.type_test("array", [[]], [1, 1.1, "foo", {}, True, None])
+ self.type_test(u"array", [[]], [1, 1.1, u"foo", {}, True, None])
def test_type_boolean(self):
self.type_test(
- "boolean", [True, False], [1, 1.1, "foo", {}, [], None]
+ u"boolean", [True, False], [1, 1.1, u"foo", {}, [], None]
)
def test_type_null(self):
- self.type_test("null", [None], [1, 1.1, "foo", {}, [], True])
+ self.type_test(u"null", [None], [1, 1.1, u"foo", {}, [], True])
def test_type_any(self):
- self.type_test("any", [1, 1.1, "foo", {}, [], True, None], [])
+ self.type_test(u"any", [1, 1.1, u"foo", {}, [], True, None], [])
def test_multiple_types(self):
self.type_test(
- ["integer", "string"], [1, "foo"], [1.1, {}, [], True, None]
+ [u"integer", u"string"], [1, u"foo"], [1.1, {}, [], True, None]
)
def test_multiple_types_subschema(self):
self.type_test(
- ["array", {"type" : "object"}],
- [[1, 2], {"foo" : "bar"}],
+ [u"array", {u"type" : u"object"}],
+ [[1, 2], {u"foo" : u"bar"}],
[1.1, True, None]
)
self.type_test(
- ["integer", {"properties" : {"foo" : {"type" : "null"}}}],
- [1, {"foo" : None}],
- [{"foo" : 1}, {"foo" : 1.1}],
+ [u"integer", {u"properties" : {u"foo" : {u"type" : u"null"}}}],
+ [1, {u"foo" : None}],
+ [{u"foo" : 1}, {u"foo" : 1.1}],
)
def test_properties(self):
schema = {
"properties" : {
- "foo" : {"type" : "number"},
- "bar" : {"type" : "string"},
+ u"foo" : {u"type" : u"number"},
+ u"bar" : {u"type" : u"string"},
}
}
valids = [
- {"foo" : 1, "bar" : "baz"},
- {"foo" : 1, "bar" : "baz", "quux" : 42},
+ {u"foo" : 1, u"bar" : u"baz"},
+ {u"foo" : 1, u"bar" : u"baz", u"quux" : 42},
]
- self.validate_test(valids, [{"foo" : 1, "bar" : []}], **schema)
+ self.validate_test(valids, [{u"foo" : 1, u"bar" : []}], **schema)
def test_patternProperties(self):
self.validate_test(
- [{"foo" : 1}, {"foo" : 1, "fah" : 2, "bar" : "baz"}],
- [{"foo" : "bar"}, {"foo" : 1, "fah" : "bar"}],
- patternProperties={"f.*" : {"type" : "integer"}},
+ [{u"foo" : 1}, {u"foo" : 1, u"fah" : 2, u"bar" : u"baz"}],
+ [{u"foo" : u"bar"}, {u"foo" : 1, u"fah" : u"bar"}],
+ patternProperties={u"f.*" : {u"type" : u"integer"}},
)
def test_multiple_patternProperties(self):
- pattern = {"a*" : {"type" : "integer"}, "aaa*" : {"maximum" : 20}}
+ pattern = {u"a*" : {u"type" : u"integer"}, u"aaa*" : {u"maximum" : 20}}
self.validate_test(
- [{"a" : 1}, {"a" : 21}, {"aaaa" : 18}],
- [{"aaa" : "foo"}, {"aaaa" : 31}],
+ [{u"a" : 1}, {u"a" : 21}, {u"aaaa" : 18}],
+ [{u"aaa" : u"foo"}, {u"aaaa" : 31}],
patternProperties=pattern,
)
def test_additionalProperties(self):
- ex = {"foo" : 1, "bar" : "baz", "quux" : False}
+ ex = {u"foo" : 1, u"bar" : u"baz", u"quux" : False}
schema = {
"properties" : {
- "foo" : {"type" : "number"},
- "bar" : {"type" : "string"},
+ u"foo" : {u"type" : u"number"},
+ u"bar" : {u"type" : u"string"},
}
}
@@ -105,81 +112,90 @@ class TestValidate(unittest.TestCase):
with self.assertRaises(ValidationError):
validate(ex, dict(additionalProperties=False, **schema))
- invalids = [{"foo" : 1, "bar" : "baz", "quux" : "boom"}]
- additional = {"type" : "boolean"}
+ invalids = [{u"foo" : 1, u"bar" : u"baz", u"quux" : u"boom"}]
+ additional = {u"type" : u"boolean"}
self.validate_test(
[ex], invalids, additionalProperties=additional, **schema
)
def test_items(self):
- validate([1, "foo", False], {"type" : "array"})
- self.validate_test([[1, 2, 3]], [[1, "x"]], items={"type" : "integer"})
+ validate([1, u"foo", False], {u"type" : u"array"})
+ self.validate_test(
+ [[1, 2, 3]], [[1, u"x"]], items={u"type" : u"integer"}
+ )
def test_items_tuple_typing(self):
- items = [{"type" : "integer"}, {"type" : "string"}]
- self.validate_test([[1, "foo"]], [["foo", 1], [1, False]], items=items)
+ items = [{u"type" : u"integer"}, {u"type" : u"string"}]
+ self.validate_test(
+ [[1, u"foo"]], [[u"foo", 1], [1, False]], items=items
+ )
def test_additionalItems(self):
- schema = {"items" : [{"type" : "integer"}, {"type" : "string"}]}
+ schema = {"items" : [{u"type" : u"integer"}, {u"type" : u"string"}]}
- validate([1, "foo", False], schema)
+ validate([1, u"foo", False], schema)
self.validate_test(
- [[1, "foo"]], [[1, "foo", False]], additionalItems=False, **schema
+ [[1, u"foo"]],
+ [[1, u"foo", False]],
+ additionalItems=False,
+ **schema
)
self.validate_test(
- [[1, "foo", 3]],
- [[1, "foo", "bar"]],
- additionalItems={"type" : "integer"},
+ [[1, u"foo", 3]],
+ [[1, u"foo", u"bar"]],
+ additionalItems={u"type" : u"integer"},
**schema
)
def test_required(self):
schema = {
- "properties" : {
- "foo" : {"type" : "number"},
- "bar" : {"type" : "string"},
+ u"properties" : {
+ u"foo" : {u"type" : u"number"},
+ u"bar" : {u"type" : u"string"},
}
}
- validate({"foo" : 1}, schema)
+ validate({u"foo" : 1}, schema)
- schema["properties"]["foo"]["required"] = False
+ schema[u"properties"][u"foo"][u"required"] = False
- validate({"foo" : 1}, schema)
+ validate({u"foo" : 1}, schema)
- schema["properties"]["foo"]["required"] = True
- schema["properties"]["bar"]["required"] = True
+ schema[u"properties"][u"foo"][u"required"] = True
+ schema[u"properties"][u"bar"][u"required"] = True
with self.assertRaises(ValidationError):
- validate({"foo" : 1}, schema)
+ validate({u"foo" : 1}, schema)
def test_dependencies(self):
- schema = {"properties" : {"bar" : {"dependencies" : "foo"}}}
+ schema = {"properties" : {u"bar" : {u"dependencies" : u"foo"}}}
self.validate_test(
- [{}, {"foo" : 1}, {"foo" : 1, "bar" : 2}], [{"bar" : 2}], **schema
+ [{}, {u"foo" : 1}, {u"foo" : 1, u"bar" : 2}],
+ [{u"bar" : 2}],
+ **schema
)
def test_multiple_dependencies(self):
schema = {
"properties" : {
- "quux" : {"dependencies" : ["foo", "bar"]}
+ u"quux" : {u"dependencies" : [u"foo", u"bar"]}
}
}
valids = [
{},
- {"foo" : 1},
- {"foo" : 1, "bar" : 2},
- {"foo" : 1, "bar" : 2, "quux" : 3},
+ {u"foo" : 1},
+ {u"foo" : 1, u"bar" : 2},
+ {u"foo" : 1, u"bar" : 2, u"quux" : 3},
]
invalids = [
- {"foo" : 1, "quux" : 2},
- {"bar" : 1, "quux" : 2},
- {"quux" : 1},
+ {u"foo" : 1, u"quux" : 2},
+ {u"bar" : 1, u"quux" : 2},
+ {u"quux" : 1},
]
self.validate_test(valids, invalids, **schema)
@@ -187,15 +203,17 @@ class TestValidate(unittest.TestCase):
def test_multiple_dependencies_subschema(self):
dependencies = {
"properties" : {
- "foo" : {"type" : "integer"},
- "bar" : {"type" : "integer"},
+ u"foo" : {u"type" : u"integer"},
+ u"bar" : {u"type" : u"integer"},
}
}
- schema = {"properties" : {"bar" : {"dependencies" : dependencies}}}
+ schema = {"properties" : {u"bar" : {u"dependencies" : dependencies}}}
self.validate_test(
- [{"foo" : 1, "bar" : 2}], [{"foo" : "quux", "bar" : 2}], **schema
+ [{u"foo" : 1, u"bar" : 2}],
+ [{u"foo" : u"quux", u"bar" : 2}],
+ **schema
)
def test_minimum(self):
@@ -216,20 +234,20 @@ class TestValidate(unittest.TestCase):
pass
def test_pattern(self):
- self.validate_test(["aaa"], ["ab"], pattern="^a*$")
+ self.validate_test([u"aaa"], [u"ab"], pattern=u"^a*$")
def test_minLength(self):
- self.validate_test(["foo"], ["f"], minLength=2)
+ self.validate_test([u"foo"], [u"f"], minLength=2)
def test_maxLength(self):
- self.validate_test(["f"], ["foo"], maxLength=2)
+ self.validate_test([u"f"], [u"foo"], maxLength=2)
def test_enum(self):
self.validate_test([1], [5], enum=[1, 2, 3])
- self.validate_test(["foo"], ["quux"], enum=["foo", "bar"])
+ self.validate_test([u"foo"], [u"quux"], enum=[u"foo", u"bar"])
self.validate_test([True], [False], enum=[True])
self.validate_test(
- [{"foo" : "bar"}], [{"foo" : "baz"}], enum=[{"foo" : "bar"}]
+ [{u"foo" : u"bar"}], [{u"foo" : u"baz"}], enum=[{u"foo" : u"bar"}]
)
def test_divisibleBy(self):