From c99486f0c9d553bc8f964273dda160dd5cb8ceda Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Fri, 28 Sep 2012 14:07:06 -0400 Subject: [PATCH] Add schema as a parameter to init for Draft3Validators. --- jsonschema.py | 32 ++++++++++++++++++---------- tests.py | 59 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/jsonschema.py b/jsonschema.py index e9a7ac3..6221b22 100644 --- a/jsonschema.py +++ b/jsonschema.py @@ -91,7 +91,7 @@ class Draft3Validator(object): "number" : (int, float), "object" : dict, "string" : basestring, } - def __init__(self, types=()): + def __init__(self, schema, types=()): """ Initialize a validator. @@ -110,6 +110,17 @@ class Draft3Validator(object): self._types.update(types) self._types["any"] = tuple(self._types.values()) + self.schema = schema + + @property + def schema(self): + return self._schema + + @schema.setter + def schema(self, schema): + self.check_schema(schema) + self._schema = schema + def is_type(self, instance, type): """ Check if an ``instance`` is of the provided ``type``. @@ -127,7 +138,7 @@ class Draft3Validator(object): return False return isinstance(instance, type) - def is_valid(self, instance, schema): + def is_valid(self, instance, schema=None): """ Check if the ``instance`` is valid under the ``schema``. @@ -151,12 +162,15 @@ class Draft3Validator(object): # I think we're safer raising these always, not yielding them raise s - def iter_errors(self, instance, schema): + def iter_errors(self, instance, schema=None): """ Lazily yield each of the errors in the given ``instance``. """ + if schema is None: + schema = self.schema + for k, v in iteritems(schema): validator = getattr(self, "validate_%s" % (k.lstrip("$"),), None) @@ -473,7 +487,7 @@ class Validator(Draft3Validator): self, version=None, unknown_type="skip", unknown_property="skip", *args, **kwargs ): - super(Validator, self).__init__(*args, **kwargs) + super(Validator, self).__init__({}, *args, **kwargs) warnings.warn( "Validator is deprecated and will be removed. " "Use Draft3Validator instead.", @@ -651,9 +665,7 @@ def _uniq(container): return True -def validate( - instance, schema, meta_validate=True, cls=Draft3Validator, *args, **kwargs -): +def validate(instance, schema, cls=Draft3Validator, *args, **kwargs): """ Validate an ``instance`` under the given ``schema``. @@ -672,7 +684,5 @@ def validate( """ - validator = cls(*args, **kwargs) - if meta_validate: - validator.check_schema(schema) - validator.validate(instance, schema) + validator = cls(schema, *args, **kwargs) + validator.validate(instance) diff --git a/tests.py b/tests.py index 3ac0f2b..314feda 100644 --- a/tests.py +++ b/tests.py @@ -588,7 +588,7 @@ class TestValidate(ParameterizedTestCase, TestCase): class TestIterErrors(TestCase): def setUp(self): - self.validator = Draft3Validator() + self.validator = Draft3Validator({}) def test_iter_errors(self): instance = [1, 2] @@ -685,7 +685,7 @@ class TestValidationErrorMessages(TestCase): class TestValidationErrorDetails(TestCase): def setUp(self): - self.validator = Draft3Validator() + self.validator = Draft3Validator({}) # TODO: These really need unit tests for each individual validator, rather # than just these higher level tests. @@ -751,7 +751,7 @@ class TestValidationErrorDetails(TestCase): class TestErrorTree(TestCase): def setUp(self): - self.validator = Draft3Validator() + self.validator = Draft3Validator({}) def test_tree(self): instance = [1, {"foo" : 2, "bar" : {"baz" : [1]}}, "quux"] @@ -795,30 +795,45 @@ class TestErrorTree(TestCase): class TestDraft3Validator(TestCase): def setUp(self): self.instance = mock.Mock() - self.validator = Draft3Validator() + self.schema = {} + self.validator = Draft3Validator(self.schema) + + def test_init(self): + with mock.patch.object(Draft3Validator, "check_schema"): + self.assertIs(self.validator.schema, self.schema) + + def test_schemas_are_validated_when_assigned(self): + schema = mock.Mock() + with mock.patch.object(self.validator, "check_schema") as check_schema: + self.validator.schema = schema + + check_schema.assert_called_once_with(schema) + self.assertEqual(self.validator.schema, schema) + + def test_valid_instances_are_valid(self): + errors = iter([]) + + with mock.patch.object( + self.validator, "iter_errors", return_value=errors, + ): + self.assertTrue( + self.validator.is_valid(self.instance, self.schema) + ) + + def test_invalid_instances_are_not_valid(self): + errors = iter([mock.Mock()]) + + with mock.patch.object( + self.validator, "iter_errors", return_value=errors, + ): + self.assertFalse( + self.validator.is_valid(self.instance, self.schema) + ) def test_non_existent_properties_are_ignored(self): instance, my_property, my_value = mock.Mock(), mock.Mock(), mock.Mock() validate(instance=instance, schema={my_property : my_value}) - def test_valid_instances_are_valid(self): - errors = iter([]) - schema = mock.Mock() - - with mock.patch.object( - self.validator, "iter_errors", return_value=errors, - ): - self.assertTrue(self.validator.is_valid(self.instance, schema)) - - def test_invalid_instances_are_not_valid(self): - errors = iter([mock.Mock()]) - schema = mock.Mock() - - with mock.patch.object( - self.validator, "iter_errors", return_value=errors, - ): - self.assertFalse(self.validator.is_valid(self.instance, schema)) - def test_is_type_is_true_for_valid_type(self): self.assertTrue(self.validator.is_type("foo", "string"))