json-schema-validator-2.3.1/0000775000175000017500000000000012321763056015664 5ustar zygazyga00000000000000json-schema-validator-2.3.1/json_schema_validator/0000775000175000017500000000000012321763056022222 5ustar zygazyga00000000000000json-schema-validator-2.3.1/json_schema_validator/misc.py0000664000175000017500000000162112321761401023517 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Stuff that does not belong anywhere else """ import decimal # List of types recognized as numeric NUMERIC_TYPES = (int, float, decimal.Decimal) json-schema-validator-2.3.1/json_schema_validator/shortcuts.py0000664000175000017500000000372112321761401024625 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ One liners that make the code shorter """ import simplejson from json_schema_validator.schema import Schema from json_schema_validator.validator import Validator def validate(schema_text, data_text): """ Validate specified JSON text (data_text) with specified schema (schema text). Both are converted to JSON objects with :func:`simplesjon.loads`. :param schema_text: Text of the JSON schema to check against :type schema_text: :class:`str` :param data_text: Text of the JSON object to check :type data_text: :class:`str` :returns: Same as :meth:`json_schema_validator.validator.Validator.validate` :raises: Whatever may be raised by simplejson (in particular :class:`simplejson.decoder.JSONDecoderError`, a subclass of :class:`ValueError`) :raises: Whatever may be raised by :meth:`json_schema_validator.validator.Validator.validate`. In particular :class:`json_schema_validator.errors.ValidationError` and :class:`json_schema_validator.errors.SchemaError` """ schema = Schema(simplejson.loads(schema_text)) data = simplejson.loads(data_text) return Validator.validate(schema, data) json-schema-validator-2.3.1/json_schema_validator/tests/0000775000175000017500000000000012321763056023364 5ustar zygazyga00000000000000json-schema-validator-2.3.1/json_schema_validator/tests/test_validator.py0000664000175000017500000006601112321761650026764 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Unit tests for JSON schema """ from testscenarios import TestWithScenarios from testtools import TestCase from json_schema_validator.errors import ValidationError from json_schema_validator.shortcuts import validate from json_schema_validator.validator import Validator class ValidatorFailureTests(TestWithScenarios, TestCase): scenarios = [ ("type_string_got_null", { 'schema': '{"type": "string"}', 'data': 'null', 'raises': ValidationError( "None does not match type 'string'", "Object has incorrect type (expected string)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_string_got_integer", { 'schema': '{"type": "string"}', 'data': '5', 'raises': ValidationError( "5 does not match type 'string'", "Object has incorrect type (expected string)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_number_got_null", { 'schema': '{"type": "number"}', 'data': 'null', 'raises': ValidationError( "None does not match type 'number'", "Object has incorrect type (expected number)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_number_got_string", { 'schema': '{"type": "number"}', 'data': '"foobar"', 'raises': ValidationError( "'foobar' does not match type 'number'", "Object has incorrect type (expected number)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_number_got_string_that_looks_like_number", { 'schema': '{"type": "number"}', 'data': '"3"', 'raises': ValidationError( "'3' does not match type 'number'", "Object has incorrect type (expected number)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_integer_got_float", { 'schema': '{"type": "integer"}', 'data': '1.5', 'raises': ValidationError( "1.5 does not match type 'integer'", "Object has incorrect type (expected integer)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_integer_got_null", { 'schema': '{"type": "integer"}', 'data': 'null', 'raises': ValidationError( "None does not match type 'integer'", "Object has incorrect type (expected integer)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_boolean_got_null", { 'schema': '{"type": "boolean"}', 'data': 'null', 'raises': ValidationError( "None does not match type 'boolean'", "Object has incorrect type (expected boolean)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_boolean_got_empty_string", { 'schema': '{"type": "boolean"}', 'data': '""', 'raises': ValidationError( "u'' does not match type 'boolean'", "Object has incorrect type (expected boolean)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_boolean_got_empty_list", { 'schema': '{"type": "boolean"}', 'data': '[]', 'raises': ValidationError( "[] does not match type 'boolean'", "Object has incorrect type (expected boolean)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_boolean_got_empty_object", { 'schema': '{"type": "boolean"}', 'data': '{}', 'raises': ValidationError( "{} does not match type 'boolean'", "Object has incorrect type (expected boolean)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_object_got_integer", { 'schema': '{"type": "object"}', 'data': '1', 'raises': ValidationError( "1 does not match type 'object'", "Object has incorrect type (expected object)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_object_got_null", { 'schema': '{"type": "object"}', 'data': 'null', 'raises': ValidationError( "None does not match type 'object'", "Object has incorrect type (expected object)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_array_got_null", { 'schema': '{"type": "array"}', 'data': 'null', 'raises': ValidationError( "None does not match type 'array'", "Object has incorrect type (expected array)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_array_got_integer", { 'schema': '{"type": "array"}', 'data': '1', 'raises': ValidationError( "1 does not match type 'array'", "Object has incorrect type (expected array)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_null_got_empty_string", { 'schema': '{"type": "null"}', 'data': '""', 'raises': ValidationError( "u'' does not match type 'null'", "Object has incorrect type (expected null)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_null_got_zero", { 'schema': '{"type": "null"}', 'data': '0', 'raises': ValidationError( "0 does not match type 'null'", "Object has incorrect type (expected null)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_null_got_empty_list", { 'schema': '{"type": "null"}', 'data': '[]', 'raises': ValidationError( "[] does not match type 'null'", "Object has incorrect type (expected null)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_null_got_empty_object", { 'schema': '{"type": "null"}', 'data': '{}', 'raises': ValidationError( "{} does not match type 'null'", "Object has incorrect type (expected null)"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("type_list_got_mismatching_item", { 'schema': '{"type": ["string", "number"]}', 'data': '{}', 'raises': ValidationError( "{} does not match any of the types in ['string', 'number']", "Object has incorrect type (multiple types possible)", ".type"), 'object_expr': 'object', 'schema_expr': 'schema.type', }), ("property_check_is_not_primitive", { 'schema': """ { "type": "object", "properties": { "foo": { "type": "number" } } }""", 'data': '{"foo": "foobar"}', 'raises': ValidationError( "'foobar' does not match type 'number'", "Object has incorrect type (expected number)"), 'object_expr': 'object.foo', 'schema_expr': 'schema.properties.foo.type', }), ("property_check_validates_optional_properties", { 'schema': """ { "type": "object", "properties": { "foo": { "type": "number", "optional": true } } }""", 'data': '{"foo": null}', 'raises': ValidationError( "None does not match type 'number'", "Object has incorrect type (expected number)"), 'object_expr': 'object.foo', 'schema_expr': 'schema.properties.foo.type', }), ("property_check_reports_missing_non_optional_properties", { 'schema': """ { "type": "object", "properties": { "foo": { "type": "number", "optional": false } } }""", 'data': '{}', 'raises': ValidationError( "{} does not have property 'foo'", "Object lacks property 'foo'"), 'object_expr': 'object', 'schema_expr': 'schema.properties.foo.optional', }), ("property_check_reports_unknown_properties_when_additionalProperties_is_false", { 'schema': """ { "type": "object", "additionalProperties": false }""", 'data': '{"foo": 5}', 'raises': ValidationError( "{'foo': 5} has unknown property 'foo' and" " additionalProperties is false", "Object has unknown property 'foo' but additional " "properties are disallowed"), 'object_expr': 'object', 'schema_expr': 'schema.additionalProperties', }), ("property_check_validates_additional_properties_using_specified_type_when_additionalProperties_is_an_object_violation", { 'schema': """ { "type": "object", "additionalProperties": { "type": "string" } }""", 'data': '{"foo": "aaa", "bar": 5}', 'raises': ValidationError( "5 does not match type 'string'", "Object has incorrect type (expected string)"), 'object_expr': 'object.bar', 'schema_expr': 'schema.additionalProperties.type', }), ("enum_check_reports_unlisted_values", { 'schema': '{"enum": [1, 2, 3]}', 'data': '5', 'raises': ValidationError( '5 does not match any value in enumeration [1, 2, 3]', "Object does not match any value in enumeration"), 'object_expr': 'object', 'schema_expr': 'schema.enum', }), ("items_with_single_schema_finds_problems", { 'schema': '{"items": {"type": "string"}}', 'data': '["foo", null, "froz"]', 'raises': ValidationError( "None does not match type 'string'", "Object has incorrect type (expected string)"), 'object_expr': 'object[1]', 'schema_expr': 'schema.items.type', }), ("items_with_array_schema_checks_for_too_short_data", { 'schema': """ { "items": [ {"type": "string"}, {"type": "boolean"} ] }""", 'data': '["foo"]', 'raises': ValidationError( "['foo'] is shorter than array schema [{'type':" " 'string'}, {'type': 'boolean'}]", "Object array is shorter than schema array"), 'object_expr': 'object', 'schema_expr': 'schema.items', }), ("items_with_array_schema_and_additionalProperties_of_false_checks_for_too_much_data", { 'schema': """ { "items": [ {"type": "string"}, {"type": "boolean"} ], "additionalProperties": false }""", 'data': '["foo", false, 5]', 'raises': ValidationError( "['foo', False, 5] is not of the same length as array" " schema [{'type': 'string'}, {'type': 'boolean'}] and" " additionalProperties is false", "Object array is not of the same length as schema array"), 'object_expr': 'object', 'schema_expr': 'schema.items', }), ("items_with_array_schema_and_additionalProperties_can_find_problems", { 'schema': """ { "items": [ {"type": "string"}, {"type": "boolean"} ], "additionalProperties": { "type": "number" } }""", 'data': '["foo", false, 5, 7.9, null]', 'raises': ValidationError( "None does not match type 'number'", "Object has incorrect type (expected number)"), 'object_expr': 'object[4]', 'schema_expr': 'schema.additionalProperties.type', }), ("array_with_array_schema_and_uniqueItems_is_True", { 'schema': """ { "type": "array", "items": {"type": "string"}, "uniqueItems": true }""", 'data': '["foo", "bar", "foo"]', 'raises': ValidationError( "Repeated items found in ['foo', 'bar', 'foo']", "Repeated items found in array"), 'object_expr': 'object', 'schema_expr': 'schema.items', }), ("requires_with_simple_property_name_can_report_problems", { 'schema': """ { "properties": { "foo": { "optional": true }, "bar": { "requires": "foo", "optional": true } } } """, 'data': '{"bar": null}', 'raises': ValidationError( "None requires presence of property 'foo' in the same" " object", "Enclosing object does not have property 'foo'"), 'object_expr': 'object.bar', 'schema_expr': 'schema.properties.bar.requires', }), ("requires_with_simple_property_name_can_report_problems_while_nested", { 'schema': """ { "type": "object", "properties": { "nested": { "properties": { "foo": { "optional": true }, "bar": { "requires": "foo", "optional": true } } } } } """, 'data': '{"nested": {"bar": null}}', 'raises': ValidationError( "None requires presence of property 'foo' in the same" " object", "Enclosing object does not have property 'foo'"), 'object_expr': 'object.nested.bar', 'schema_expr': 'schema.properties.nested.properties.bar.requires', }), ("requires_with_schema_can_report_problems", { 'schema': """ { "properties": { "foo": { "optional": true }, "bar": { "requires": { "properties": { "foo": { "type": "number" } } }, "optional": true } } } """, 'data': '{"bar": null}', 'raises': ValidationError( "{'bar': None} does not have property 'foo'", "Object lacks property 'foo'"), 'object_expr': 'object', 'schema_expr': 'schema.properties.bar.requires.properties.foo.optional', }), ("requires_with_schema_can_report_subtle_problems", { # In this test presence of "bar" requires that "foo" is # present and has a type "number" 'schema': """ { "properties": { "foo": { "optional": true }, "bar": { "requires": { "properties": { "foo": { "type": "number" } } }, "optional": true } } } """, 'data': '{"bar": null, "foo": "not a number"}', 'raises': ValidationError( "'not a number' does not match type 'number'", "Object has incorrect type (expected number)"), 'object_expr': 'object.foo', 'schema_expr': 'schema.properties.bar.requires.properties.foo.type' }), ("format_date_time_finds_problems", { 'schema': '{"format": "date-time"}', 'data': '"broken"', 'raises': ValidationError( "'broken' is not a string representing JSON date-time", "Object is not a string representing JSON date-time"), 'object_expr': 'object', 'schema_expr': 'schema.format' }), ] def test_validation_error_has_proper_message(self): ex = self.assertRaises(ValidationError, validate, self.schema, self.data) self.assertEqual(ex.message, self.raises.message) def test_validation_error_has_proper_new_message(self): ex = self.assertRaises(ValidationError, validate, self.schema, self.data) self.assertEqual(ex.new_message, self.raises.new_message) def test_validation_error_has_proper_object_expr(self): ex = self.assertRaises(ValidationError, validate, self.schema, self.data) self.assertEqual(ex.object_expr, self.object_expr) def test_validation_error_has_proper_schema_expr(self): ex = self.assertRaises(ValidationError, validate, self.schema, self.data) self.assertEqual(ex.schema_expr, self.schema_expr) class ValidatorSuccessTests(TestWithScenarios, TestCase): scenarios = [ ("type_string_got_string", { 'schema': '{"type": "string"}', 'data': '"foobar"' }), ("type_number_got_integer", { 'schema': '{"type": "number"}', 'data': '1', }), ("type_number_number_float", { 'schema': '{"type": "number"}', 'data': '1.1', }), ("type_integer_got_integer_one", { 'schema': '{"type": "integer"}', 'data': '1' }), ("type_integer_got_integer", { 'schema': '{"type": "integer"}', 'data': '5' }), ("type_boolean_got_true", { 'schema': '{"type": "boolean"}', 'data': 'true', }), ("type_boolean_got_false", { 'schema': '{"type": "boolean"}', 'data': 'true', }), ("type_object_got_object", { 'schema': '{"type": "object"}', 'data': '{}' }), ("type_array_got_array", { 'schema': '{"type": "array"}', 'data': '[]' }), ("type_null_got_null", { 'schema': '{"type": "null"}', 'data': 'null', }), ("type_any_got_null", { 'schema': '{"type": "any"}', 'data': 'null', }), ("type_any_got_integer", { 'schema': '{"type": "any"}', 'data': '5', }), ("type_any_got_boolean", { 'schema': '{"type": "any"}', 'data': 'false', }), ("type_any_got_string", { 'schema': '{"type": "any"}', 'data': '"foobar"', }), ("type_any_got_array", { 'schema': '{"type": "any"}', 'data': '[]', }), ("type_any_got_object", { 'schema': '{"type": "any"}', 'data': '{}', }), ("type_nested_schema_check", { 'schema': '{"type": {"type": "number"}}', 'data': '5', }), ("type_list_with_two_values_got_first_value", { 'schema': '{"type": ["number", "string"]}', 'data': '1', }), ("type_list_with_two_values_got_second_value", { 'schema': '{"type": ["number", "string"]}', 'data': '"string"', }), ("property_ignored_on_non_objects", { 'schema': '{"properties": {"foo": {"type": "number"}}}', 'data': '"foobar"', }), ("property_checks_known_props", { 'schema': """ { "type": "object", "properties": { "foo": { "type": "number" }, "bar": { "type": "boolean" } } }""", 'data': """ { "foo": 5, "bar": false }""" }), ("property_check_ignores_missing_optional_properties", { 'schema': """ { "type": "object", "properties": { "foo": { "type": "number", "optional": true } } }""", 'data': '{}', }), ("property_check_ignores_normal_properties_when_additionalProperties_is_false", { 'schema': """ { "type": "object", "properties": { "foo": {} }, "additionalProperties": false }""", 'data': '{"foo": 5}', }), ("property_check_validates_additional_properties_using_specified_type_when_additionalProperties_is_an_object", { 'schema': """ { "type": "object", "additionalProperties": { "type": "string" } }""", 'data': '{"foo": "aaa", "bar": "bbb"}', }), ("enum_check_does_nothing_by_default", { 'schema': '{}', 'data': '5', }), ("enum_check_verifies_possible_values", { 'schema': '{"enum": [1, 2, 3]}', 'data': '2', }), ("items_check_does_nothing_for_non_arrays", { 'schema': '{"items": {"type": "string"}}', 'data': '5', }), ("items_with_single_schema_applies_to_each_item", { 'schema': '{"items": {"type": "string"}}', 'data': '["foo", "bar", "froz"]', }), ("items_with_array_schema_applies_to_corresponding_items", { 'schema': """ { "items": [ {"type": "string"}, {"type": "boolean"} ] }""", 'data': '["foo", true]', }), ("items_with_array_schema_and_additionalProperties", { 'schema': """ { "items": [ {"type": "string"}, {"type": "boolean"} ], "additionalProperties": { "type": "number" } }""", 'data': '["foo", false, 5, 7.9]', }), ("requires_with_simple_property_name_does_nothing_when_parent_property_is_not_used", { 'schema': """ { "properties": { "foo": { "optional": true }, "bar": { "requires": "foo", "optional": true } } } """, 'data': '{}', }), ("requires_with_simple_property_name_works_when_condition_satisfied", { 'schema': """ { "properties": { "foo": { "optional": true }, "bar": { "requires": "foo", "optional": true } } } """, 'data': '{"foo": null, "bar": null}', }), ("requires_with_schema_name_does_nothing_when_parent_property_is_not_used", { 'schema': """ { "properties": { "foo": { "optional": true }, "bar": { "requires": { "properties": { "foo": { "type": "number" } } }, "optional": true } } } """, 'data': '{}', }), ("format_date_time_works", { 'schema': '{"format": "date-time"}', 'data': '"2010-11-12T14:38:55Z"', }), ("array_with_array_schema_and_uniqueItems_is_True", { 'schema': """ { "type": "array", "items": {"type": "string"}, "uniqueItems": true }""", 'data': '["foo", "bar", "baz"]', }), ] def test_validator_does_not_raise_an_exception(self): self.assertEqual( True, validate(self.schema, self.data)) json-schema-validator-2.3.1/json_schema_validator/tests/__init__.py0000664000175000017500000000355712321761401025477 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Package with unit tests for json-schema-validator """ import doctest import unittest def app_modules(): return [ 'json_schema_validator', 'json_schema_validator.errors', 'json_schema_validator.extensions', 'json_schema_validator.misc', 'json_schema_validator.schema', 'json_schema_validator.shortcuts', 'json_schema_validator.validator', ] def test_modules(): return [ 'json_schema_validator.tests.test_extensions', 'json_schema_validator.tests.test_schema', 'json_schema_validator.tests.test_validator', ] def test_suite(): """ Build an unittest.TestSuite() object with all the tests in _modules. Each module is harvested for both regular unittests and doctests """ modules = app_modules() + test_modules() suite = unittest.TestSuite() loader = unittest.TestLoader() for name in modules: __import__(name, fromlist=['']) tests = loader.loadTestsFromName(name) suite.addTests(tests) doctests = doctest.DocTestSuite(name) suite.addTests(doctests) return suite json-schema-validator-2.3.1/json_schema_validator/tests/test_schema.py0000664000175000017500000006015712321761401026236 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Unit tests for JSON schema """ import simplejson from testscenarios import TestWithScenarios from testtools import TestCase from json_schema_validator.errors import SchemaError from json_schema_validator.schema import Schema class SchemaTests(TestWithScenarios, TestCase): scenarios = [ ('type_default', { 'schema': '{}', 'expected': { 'type': 'any' }, }), ('type_string', { 'schema': '{"type": "string"}', 'expected': { 'type': 'string' }, }), ('type_number', { 'schema': '{"type": "number"}', 'expected': { 'type': 'number' }, }), ('type_integer', { 'schema': '{"type": "integer"}', 'expected': { 'type': 'integer' }, }), ('type_boolean', { 'schema': '{"type": "boolean"}', 'expected': { 'type': 'boolean' }, }), ('type_object', { 'schema': '{"type": "object"}', 'expected': { 'type': 'object' }, }), ('type_array', { 'schema': '{"type": "array"}', 'expected': { 'type': 'array' }, }), ('type_complex_subtype', { 'schema': '{"type": {}}', 'expected': { 'type': {}, }, }), ("type_empty_list", { 'schema': '{"type": []}', 'access': 'type', 'raises': SchemaError("union type [] is too short") }), ("type_list_with_one_item", { 'schema': '{"type": ["number"]}', 'access': 'type', 'raises': SchemaError("union type ['number'] is too short") }), ('type_list', { 'schema': '{"type": ["string", "number"]}', 'expected': { 'type': ["string", "number"], }, }), ('type_wrong_type', { 'schema': '{"type": 5}', 'access': 'type', 'raises': SchemaError( "type value 5 is not a simple type name," " nested schema nor a list of those"), }), ('type_not_a_simple_type_name', { 'schema': '{"type": "foobar"}', 'access': 'type', 'raises': SchemaError( "type value 'foobar' is not a simple type name"), }), ('type_list_duplicates', { 'schema': '{"type": ["string", "string"]}', 'access': 'type', 'raises': SchemaError( "type value ['string', 'string'] contains duplicate" " element 'string'") }), ('properties_default', { 'schema': '{}', 'expected': { 'properties': {}, }, }), ('properties_example', { 'schema': '{"properties": {"prop": {"type": "number"}}}', 'expected': { 'properties': {"prop": {"type": "number"}}, }, }), ('properties_wrong_type', { 'schema': '{"properties": 5}', 'access': 'properties', 'raises': SchemaError( 'properties value 5 is not an object'), }), ('items_default', { 'schema': '{}', 'expected': { 'items': {}, }, }), ('items_tuple', { 'schema': '{"items": [{}, {}]}', 'expected': { 'items': [{}, {}], }, }), ('items_each', { 'schema': '{"items": {"type": "number"}}', 'expected': { 'items': {"type": "number"}, }, }), ('items_wrong_type', { 'schema': '{"items": 5}', 'access': 'items', 'raises': SchemaError( 'items value 5 is neither a list nor an object'), }), ('optional_default', { 'schema': '{}', 'expected': { 'optional': False, }, }), ('optional_true', { 'schema': '{"optional": true}', 'expected': { 'optional': True, }, }), ('optional_false', { 'schema': '{"optional": false}', 'expected': { 'optional': False, }, }), ('optional_wrong_type', { 'schema': '{"optional": 5}', 'access': 'optional', 'raises': SchemaError( 'optional value 5 is not a boolean'), }), ('additionalProperties_default', { 'schema': '{}', 'expected': { 'additionalProperties': {} }, }), ('additionalProperties_false', { 'schema': '{"additionalProperties": false}', 'expected': { "additionalProperties": False, }, }), ('additionalProperties_object', { 'schema': '{"additionalProperties": {"type": "number"}}', 'expected': { "additionalProperties": {"type": "number"}, }, }), ('additionalProperties_wrong_type', { 'schema': '{"additionalProperties": 5}', 'access': 'additionalProperties', 'raises': SchemaError( 'additionalProperties value 5 is neither false nor an' ' object'), }), ('requires_default', { 'schema': '{}', 'expected': { 'requires': {}, }, }), ('requires_property_name', { 'schema': '{"requires": "other"}', 'expected': { 'requires': "other", }, }), ('requires_schema', { 'schema': '{"requires": {"properties": {"other": {"type": "number"}}}}', 'expected': { 'requires': { 'properties': { 'other': { 'type': 'number' }, }, }, }, }), ('requires_wrong_value', { 'schema': '{"requires": 5}', 'access': 'requires', 'raises': SchemaError( 'requires value 5 is neither a string nor an object'), }), ('minimum_default', { 'schema': '{}', 'expected': { 'minimum': None }, }), ('minimum_integer', { 'schema': '{"minimum": 5}', 'expected': { 'minimum': 5 }, }), ('minimum_float', { 'schema': '{"minimum": 3.5}', 'expected': { 'minimum': 3.5 }, }), ('minimum_wrong_type', { 'schema': '{"minimum": "foobar"}', 'access': 'minimum', 'raises': SchemaError( 'minimum value \'foobar\' is not a numeric type') }), ('maximum_default', { 'schema': '{}', 'expected': { 'maximum': None }, }), ('maximum_integer', { 'schema': '{"maximum": 5}', 'expected': { 'maximum': 5 }, }), ('maximum_float', { 'schema': '{"maximum": 3.5}', 'expected': { 'maximum': 3.5 }, }), ('maximum_wrong_type', { 'schema': '{"maximum": "foobar"}', 'access': 'maximum', 'raises': SchemaError( 'maximum value \'foobar\' is not a numeric type') }), ('minimumCanEqual_default', { 'schema': '{"minimum": 5}', 'expected': { 'minimum': 5, 'minimumCanEqual': True }, }), ('minimumCanEqual_false', { 'schema': '{"minimum": 5, "minimumCanEqual": false}', 'expected': { 'minimum': 5, 'minimumCanEqual': False, }, }), ('minimumCanEqual_true', { 'schema': '{"minimum": 5, "minimumCanEqual": true}', 'expected': { 'minimum': 5, 'minimumCanEqual': True }, }), ('minimumCanEqual_without_minimum', { 'schema': '{}', 'access': 'minimumCanEqual', 'raises': SchemaError( "minimumCanEqual requires presence of minimum"), }), ('minimumCanEqual_wrong_type', { 'schema': '{"minimum": 5, "minimumCanEqual": 5}', 'access': 'minimumCanEqual', 'raises': SchemaError( "minimumCanEqual value 5 is not a boolean"), }), ('maximumCanEqual_default', { 'schema': '{"maximum": 5}', 'expected': { 'maximum': 5, 'maximumCanEqual': True }, }), ('maximumCanEqual_false', { 'schema': '{"maximum": 5, "maximumCanEqual": false}', 'expected': { 'maximum': 5, 'maximumCanEqual': False, }, }), ('maximumCanEqual_true', { 'schema': '{"maximum": 5, "maximumCanEqual": true}', 'expected': { 'maximum': 5, 'maximumCanEqual': True }, }), ('maximumCanEqual_without_maximum', { 'schema': '{}', 'access': 'maximumCanEqual', 'raises': SchemaError( "maximumCanEqual requires presence of maximum"), }), ('maximumCanEqual_wrong_type', { 'schema': '{"maximum": 5, "maximumCanEqual": 5}', 'access': 'maximumCanEqual', 'raises': SchemaError( "maximumCanEqual value 5 is not a boolean"), }), ("minItems_default", { 'schema': '{}', 'expected': { 'minItems': 0, }, }), ("minItems_integer", { 'schema': '{"minItems": 13}', 'expected': { 'minItems': 13, }, }), ("minItems_zero", { 'schema': '{"minItems": 0}', 'expected': { 'minItems': 0, }, }), ("minItems_minus_one", { 'schema': '{"minItems": -1}', 'access': 'minItems', 'raises': SchemaError( "minItems value -1 cannot be negative"), }), ("minItems_wrong_type", { 'schema': '{"minItems": "foobar"}', 'access': 'minItems', 'raises': SchemaError( "minItems value 'foobar' is not an integer"), }), ("maxItems_default", { 'schema': '{}', 'expected': { 'maxItems': None, }, }), ("maxItems_integer", { 'schema': '{"maxItems": 13}', 'expected': { 'maxItems': 13, }, }), ("maxItems_zero", { 'schema': '{"maxItems": 0}', 'expected': { 'maxItems': 0, }, }), ("maxItems_minus_one", { 'schema': '{"maxItems": -1}', 'expected': { 'maxItems': -1 }, }), ("maxItems_wrong_type", { 'schema': '{"maxItems": "foobar"}', 'access': 'maxItems', 'raises': SchemaError( "maxItems value 'foobar' is not an integer"), }), ("uniqueItems_default", { 'schema': '{}', 'expected': { 'uniqueItems': False } }), ("uniqueItems_true", { 'schema': '{"uniqueItems": true}', 'expected': { 'uniqueItems': True } }), ("uniqueItems_false", { 'schema': '{"uniqueItems": false}', 'expected': { 'uniqueItems': False } }), ("uniqueItems_wrong_type", { 'schema': '{"uniqueItems": 5}', 'access': 'uniqueItems', 'raises': SchemaError( "uniqueItems value 5 is not a boolean") }), ("pattern_default", { 'schema': '{}', 'expected': { 'pattern': None, }, }), #("pattern_simple", { # 'schema': '{"pattern": "foo|bar"}', # 'expected': { # 'pattern': re.compile('foo|bar'), # }, #}), ("pattern_broken", { 'schema': '{"pattern": "[unterminated"}', 'access': 'pattern', 'raises': SchemaError( "pattern value '[unterminated' is not a valid regular" " expression: unexpected end of regular expression"), }), ("minLength_default", { 'schema': '{}', 'expected': { 'minLength': 0, }, }), ("minLength_integer", { 'schema': '{"minLength": 13}', 'expected': { 'minLength': 13, }, }), ("minLength_zero", { 'schema': '{"minLength": 0}', 'expected': { 'minLength': 0, }, }), ("minLength_minus_one", { 'schema': '{"minLength": -1}', 'access': 'minLength', 'raises': SchemaError( "minLength value -1 cannot be negative"), }), ("minLength_wrong_type", { 'schema': '{"minLength": "foobar"}', 'access': 'minLength', 'raises': SchemaError( "minLength value 'foobar' is not an integer"), }), ("maxLength_default", { 'schema': '{}', 'expected': { 'maxLength': None, }, }), ("maxLength_integer", { 'schema': '{"maxLength": 13}', 'expected': { 'maxLength': 13, }, }), ("maxLength_zero", { 'schema': '{"maxLength": 0}', 'expected': { 'maxLength': 0, }, }), ("maxLength_minus_one", { 'schema': '{"maxLength": -1}', 'expected': { 'maxLength': -1 }, }), ("maxLength_wrong_type", { 'schema': '{"maxLength": "foobar"}', 'access': 'maxLength', 'raises': SchemaError( "maxLength value 'foobar' is not an integer"), }), ("enum_default", { 'schema': '{}', 'expected': { 'enum': None, } }), ("enum_simple", { 'schema': '{"enum": ["foo", "bar"]}', 'expected': { 'enum': ["foo", "bar"], } }), ("enum_mixed", { 'schema': '{"enum": [5, false, "foobar"]}', 'expected': { 'enum':[5, False, "foobar"] } }), ("enum_wrong_type", { 'schema': '{"enum": "foobar"}', 'access': 'enum', 'raises': SchemaError( "enum value 'foobar' is not a list"), }), ("enum_too_short", { 'schema': '{"enum": []}', 'access': 'enum', 'raises': SchemaError( "enum value [] does not contain any elements"), }), ("enum_duplicates", { 'schema': '{"enum": ["foo", "foo"]}', 'access': 'enum', 'raises': SchemaError( "enum value ['foo', 'foo'] contains duplicate element" " 'foo'"), }), ("title_default", { 'schema': '{}', 'expected': { 'title': None, }, }), ("title_simple", { 'schema': '{"title": "foobar"}', 'expected': { 'title': "foobar", }, }), ("title_wrong_type", { 'schema': '{"title": 5}', 'access': 'title', 'raises': SchemaError('title value 5 is not a string') }), ("description_default", { 'schema': '{}', 'expected': { 'description': None, }, }), ("description_simple", { 'schema': '{"description": "foobar"}', 'expected': { 'description': "foobar", }, }), ("description_wrong_type", { 'schema': '{"description": 5}', 'access': 'description', 'raises': SchemaError('description value 5 is not a string') }), ("format_default", { 'schema': '{}', 'expected': { 'format': None }, }), ("format_date_time", { 'schema': '{"format": "date-time"}', 'expected': { 'format': "date-time" }, }), ("format_regex", { 'schema': '{"format": "regex"}', 'expected': { 'format': "regex" }, }), ("format_wrong_type", { 'schema': '{"format": 5}', 'access': 'format', 'raises': SchemaError('format value 5 is not a string') }), ("format_not_implemented", { 'schema': '{"format": "color"}', 'access': 'format', 'raises': NotImplementedError( "format value 'color' is not supported") }), ("contentEncoding_default", { 'schema': '{}', 'expected': { 'contentEncoding': None, } }), ("contentEncoding_base64", { 'schema': '{"contentEncoding": "base64"}', 'expected': { 'contentEncoding': "base64", }, }), ("contentEncoding_base64_mixed_case", { 'schema': '{"contentEncoding": "BAsE64"}', 'expected': { 'contentEncoding': 'BAsE64', }, }), ("contentEncoding_unsupported_value", { 'schema': '{"contentEncoding": "x-token"}', 'access': 'contentEncoding', 'raises': NotImplementedError( "contentEncoding value 'x-token' is not supported") }), ("contentEncoding_unknown_value", { 'schema': '{"contentEncoding": "bogus"}', 'access': 'contentEncoding', 'raises': SchemaError( "contentEncoding value 'bogus' is not valid") }), ("divisibleBy_default", { 'schema': '{}', 'expected': { 'divisibleBy': 1 } }), ("divisibleBy_int", { 'schema': '{"divisibleBy": 5}', 'expected': { 'divisibleBy': 5 } }), ("divisibleBy_float", { 'schema': '{"divisibleBy": 3.5}', 'expected': { 'divisibleBy': 3.5 } }), ("divisibleBy_wrong_type", { 'schema': '{"divisibleBy": "foobar"}', 'access': 'divisibleBy', 'raises': SchemaError( "divisibleBy value 'foobar' is not a numeric type") }), ("divisibleBy_minus_one", { 'schema': '{"divisibleBy": -1}', 'access': 'divisibleBy', 'raises': SchemaError( "divisibleBy value -1 cannot be negative") }), ('disallow_default', { 'schema': '{}', 'expected': { 'disallow': None }, }), ('disallow_string', { 'schema': '{"disallow": "string"}', 'expected': { 'disallow': ['string'] }, }), ('disallow_number', { 'schema': '{"disallow": "number"}', 'expected': { 'disallow': ['number'] }, }), ('disallow_integer', { 'schema': '{"disallow": "integer"}', 'expected': { 'disallow': ['integer'] }, }), ('disallow_boolean', { 'schema': '{"disallow": "boolean"}', 'expected': { 'disallow': ['boolean'] }, }), ('disallow_object', { 'schema': '{"disallow": "object"}', 'expected': { 'disallow': ['object'] }, }), ('disallow_array', { 'schema': '{"disallow": "array"}', 'expected': { 'disallow': ['array'] }, }), ('disallow_complex_subtype', { 'schema': '{"disallow": {}}', 'expected': { 'disallow': [{}], }, }), ('disallow_list', { 'schema': '{"disallow": ["string", "number"]}', 'expected': { 'disallow': ["string", "number"], }, }), ('disallow_wrong_type', { 'schema': '{"disallow": 5}', 'access': 'disallow', 'raises': SchemaError( "disallow value 5 is not a simple type name," " nested schema nor a list of those"), }), ('disallow_not_a_simple_disallow_name', { 'schema': '{"disallow": "foobar"}', 'access': 'disallow', 'raises': SchemaError( "disallow value 'foobar' is not a simple type name") }), ('disallow_list_duplicates', { 'schema': '{"disallow": ["string", "string"]}', 'access': 'disallow', 'raises': SchemaError( "disallow value ['string', 'string'] contains" " duplicate element 'string'") }), ('extends_not_supported', { 'schema': '{}', 'access': 'extends', 'raises': NotImplementedError( "extends property is not supported"), }), ('default_with_value', { 'schema': '{"default": 5}', 'expected': { 'default': 5 } }), ('default_without_value', { 'schema': '{}', 'access': 'default', 'raises': SchemaError("There is no schema default for this item"), }), ] def test_schema_attribute(self): schema = Schema(simplejson.loads(self.schema)) if hasattr(self, 'expected'): for attr, expected_value in self.expected.iteritems(): self.assertEqual( expected_value, getattr(schema, attr)) elif hasattr(self, 'access') and hasattr(self, 'raises'): self.assertRaises( type(self.raises), getattr, schema, self.access) try: getattr(schema, self.access) except type(self.raises) as ex: self.assertEqual(str(ex), str(self.raises)) except Exception as ex: self.fail("Raised exception {0!r} instead of {1!r}".format( ex, self.raises)) else: self.fail("Broken test definition, must define 'expected' " "or 'access' and 'raises' scenario attributes") json-schema-validator-2.3.1/json_schema_validator/tests/test_extensions.py0000664000175000017500000000317212321761401027167 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Unit tests for JSON extensions """ from testtools import TestCase from datetime import datetime, timedelta from json_schema_validator.extensions import datetime_extension, timedelta_extension class ExtensionTests(object): def test_to_json(self): text = self.extension.to_json(self.reference_obj) self.assertEqual(text, self.reference_text) def test_from_json(self): obj = self.extension.from_json(self.reference_text) self.assertEqual(obj, self.reference_obj) class DatetimeExtensionTests(TestCase, ExtensionTests): reference_obj = datetime(2010, 12, 7, 23, 59, 58) reference_text = "2010-12-07T23:59:58Z" extension = datetime_extension class TimedeltaExtensionTests(TestCase, ExtensionTests): reference_obj = timedelta(days=1, seconds=2, microseconds=3) reference_text = "1d 2s 3us" extension = timedelta_extension json-schema-validator-2.3.1/json_schema_validator/schema.py0000664000175000017500000003235712321761401024036 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Helper module to work with raw JSON Schema """ import re from json_schema_validator.errors import SchemaError from json_schema_validator.misc import NUMERIC_TYPES class Schema(object): """ JSON schema object """ def __init__(self, json_obj): """ Initialize schema with JSON object .. note:: JSON objects are just plain python dictionaries """ if not isinstance(json_obj, dict): raise SchemaError("Schema definition must be a JSON object") self._schema = json_obj def __repr__(self): return "Schema({0!r})".format(self._schema) @property def type(self): """ Return the 'type' property of this schema. The return value is always a list of correct JSON types. Correct JSON types are one of the pre-defined simple types or another schema object. List of built-in simple types: * 'string' * 'number' * 'integer' * 'boolean' * 'object' * 'array' * 'any' (default) """ value = self._schema.get("type", "any") if not isinstance(value, (basestring, dict, list)): raise SchemaError( "type value {0!r} is not a simple type name, nested " "schema nor a list of those".format(value)) if isinstance(value, list): type_list = value # Union types have to have at least two alternatives if len(type_list) < 2: raise SchemaError( "union type {0!r} is too short".format(value)) else: type_list = [value] seen = set() for js_type in type_list: if isinstance(js_type, dict): # no nested validation here pass elif isinstance(js_type, list): # no nested validation here pass else: if js_type in seen: raise SchemaError( ("type value {0!r} contains duplicate element" " {1!r}").format(value, js_type)) else: seen.add(js_type) if js_type not in ( "string", "number", "integer", "boolean", "object", "array", "null", "any"): raise SchemaError( "type value {0!r} is not a simple type " "name".format(js_type)) return value @property def properties(self): """ The properties property contains schema for each property in a dictionary. The dictionary name is the property name. The dictionary value is the schema object itself. """ value = self._schema.get("properties", {}) if not isinstance(value, dict): raise SchemaError( "properties value {0!r} is not an object".format(value)) return value @property def items(self): value = self._schema.get("items", {}) if not isinstance(value, (list, dict)): raise SchemaError( "items value {0!r} is neither a list nor an object". format(value)) return value @property def optional(self): value = self._schema.get("optional", False) if value is not False and value is not True: raise SchemaError( "optional value {0!r} is not a boolean".format(value)) return value @property def additionalProperties(self): value = self._schema.get("additionalProperties", {}) if not isinstance(value, dict) and value is not False: raise SchemaError( "additionalProperties value {0!r} is neither false nor" " an object".format(value)) return value @property def requires(self): value = self._schema.get("requires", {}) if not isinstance(value, (basestring, dict)): raise SchemaError( "requires value {0!r} is neither a string nor an" " object".format(value)) return value @property def minimum(self): value = self._schema.get("minimum", None) if value is None: return if not isinstance(value, NUMERIC_TYPES): raise SchemaError( "minimum value {0!r} is not a numeric type".format( value)) return value @property def maximum(self): value = self._schema.get("maximum", None) if value is None: return if not isinstance(value, NUMERIC_TYPES): raise SchemaError( "maximum value {0!r} is not a numeric type".format( value)) return value @property def minimumCanEqual(self): if self.minimum is None: raise SchemaError("minimumCanEqual requires presence of minimum") value = self._schema.get("minimumCanEqual", True) if value is not True and value is not False: raise SchemaError( "minimumCanEqual value {0!r} is not a boolean".format( value)) return value @property def maximumCanEqual(self): if self.maximum is None: raise SchemaError("maximumCanEqual requires presence of maximum") value = self._schema.get("maximumCanEqual", True) if value is not True and value is not False: raise SchemaError( "maximumCanEqual value {0!r} is not a boolean".format( value)) return value @property def minItems(self): value = self._schema.get("minItems", 0) if not isinstance(value, int): raise SchemaError( "minItems value {0!r} is not an integer".format(value)) if value < 0: raise SchemaError( "minItems value {0!r} cannot be negative".format(value)) return value @property def maxItems(self): value = self._schema.get("maxItems", None) if value is None: return if not isinstance(value, int): raise SchemaError( "maxItems value {0!r} is not an integer".format(value)) return value @property def uniqueItems(self): value = self._schema.get("uniqueItems", False) if value is not True and value is not False: raise SchemaError( "uniqueItems value {0!r} is not a boolean".format(value)) return value @property def pattern(self): """ .. note:: JSON schema specifications says that this value SHOULD follow the ``EMCA 262/Perl 5`` format. We cannot support this so we support python regular expressions instead. This is still valid but should be noted for clarity. :returns None or compiled regular expression """ value = self._schema.get("pattern", None) if value is None: return try: return re.compile(value) except re.error as ex: raise SchemaError( "pattern value {0!r} is not a valid regular expression:" " {1}".format(value, str(ex))) @property def minLength(self): value = self._schema.get("minLength", 0) if not isinstance(value, int): raise SchemaError( "minLength value {0!r} is not an integer".format(value)) if value < 0: raise SchemaError( "minLength value {0!r} cannot be negative".format(value)) return value @property def maxLength(self): value = self._schema.get("maxLength", None) if value is None: return if not isinstance(value, int): raise SchemaError( "maxLength value {0!r} is not an integer".format(value)) return value @property def enum(self): """ Enumeration of possible correct values. *Must* be either ``None`` or a non-empty list of valid objects. The list *must not* contain duplicate elements. """ value = self._schema.get("enum", None) if value is None: return if not isinstance(value, list): raise SchemaError( "enum value {0!r} is not a list".format(value)) if len(value) == 0: raise SchemaError( "enum value {0!r} does not contain any" " elements".format(value)) seen = set() for item in value: if item in seen: raise SchemaError( "enum value {0!r} contains duplicate element" " {1!r}".format(value, item)) else: seen.add(item) return value @property def title(self): value = self._schema.get("title", None) if value is None: return if not isinstance(value, basestring): raise SchemaError( "title value {0!r} is not a string".format(value)) return value @property def description(self): value = self._schema.get("description", None) if value is None: return if not isinstance(value, basestring): raise SchemaError( "description value {0!r} is not a string".format(value)) return value @property def format(self): value = self._schema.get("format", None) if value is None: return if not isinstance(value, basestring): raise SchemaError( "format value {0!r} is not a string".format(value)) if value in [ 'date-time', 'regex', ]: return value raise NotImplementedError( "format value {0!r} is not supported".format(value)) @property def contentEncoding(self): value = self._schema.get("contentEncoding", None) if value is None: return if value.lower() not in [ "7bit", "8bit", "binary", "quoted-printable", "base64", "ietf-token", "x-token"]: raise SchemaError( "contentEncoding value {0!r} is not" " valid".format(value)) if value.lower() != "base64": raise NotImplementedError( "contentEncoding value {0!r} is not supported".format( value)) return value @property def divisibleBy(self): value = self._schema.get("divisibleBy", 1) if value is None: return if not isinstance(value, NUMERIC_TYPES): raise SchemaError( "divisibleBy value {0!r} is not a numeric type". format(value)) if value < 0: raise SchemaError( "divisibleBy value {0!r} cannot be" " negative".format(value)) return value @property def disallow(self): value = self._schema.get("disallow", None) if value is None: return if not isinstance(value, (basestring, dict, list)): raise SchemaError( "disallow value {0!r} is not a simple type name, nested " "schema nor a list of those".format(value)) if isinstance(value, list): disallow_list = value else: disallow_list = [value] seen = set() for js_disallow in disallow_list: if isinstance(js_disallow, dict): # no nested validation here pass else: if js_disallow in seen: raise SchemaError( "disallow value {0!r} contains duplicate element" " {1!r}".format(value, js_disallow)) else: seen.add(js_disallow) if js_disallow not in ( "string", "number", "integer", "boolean", "object", "array", "null", "any"): raise SchemaError( "disallow value {0!r} is not a simple type" " name".format(js_disallow)) return disallow_list @property def extends(self): raise NotImplementedError("extends property is not supported") @property def default(self): try: return self._schema["default"] except KeyError: raise SchemaError("There is no schema default for this item") json-schema-validator-2.3.1/json_schema_validator/__init__.py0000664000175000017500000000147512321763023024334 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ JSON Schema Validator """ __version__ = (2, 3, 1, "final", 0) json-schema-validator-2.3.1/json_schema_validator/errors.py0000664000175000017500000000422612321761401024104 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Error classes used by this package """ class SchemaError(ValueError): """ An exception raised when there is a problem with the schema itself. """ class ValidationError(ValueError): """ An exception raised when validator finds mismatch between the validated object and the schema. :ivar message: Old and verbose message that contains less helpful message and lots of JSON data (deprecated). :ivar new_message: short and concise message about the problem :ivar object_expr: A JavaScript expression that evaluates to the object that failed to validate. The expression always starts with a root object called ``'object'``. :ivar schema_expr: A JavaScript expression that evaluates to the schema that was checked at the time validation failed. The expression always starts with a root object called ``'schema'``. """ def __init__(self, message, new_message=None, object_expr=None, schema_expr=None): self.message = message self.new_message = new_message self.object_expr = object_expr self.schema_expr = schema_expr def __str__(self): return ("ValidationError: {0} " "object_expr={1!r}, " "schema_expr={2!r})").format( self.new_message, self.object_expr, self.schema_expr) json-schema-validator-2.3.1/json_schema_validator/validator.py0000664000175000017500000005123312321761650024563 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Validator implementation """ import re import datetime import itertools import types from json_schema_validator.errors import ValidationError from json_schema_validator.misc import NUMERIC_TYPES from json_schema_validator.schema import Schema class Validator(object): """ JSON Schema validator. Can be used to validate any JSON document against a :class:`json_schema_validator.schema.Schema`. """ JSON_TYPE_MAP = { "string": basestring, "number": NUMERIC_TYPES, "integer": int, "object": dict, "array": list, "null": types.NoneType, } def __init__(self): self._schema_stack = [] self._object_stack = [] def _push_object(self, obj, path): self._object_stack.append((obj, path)) def _pop_object(self): self._object_stack.pop() def _push_schema(self, schema, path): self._schema_stack.append((schema, path)) def _pop_schema(self): self._schema_stack.pop() @property def _object(self): return self._object_stack[-1][0] @property def _schema(self): return self._schema_stack[-1][0] @classmethod def validate(cls, schema, obj): """ Validate specified JSON object obj with specified Schema instance schema. :param schema: Schema to validate against :type schema: :class:`json_schema_validator.schema.Schema` :param obj: JSON object to validate :rtype: bool :returns: True on success :raises `json_schema_validator.errors.ValidationError`: if the object does not match schema. :raises `json_schema_validator.errors.SchemaError`: if the schema itself is wrong. """ if not isinstance(schema, Schema): raise ValueError( "schema value {0!r} is not a Schema" " object".format(schema)) self = cls() self.validate_toplevel(schema, obj) return True def _get_object_expression(self): return "".join(map(lambda x: x[1], self._object_stack)) def _get_schema_expression(self): return "".join(map(lambda x: x[1], self._schema_stack)) def validate_toplevel(self, schema, obj): self._object_stack = [] self._schema_stack = [] self._push_schema(schema, "schema") self._push_object(obj, "object") self._validate() self._pop_schema() self._pop_object() def _validate(self): obj = self._object self._validate_type() self._validate_requires() if isinstance(obj, dict): self._validate_properties() self._validate_additional_properties() elif isinstance(obj, list): self._validate_items() else: self._validate_enum() self._validate_format() self._validate_pattern() if isinstance(obj, basestring): self._validate_length() elif isinstance(obj, NUMERIC_TYPES): self._validate_range() self._report_unsupported() def _report_error(self, legacy_message, new_message=None, schema_suffix=None): """ Report an error during validation. There are two error messages. The legacy message is used for backwards compatibility and usually contains the object (possibly very large) that failed to validate. The new message is much better as it contains just a short message on what went wrong. User code can inspect object_expr and schema_expr to see which part of the object failed to validate against which part of the schema. The schema_suffix, if provided, is appended to the schema_expr. This is quite handy to specify the bit that the validator looked at (such as the type or optional flag, etc). object_suffix serves the same purpose but is used for object expressions instead. """ object_expr = self._get_object_expression() schema_expr = self._get_schema_expression() if schema_suffix: schema_expr += schema_suffix raise ValidationError(legacy_message, new_message, object_expr, schema_expr) def _push_property_schema(self, prop): """ Construct a sub-schema from the value of the specified attribute of the current schema. """ schema = Schema(self._schema.properties[prop]) self._push_schema(schema, ".properties." + prop) def _push_additional_property_schema(self): schema = Schema(self._schema.additionalProperties) self._push_schema(schema, ".additionalProperties") def _push_array_schema(self): schema = Schema(self._schema.items) self._push_schema(schema, ".items") def _push_array_item_object(self, index): self._push_object(self._object[index], "[%d]" % index) def _push_property_object(self, prop): self._push_object(self._object[prop], "." + prop) def _report_unsupported(self): schema = self._schema if schema.contentEncoding is not None: raise NotImplementedError("contentEncoding is not supported") if schema.divisibleBy != 1: raise NotImplementedError("divisibleBy is not supported") if schema.disallow is not None: raise NotImplementedError("disallow is not supported") def _validate_type(self): schema = self._schema json_type = schema.type if json_type == "any": return obj = self._object if json_type == "boolean": # Bool is special cased because in python there is no # way to test for isinstance(something, bool) that would # not catch isinstance(1, bool) :/ if obj is not True and obj is not False: self._report_error( "{obj!r} does not match type {type!r}".format( obj=obj, type=json_type), "Object has incorrect type (expected boolean)", schema_suffix=".type") elif isinstance(json_type, dict): # Nested type check. This is pretty odd case. Here we # don't change our object stack (it's the same object). self._push_schema(Schema(json_type), ".type") self._validate() self._pop_schema() elif isinstance(json_type, list): # Alternative type check, here we may match _any_ of the types # in the list to be considered valid. json_type_list = json_type if json_type == []: return for index, json_type in enumerate(json_type_list): # Aww, ugly. The level of packaging around Schema is annoying self._push_schema( Schema({'type': json_type}), ".type.%d" % index) try: self._validate() except ValidationError: # Ignore errors, we just want one thing to match pass else: # We've got a match - break the loop break finally: # Pop the schema regardless of match/mismatch self._pop_schema() else: # We were not interupted (no break) so we did not match self._report_error( "{obj!r} does not match any of the types in {type!r}".format( obj=obj, type=json_type_list), "Object has incorrect type (multiple types possible)", schema_suffix=".type") else: # Simple type check if not isinstance(obj, self.JSON_TYPE_MAP[json_type]): self._report_error( "{obj!r} does not match type {type!r}".format( obj=obj, type=json_type), "Object has incorrect type (expected {type})".format( type=json_type), schema_suffix=".type") def _validate_pattern(self): ptn = self._schema.pattern obj = self._object if ptn is None: return if not isinstance(obj, basestring): return if re.match(ptn, obj): return self._report_error( "{obj!r} does not match pattern {ptn!r}".format( obj=obj,ptn=ptn), "Object does not match pattern (expected {ptn})".format( ptn=ptn), schema_suffix=".pattern" ) def _validate_format(self): fmt = self._schema.format obj = self._object if fmt is None: return if fmt == 'date-time': try: DATE_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" datetime.datetime.strptime(obj, DATE_TIME_FORMAT) except ValueError: self._report_error( "{obj!r} is not a string representing JSON date-time".format( obj=obj), "Object is not a string representing JSON date-time", schema_suffix=".format") elif fmt == 'regex': try: re.compile(obj) except: self._report_error( "{obj!r} is not a string representing a regex".format( obj=obj), "Object is not a string representing a regex", schema_suffix=".format") else: raise NotImplementedError("format {0!r} is not supported".format(fmt)) def _validate_properties(self): obj = self._object schema = self._schema assert isinstance(obj, dict) for prop in schema.properties.iterkeys(): self._push_property_schema(prop) if prop in obj: self._push_property_object(prop) self._validate() self._pop_object() else: if not self._schema.optional: self._report_error( "{obj!r} does not have property {prop!r}".format( obj=obj, prop=prop), "Object lacks property {prop!r}".format( prop=prop), schema_suffix=".optional") self._pop_schema() def _validate_additional_properties(self): obj = self._object assert isinstance(obj, dict) if self._schema.additionalProperties is False: # Additional properties are disallowed # Report exception for each unknown property for prop in obj.iterkeys(): if prop not in self._schema.properties: self._report_error( "{obj!r} has unknown property {prop!r} and" " additionalProperties is false".format( obj=obj, prop=prop), "Object has unknown property {prop!r} but" " additional properties are disallowed".format( prop=prop), schema_suffix=".additionalProperties") else: # Check each property against this object self._push_additional_property_schema() for prop in obj.iterkeys(): self._push_property_object(prop) self._validate() self._pop_object() self._pop_schema() def _validate_enum(self): obj = self._object schema = self._schema if schema.enum is not None: for allowed_value in schema.enum: if obj == allowed_value: break else: self._report_error( "{obj!r} does not match any value in enumeration" " {enum!r}".format(obj=obj, enum=schema.enum), "Object does not match any value in enumeration", schema_suffix=".enum") def _validate_length(self): obj = self._object schema = self._schema if schema.minLength is not None: if len(obj) < schema.minLength: self._report_error( "{obj!r} does not meet the minimum length" " {minLength!r}".format(obj=obj, minLength=schema.minLength), "Object does not meet the minimum length", schema_suffix=".minLength") if schema.maxLength is not None: if len(obj) > schema.maxLength: self._report_error( "{obj!r} exceeds the maximum length" " {maxLength!r}".format(obj=obj, maxLength=schema.maxLength), "Object exceeds the maximum length", schema_suffix=".maxLength") def _validate_range(self): obj = self._object schema = self._schema if schema.minimum is not None: if obj < schema.minimum or (obj == schema.minimum and not schema.minimumCanEqual): self._report_error( "{obj!r} is less than the minimum" " {minimum!r}".format(obj=obj, minimum=schema.minimum), "Object is less than the minimum", schema_suffix=".minimum") if schema.maximum is not None: if obj > schema.maximum or (obj == schema.maximum and not schema.maximumCanEqual): self._report_error( "{obj!r} is greater than the maximum" " {maximum!r}".format(obj=obj, maximum=schema.maximum), "Object is greater than the maximum", schema_suffix=".maximum") def _validate_items(self): obj = self._object schema = self._schema assert isinstance(obj, list) items_schema_json = schema.items if items_schema_json == {}: # default value, don't do anything return if isinstance(obj, list) and schema.uniqueItems is True and len(set(obj)) != len(obj): # If we want a list of unique items and the length of unique # elements is different from the length of the full list # then validation fails. # This implementation isn't strictly compatible with the specs, because # we are not checking unique dicts. self._report_error( "Repeated items found in {obj!r}".format(obj=obj), "Repeated items found in array", schema_suffix=".items") if schema.minItems: if len(obj) < schema.minItems: self._report_error( "{obj!r} has fewer than the minimum number of items" " {minItems!r}".format(obj=obj, minimum=schema.minItems), "Object has fewer than the minimum number of items", schema_suffix=".minItems") if schema.maxItems is not None: if len(obj) > schema.maxItems: self._report_error( "{obj!r} has more than the maximum number of items" " {maxItems!r}".format(obj=obj, minimum=schema.maxItems), "Object has more than the maximum number of items", schema_suffix=".maxItems") if isinstance(items_schema_json, dict): self._push_array_schema() for index, item in enumerate(obj): self._push_array_item_object(index) self._validate() self._pop_object() self._pop_schema() elif isinstance(items_schema_json, list): if len(obj) < len(items_schema_json): # If our data array is shorter than the schema then # validation fails. Longer arrays are okay (during this # step) as they are validated based on # additionalProperties schema self._report_error( "{obj!r} is shorter than array schema {schema!r}". format(obj=obj, schema=items_schema_json), "Object array is shorter than schema array", schema_suffix=".items") if len(obj) != len(items_schema_json) and schema.additionalProperties is False: # If our array is not exactly the same size as the # schema and additional properties are disallowed then # validation fails self._report_error( "{obj!r} is not of the same length as array schema" " {schema!r} and additionalProperties is" " false".format(obj=obj, schema=items_schema_json), "Object array is not of the same length as schema array", schema_suffix=".items") # Validate each array element using schema for the # corresponding array index, fill missing values (since # there may be more items in our array than in the schema) # with additionalProperties which by now is not False for index, (item, item_schema_json) in enumerate( itertools.izip_longest( obj, items_schema_json, fillvalue=schema.additionalProperties)): item_schema = Schema(item_schema_json) if index < len(items_schema_json): self._push_schema(item_schema, "items[%d]" % index) else: self._push_schema(item_schema, ".additionalProperties") self._push_array_item_object(index) self._validate() self._pop_schema() self._pop_object() def _validate_requires(self): obj = self._object schema = self._schema requires_json = schema.requires if requires_json == {}: # default value, don't do anything return # Find our enclosing object in the object stack if len(self._object_stack) < 2: self._report_error( "{obj!r} requires that enclosing object matches" " schema {schema!r} but there is no enclosing" " object".format(obj=obj, schema=requires_json), "Object has no enclosing object that matches schema", schema_suffix=".requires") # Note: Parent object can be None, (e.g. a null property) parent_obj = self._object_stack[-2][0] if isinstance(requires_json, basestring): # This is a simple property test if (not isinstance(parent_obj, dict) or requires_json not in parent_obj): self._report_error( "{obj!r} requires presence of property {requires!r}" " in the same object".format( obj=obj, requires=requires_json), "Enclosing object does not have property" " {prop!r}".format(prop=requires_json), schema_suffix=".requires") elif isinstance(requires_json, dict): # Requires designates a whole schema, the enclosing object # must match against that schema. # Here we resort to a small hack. Proper implementation # would require us to validate the parent object from its # own context (own list of parent objects). Since doing that # and restoring the state would be very complicated we just # instantiate a new validator with a subset of our current # history here. sub_validator = Validator() sub_validator._object_stack = self._object_stack[:-1] sub_validator._schema_stack = self._schema_stack[:] sub_validator._push_schema( Schema(requires_json), ".requires") sub_validator._validate() json-schema-validator-2.3.1/json_schema_validator/extensions.py0000664000175000017500000000536712321761401024776 0ustar zygazyga00000000000000# Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . """ Date-time extension, allows to serialize and deserialize datetime objects in a consistent way. Implements equivalent of schema: { "type": "string", "format": "date-time" } """ from datetime import datetime, timedelta import re class datetime_extension(object): """ Proxy class for serializing datetime.datetime objects. The serialization is a JSON string. Date is encoded using the ISO 8601 format: YYYY-MM-DDThh:mm:ssZ That is: * Four digit year code * Dash * Two digit month code * Dash * Two digit day code * Capital letter 'T' - time stamp indicator * Two digit hour code * Colon * Two digit minute code * Colon * Two digit seconds code * Capital letter 'Z' - Zulu (UTC) time zone indicator """ FORMAT = "%Y-%m-%dT%H:%M:%SZ" @classmethod def to_json(cls, obj): return obj.strftime(cls.FORMAT) @classmethod def from_json(cls, doc): return datetime.strptime(doc, cls.FORMAT) class timedelta_extension(object): """ Proxy for serializing datetime.timedelta instances """ PATTERN = re.compile("^(\d+)d (\d+)s (\d+)us$") @classmethod def to_json(cls, obj): """ Serialize wrapped datetime.timedelta instance to a string the with the following format: [DAYS]d [SECONDS]s [MICROSECONDS]us """ return "{0}d {1}s {2}us".format( obj.days, obj.seconds, obj.microseconds) @classmethod def from_json(cls, doc): """ Deserialize JSON document (string) to datetime.timedelta instance """ if not isinstance(doc, basestring): raise TypeError("JSON document must be a string") match = cls.PATTERN.match(doc) if not match: raise ValueError("JSON document must match expected pattern") days, seconds, microseconds = map(int, match.groups()) return timedelta(days, seconds, microseconds) json-schema-validator-2.3.1/README0000664000175000017500000000061112321762727016546 0ustar zygazyga00000000000000.. image:: https://travis-ci.org/zyga/json-schema-validator.svg?branch=master :target: https://travis-ci.org/zyga/json-schema-validator About ===== This package contains an implementation of JSON Schema validator as defined by http://json-schema.org/ Installation ============ $ pip install json-schema-validator Testing ======= You will need tox (get it from pip) as python2.7 $ tox json-schema-validator-2.3.1/setup.cfg0000664000175000017500000000017712321763056017512 0ustar zygazyga00000000000000[upload_docs] upload-dir = build/sphinx/html [upload] sign = True [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 json-schema-validator-2.3.1/MANIFEST.in0000664000175000017500000000006012274741533017421 0ustar zygazyga00000000000000include doc/conf.py recursive-include doc *.rst json-schema-validator-2.3.1/PKG-INFO0000664000175000017500000000104712321763056016763 0ustar zygazyga00000000000000Metadata-Version: 1.1 Name: json-schema-validator Version: 2.3.1 Summary: JSON Schema Validator Home-page: https://github.com/zyga/json-schema-validator Author: Zygmunt Krynicki Author-email: zygmunt.krynicki@linaro.org License: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2.7 json-schema-validator-2.3.1/setup.py0000775000175000017500000000326312321762752017407 0ustar zygazyga00000000000000#!/usr/bin/env python # # Copyright (C) 2010, 2011 Linaro Limited # # Author: Zygmunt Krynicki # # This file is part of json-schema-validator. # # json-schema-validator is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation # # json-schema-validator is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with json-schema-validator. If not, see . from setuptools import setup, find_packages setup( name='json-schema-validator', version=":versiontools:json_schema_validator:__version__", author="Zygmunt Krynicki", author_email="zygmunt.krynicki@linaro.org", description="JSON Schema Validator", packages=find_packages(), url='https://github.com/zyga/json-schema-validator', test_suite='json_schema_validator.tests.test_suite', classifiers=[ "Development Status :: 4 - Beta", "Intended Audience :: Developers", ("License :: OSI Approved :: GNU Library or Lesser General Public" " License (LGPL)"), "Operating System :: OS Independent", "Programming Language :: Python :: 2.7"], install_requires=[ 'simplejson >= 2.0.9'], setup_requires=[ 'versiontools >= 1.3.1'], tests_require=[ 'testscenarios >= 0.1', 'testtools >= 0.9.2'], zip_safe=True) json-schema-validator-2.3.1/doc/0000775000175000017500000000000012321763056016431 5ustar zygazyga00000000000000json-schema-validator-2.3.1/doc/changes.rst0000664000175000017500000000263612321761401020572 0ustar zygazyga00000000000000Version History *************** Version 2.1 =========== * Renamed from linaro-json to json-schema-validator and moved to github. * Reorganized the package into more sub-modules * Updated documentation a bit Version 2.0.1 ============= * Make the package installable via pip by using new versiontools * Fix test suite to be agnostic to python's rounding of floats Version 2.0 =========== * New major release, incompatible with past releases * Drop everything apart from schema validator as other elements have lost their significance * Tweak requirements to support current Ubuntu LTS (10.04 aka Lucid) * Refresh installation instructions to point to the new PPA, provide links to lp.net project page and pypi project page. Version 1.2.3 ============= * Change how setup.py finds the version of the code to make it pip install okay when simplejson is not installed yet. Version 1.2.2 ============= * Fix another problem with pip and versiontools (removed unconditional import of versiontools from __init__.py) Version 1.2.1 ============= * Fix installation problem with pip due to versiontools not being available when parsing initial setup.py Version 1.2 =========== * Change name to json-schema-validator * Add dependency on versiontools * Register on pypi * Add ReST documentation Version 1.1 =========== * Add support for retrieving default values from the schema Version 1.0 =========== * Initial release json-schema-validator-2.3.1/doc/reference.rst0000664000175000017500000000036212321761401021112 0ustar zygazyga00000000000000Code documentation ****************** .. automodule:: json_schema_validator .. toctree:: :maxdepth: 2 reference/errors.rst reference/misc.rst reference/schema.rst reference/shortcuts.rst reference/validator.rst json-schema-validator-2.3.1/doc/reference/0000775000175000017500000000000012321763056020367 5ustar zygazyga00000000000000json-schema-validator-2.3.1/doc/reference/schema.rst0000664000175000017500000000013012321761401022343 0ustar zygazyga00000000000000Schema module ^^^^^^^^^^^^^ .. automodule:: json_schema_validator.schema :members: json-schema-validator-2.3.1/doc/reference/errors.rst0000664000175000017500000000013012321761401022417 0ustar zygazyga00000000000000Errors module ^^^^^^^^^^^^^ .. automodule:: json_schema_validator.errors :members: json-schema-validator-2.3.1/doc/reference/shortcuts.rst0000664000175000017500000000014112321761401023143 0ustar zygazyga00000000000000Shortcuts module ^^^^^^^^^^^^^^^^ .. automodule:: json_schema_validator.shortcuts :members: json-schema-validator-2.3.1/doc/reference/validator.rst0000664000175000017500000000014112321761401023072 0ustar zygazyga00000000000000Validator module ^^^^^^^^^^^^^^^^ .. automodule:: json_schema_validator.validator :members: json-schema-validator-2.3.1/doc/reference/misc.rst0000664000175000017500000000012212321761401022037 0ustar zygazyga00000000000000Misc module ^^^^^^^^^^^ .. automodule:: json_schema_validator.misc :members: json-schema-validator-2.3.1/doc/index.rst0000664000175000017500000000206512321761401020265 0ustar zygazyga00000000000000JSON Schema Validator ********************* About ===== This package contains an implementation of JSON Schema validator. .. note:: This project is just getting started. While the code relatively feature-complete, rather well tested and used in production daily the *documentation* is lacking. .. warning:: This implementation was based on the *second draft* of the specification A third draft was published on the 22nd Nov 2010. This draft introduced several important changes that are not yet implemented. .. note:: Only a subset of schema features are currently supported. Unsupported features are detected and raise a NotImplementedError when you call :func:`json_schema_validator.schema.Validator.validate` .. seealso:: http://json-schema.org/ for details about the schema Table of contents ================= .. toctree:: :maxdepth: 2 installation.rst usage.rst reference.rst changes.rst hacking.rst Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` json-schema-validator-2.3.1/doc/conf.py0000664000175000017500000001511412321761401017722 0ustar zygazyga00000000000000# -*- coding: utf-8 -*- # # JSON Schema Validator documentation build configuration file, created by # sphinx-quickstart on Mon Dec 27 16:39:47 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.append(os.path.abspath('..')) # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage'] # Add any paths that contain templates here, relative to this directory. templates_path = [] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'JSON Schema Validator' copyright = u'2010, 2011 Linaro Limited' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. import json_schema_validator import versiontools version = "%d.%d" % json_schema_validator.__version__[0:2] # The full version, including alpha/beta/rc tags. release = versiontools.format_version(json_schema_validator.__version__) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'JSONSchemaValidatorDoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'LinaroJSON.tex', u'JSON Schema Validator Documentation', u'Zygmunt Krynicki', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'http://docs.python.org/': None} json-schema-validator-2.3.1/doc/hacking.rst0000664000175000017500000000205012321761401020554 0ustar zygazyga00000000000000 Hacking ******* The project is hosted on github (http://github.com/zyga/json-schema-validator/), feel free to fork it and propose a pull request. Goals ----- The goal of this project is to construct a complete and fast implementation of the JSON Schema as defined by http://json-schema.org/. JSON is powerful because of the simplicity. Unlike the baroque YAML it thrives on being easy to implement in any language, correctly, completely, with confidence and test. Python has a good built-in implementation of the serializer (decoder and encoder) but lacks more advanced tools. Working with JSON as a backend for your application, whether it's configuration, application data or envelope for your RPC system, almost always requires data validation and integrity checking. Infrastructure -------------- Github is used for: * Hosting source code (in git) * Reporting and tracking bugs Launchpad.net is used for: * Hosting source code (as bzr mirror) * Packaging aid for Ubuntu PyPi is used for: * Hosting released tarballs * Hosting built documentation json-schema-validator-2.3.1/doc/installation.rst0000664000175000017500000000107212321761401021654 0ustar zygazyga00000000000000Installation ============ Prerequisites ^^^^^^^^^^^^^ This package has the following prerequisites: * simplejson * versiontools To run the test suite you will also need: * testtools * testscenarios To build the documentation from source you will also need: * sphinx Installation Options ^^^^^^^^^^^^^^^^^^^^ This package is being actively maintained and published in the `Python Package Index `_. You can install it if you have `pip `_ tool using just one line:: pip install json-schema-validator json-schema-validator-2.3.1/doc/usage.rst0000664000175000017500000000002212274741533020264 0ustar zygazyga00000000000000Usage ***** TODO json-schema-validator-2.3.1/json_schema_validator.egg-info/0000775000175000017500000000000012321763056023714 5ustar zygazyga00000000000000json-schema-validator-2.3.1/json_schema_validator.egg-info/PKG-INFO0000664000175000017500000000104712321763056025013 0ustar zygazyga00000000000000Metadata-Version: 1.1 Name: json-schema-validator Version: 2.3.1 Summary: JSON Schema Validator Home-page: https://github.com/zyga/json-schema-validator Author: Zygmunt Krynicki Author-email: zygmunt.krynicki@linaro.org License: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2.7 json-schema-validator-2.3.1/json_schema_validator.egg-info/requires.txt0000664000175000017500000000002312321763056026307 0ustar zygazyga00000000000000simplejson >= 2.0.9json-schema-validator-2.3.1/json_schema_validator.egg-info/dependency_links.txt0000664000175000017500000000000112321763056027762 0ustar zygazyga00000000000000 json-schema-validator-2.3.1/json_schema_validator.egg-info/zip-safe0000664000175000017500000000000112274741644025352 0ustar zygazyga00000000000000 json-schema-validator-2.3.1/json_schema_validator.egg-info/top_level.txt0000664000175000017500000000002612321763056026444 0ustar zygazyga00000000000000json_schema_validator json-schema-validator-2.3.1/json_schema_validator.egg-info/SOURCES.txt0000664000175000017500000000166712321763056025612 0ustar zygazyga00000000000000MANIFEST.in README setup.cfg setup.py doc/changes.rst doc/conf.py doc/hacking.rst doc/index.rst doc/installation.rst doc/reference.rst doc/usage.rst doc/reference/errors.rst doc/reference/misc.rst doc/reference/schema.rst doc/reference/shortcuts.rst doc/reference/validator.rst json_schema_validator/__init__.py json_schema_validator/errors.py json_schema_validator/extensions.py json_schema_validator/misc.py json_schema_validator/schema.py json_schema_validator/shortcuts.py json_schema_validator/validator.py json_schema_validator.egg-info/PKG-INFO json_schema_validator.egg-info/SOURCES.txt json_schema_validator.egg-info/dependency_links.txt json_schema_validator.egg-info/requires.txt json_schema_validator.egg-info/top_level.txt json_schema_validator.egg-info/zip-safe json_schema_validator/tests/__init__.py json_schema_validator/tests/test_extensions.py json_schema_validator/tests/test_schema.py json_schema_validator/tests/test_validator.py