def test_draft4_validator_is_chosen(self): pv = PandelVisitor({}) schema = {"$schema": "http://json-schema.org/draft-04/schema#"} with mock.patch.object(pv, "iter_errors", return_value=()) as chk_schema: pv.validate({}, schema) chk_schema.assert_called_once_with({}, schema)
def test_additionalItems(self): data = ["foo", 1] schema = { "$schema": "http://json-schema.org/draft-03/schema#", "items": [], "additionalItems": { "type": "integer", "minimum": 5 }, } validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) e1, e2 = sorted_errors(errors) self.assertEqual(e1.path, deque([0])) self.assertEqual(e2.path, deque([1])) if not isinstance(instance, np.ndarray): # numpy-arrays have column-types so str+int-->str and both # errors are type-errors. self.assertSequenceEqual([e.validator for e in (e1, e2)], ("type", "minimum"), (e1, e2))
def test_patternProperties(self): data = {"bar": 1, "foo": 2} schema = { "patternProperties": { "bar": { "type": "string" }, "foo": { "minimum": 5 } } } validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) try: e1, e2 = sorted_errors(errors) except ValueError as ex: print(list(sorted_errors(validator.iter_errors(instance)))) raise ex self.assertEqual(e1.path, deque(["bar"])) self.assertEqual(e2.path, deque(["foo"])) self.assertEqual(e1.validator, "type") self.assertEqual(e2.validator, "minimum")
def test_anyOf(self): instance = 5 schema = {"anyOf": [{"minimum": 20}, {"type": "string"}]} validator = PandelVisitor(schema) errors = list(validator.iter_errors(instance)) self.assertEqual(len(errors), 1) e = errors[0] self.assertEqual(e.validator, "anyOf") self.assertEqual(e.validator_value, schema["anyOf"]) self.assertEqual(e.instance, instance) self.assertEqual(e.schema, schema) self.assertIsNone(e.parent) self.assertEqual(e.path, deque([])) self.assertEqual(e.relative_path, deque([])) self.assertEqual(e.absolute_path, deque([])) self.assertEqual(e.schema_path, deque(["anyOf"])) self.assertEqual(e.relative_schema_path, deque(["anyOf"])) self.assertEqual(e.absolute_schema_path, deque(["anyOf"])) self.assertEqual(len(e.context), 2) e1, e2 = sorted_errors(e.context) self.assertEqual(e1.validator, "minimum") self.assertEqual(e1.validator_value, schema["anyOf"][0]["minimum"]) self.assertEqual(e1.instance, instance) self.assertEqual(e1.schema, schema["anyOf"][0]) self.assertIs(e1.parent, e) self.assertEqual(e1.path, deque([])) self.assertEqual(e1.absolute_path, deque([])) self.assertEqual(e1.relative_path, deque([])) self.assertEqual(e1.schema_path, deque([0, "minimum"])) self.assertEqual(e1.relative_schema_path, deque([0, "minimum"])) self.assertEqual(e1.absolute_schema_path, deque(["anyOf", 0, "minimum"])) self.assertFalse(e1.context) self.assertEqual(e2.validator, "type") self.assertEqual(e2.validator_value, schema["anyOf"][1]["type"]) self.assertEqual(e2.instance, instance) self.assertEqual(e2.schema, schema["anyOf"][1]) self.assertIs(e2.parent, e) self.assertEqual(e2.path, deque([])) self.assertEqual(e2.relative_path, deque([])) self.assertEqual(e2.absolute_path, deque([])) self.assertEqual(e2.schema_path, deque([1, "type"])) self.assertEqual(e2.relative_schema_path, deque([1, "type"])) self.assertEqual(e2.absolute_schema_path, deque(["anyOf", 1, "type"])) self.assertEqual(len(e2.context), 0)
def test_multiple_nesting(self): instance = [1, {"foo": 2, "bar": {"baz": [1]}}, "quux"] schema = { "$schema": "http://json-schema.org/draft-03/schema#", "type": "string", "items": { "type": ["string", "object"], "properties": { "foo": { "enum": [1, 3] }, "bar": { "type": "array", "properties": { "bar": { "required": True }, "baz": { "minItems": 2 }, }, }, }, }, } validator = PandelVisitor(schema) errors = validator.iter_errors(instance) e1, e2, e3, e4, e5, e6 = sorted_errors(errors) self.assertEqual(e1.path, deque([])) self.assertEqual(e2.path, deque([0])) self.assertEqual(e3.path, deque([1, "bar"])) self.assertEqual(e4.path, deque([1, "bar", "bar"])) self.assertEqual(e5.path, deque([1, "bar", "baz"])) self.assertEqual(e6.path, deque([1, "foo"])) self.assertEqual(e1.schema_path, deque(["type"])) self.assertEqual(e2.schema_path, deque(["items", "type"])) self.assertEqual(list(e3.schema_path), ["items", "properties", "bar", "type"]) self.assertEqual( list(e4.schema_path), ["items", "properties", "bar", "properties", "bar", "required"], ) self.assertEqual( list(e5.schema_path), ["items", "properties", "bar", "properties", "baz", "minItems"], ) self.assertEqual(list(e6.schema_path), ["items", "properties", "foo", "enum"]) self.assertEqual(e1.validator, "type") self.assertEqual(e2.validator, "type") self.assertEqual(e3.validator, "type") self.assertEqual(e4.validator, "required") self.assertEqual(e5.validator, "minItems") self.assertEqual(e6.validator, "enum")
def test_multiple_nesting(self): instance = [1, {"foo": 2, "bar": {"baz": [1]}}, "quux"] schema = { "$schema": "http://json-schema.org/draft-03/schema#", "type": "string", "items": { "type": ["string", "object"], "properties": { "foo": {"enum": [1, 3]}, "bar": { "type": "array", "properties": { "bar": {"required": True}, "baz": {"minItems": 2}, } } } } } validator = PandelVisitor(schema) errors = validator.iter_errors(instance) e1, e2, e3, e4, e5, e6 = sorted_errors(errors) self.assertEqual(e1.path, deque([])) self.assertEqual(e2.path, deque([0])) self.assertEqual(e3.path, deque([1, "bar"])) self.assertEqual(e4.path, deque([1, "bar", "bar"])) self.assertEqual(e5.path, deque([1, "bar", "baz"])) self.assertEqual(e6.path, deque([1, "foo"])) self.assertEqual(e1.schema_path, deque(["type"])) self.assertEqual(e2.schema_path, deque(["items", "type"])) self.assertEqual( list(e3.schema_path), ["items", "properties", "bar", "type"], ) self.assertEqual( list(e4.schema_path), ["items", "properties", "bar", "properties", "bar", "required"], ) self.assertEqual( list(e5.schema_path), ["items", "properties", "bar", "properties", "baz", "minItems"] ) self.assertEqual( list(e6.schema_path), ["items", "properties", "foo", "enum"], ) self.assertEqual(e1.validator, "type") self.assertEqual(e2.validator, "type") self.assertEqual(e3.validator, "type") self.assertEqual(e4.validator, "required") self.assertEqual(e5.validator, "minItems") self.assertEqual(e6.validator, "enum")
def test_validate_object_or_pandas(self): schema = {"type": ["object"]} pv = PandelVisitor(schema) pv.validate({"foo": "bar"}) pv.validate(pd.Series({"foo": "bar", "foofoo": "bar"})) pv.validate(pd.DataFrame({"foo": [1, 2], "foofoo": [3, 4]})) with self.assertRaisesRegex(ValidationError, r"\[1, 2, 3\] is not of type u?'object'"): pv.validate([1, 2, 3])
class TestDraft3lValidator(ValidatorTestMixin, unittest.TestCase): def setUp(self): super().setUp() self.validator = PandelVisitor( {"$schema": "http://json-schema.org/draft-03/schema#"}) def test_is_type_is_true_for_any_type(self): self.assertTrue(self.validator.is_valid(mock.Mock(), {"type": "any"})) def test_is_type_does_not_evade_bool_if_it_is_being_tested(self): self.assertTrue(self.validator.is_type(True, "boolean")) self.assertTrue(self.validator.is_valid(True, {"type": "any"}))
def test_additionalProperties(self): data = {"bar": "bar", "foo": 2} schema = {"additionalProperties": {"type": "integer", "minimum": 5}} validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) e1, e2 = sorted_errors(errors) self.assertEqual(e1.path, deque(["bar"])) self.assertEqual(e2.path, deque(["foo"])) self.assertEqual(e1.validator, "type") self.assertEqual(e2.validator, "minimum")
def test_validate_object_or_pandas(self): schema = { 'type': ['object'], } pv = PandelVisitor(schema) pv.validate({'foo': 'bar'}) pv.validate(pd.Series({'foo': 'bar', 'foofoo': 'bar'})) pv.validate(pd.DataFrame({'foo': [1, 2], 'foofoo': [3, 4]})) with assertRaisesRegex(self, ValidationError, "\[1, 2, 3\] is not of type u?'object'"): pv.validate([1, 2, 3])
def test_additionalProperties(self): data = {"bar": "bar", "foo": 2} schema = { "additionalProperties": {"type": "integer", "minimum": 5} } validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) e1, e2 = sorted_errors(errors) self.assertEqual(e1.path, deque(["bar"])) self.assertEqual(e2.path, deque(["foo"])) self.assertEqual(e1.validator, "type") self.assertEqual(e2.validator, "minimum")
def test_single_nesting(self): data = {"foo": 2, "bar": [1], "baz": 15, "quux": "spam"} schema = { "properties": { "foo": { "type": "string" }, "bar": { "minItems": 2 }, "baz": { "maximum": 10, "enum": [2, 4, 6, 8] }, } } validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) errors = sorted_errors(errors) try: e1, e2, e3, e4 = errors except ValueError as ex: print(list(sorted_errors(validator.iter_errors(instance)))) raise ex self.assertEqual(e1.path, deque(["bar"])) self.assertEqual(e2.path, deque(["baz"])) self.assertEqual(e3.path, deque(["baz"])) self.assertEqual(e4.path, deque(["foo"])) self.assertEqual(e1.relative_path, deque(["bar"])) self.assertEqual(e2.relative_path, deque(["baz"])) self.assertEqual(e3.relative_path, deque(["baz"])) self.assertEqual(e4.relative_path, deque(["foo"])) self.assertEqual(e1.absolute_path, deque(["bar"])) self.assertEqual(e2.absolute_path, deque(["baz"])) self.assertEqual(e3.absolute_path, deque(["baz"])) self.assertEqual(e4.absolute_path, deque(["foo"])) self.assertEqual(e1.validator, "minItems") self.assertEqual(e2.validator, "enum") self.assertEqual(e3.validator, "maximum") self.assertEqual(e4.validator, "type")
def test_additionalItems_with_items(self): data = ["foo", "bar", 1] schema = { "items": [{}], "additionalItems": {"type": "integer", "minimum": 5} } validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) e1, e2 = sorted_errors(errors) self.assertEqual(e1.path, deque([1])) self.assertEqual(e2.path, deque([2])) if not isinstance(instance, np.ndarray): # numpy-arrays have column-types so str+int-->str and both # errors are type-errors. self.assertSequenceEqual( [e.validator for e in (e1, e2)], ("type", "minimum"), (e1, e2))
def model_validator(additional_properties=False, validate_wltc_data=False, validate_schema=False) -> PandelVisitor: ## NOTE: Using non-copied (mode, wltc)-schemas, # since we are certain they will not be modified here. # schema = _get_model_schema(additional_properties) wltc_schema = (_get_wltc_schema() if validate_wltc_data else {} ) ## Do not supply wltc schema, for speedup. resolver = RefResolver(_model_url, schema, store={_wltc_url: wltc_schema}) validator = PandelVisitor( schema, resolver=resolver, auto_default=True, auto_default_nulls=True, auto_remove_nulls=True, ) if validate_schema: ## Patch jsonschema-schema for extra fields & forbid miss-spells. # See https://github.com/Julian/jsonschema/issues/268 # stricter_metaschema = { **validator.META_SCHEMA, "additionalProperties": False, "properties": { **validator.META_SCHEMA["properties"], "tags": { "description": "Data item extra label e.g. input/output or use/purpose.", "type": "array", "items": { "type": "string" }, "uniqueItems": True, }, "units": { "description": "Default units of the quantity, by `pint` library.", "type": "string", }, # For extension https://sphinx-jsonschema.readthedocs.io/en/latest/schemakeywords.html "$$target": { "type": ["string", "array"] }, }, } strictValidator = jsonschema.validators.validator_for( stricter_metaschema) strictValidator(stricter_metaschema).validate(schema) return validator
def test_single_nesting(self): data = {"foo": 2, "bar": [1], "baz": 15, "quux": "spam"} schema = { "properties": { "foo": {"type": "string"}, "bar": {"minItems": 2}, "baz": {"maximum": 10, "enum": [2, 4, 6, 8]}, } } validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) errors = sorted_errors(errors) try: e1, e2, e3, e4 = errors except ValueError as ex: print(list(sorted_errors(validator.iter_errors(instance)))) raise ex self.assertEqual(e1.path, deque(["bar"])) self.assertEqual(e2.path, deque(["baz"])) self.assertEqual(e3.path, deque(["baz"])) self.assertEqual(e4.path, deque(["foo"])) self.assertEqual(e1.relative_path, deque(["bar"])) self.assertEqual(e2.relative_path, deque(["baz"])) self.assertEqual(e3.relative_path, deque(["baz"])) self.assertEqual(e4.relative_path, deque(["foo"])) self.assertEqual(e1.absolute_path, deque(["bar"])) self.assertEqual(e2.absolute_path, deque(["baz"])) self.assertEqual(e3.absolute_path, deque(["baz"])) self.assertEqual(e4.absolute_path, deque(["foo"])) self.assertEqual(e1.validator, "minItems") self.assertEqual(e2.validator, "enum") self.assertEqual(e3.validator, "maximum") self.assertEqual(e4.validator, "type")
class TestDraft3lValidator(ValidatorTestMixin, unittest.TestCase): validator_class = PandelVisitor def setUp(self): super(TestDraft3lValidator, self).setUp() self.validator = PandelVisitor({ "$schema": "http://json-schema.org/draft-03/schema#" }) #@unittest.skip("For Draft3Validator only!") def test_is_type_is_true_for_any_type(self): self.assertTrue(self.validator.is_valid(mock.Mock(), {"type": "any"})) #@unittest.skip("For Draft3Validator only!") def test_is_type_does_not_evade_bool_if_it_is_being_tested(self): self.assertTrue(self.validator.is_type(True, "boolean")) self.assertTrue(self.validator.is_valid(True, {"type": "any"})) #@unittest.skip("The schema below in invalid under Draft3/4, but original test had averted meta-validation.") def test_non_string_custom_types(self): schema = { "$schema": "http://json-schema.org/draft-03/schema#", 'type': [None] } cls = self.validator_class( schema, types={None: type(None)}, skip_meta_validation=True) cls.validate(None, schema) schema = { "$schema": "http://json-schema.org/draft-03/schema#", 'type': 'some' } types = { 'object': dict, 'some': pd.DataFrame, } cls = self.validator_class( schema, types=types, skip_meta_validation=True) cls.validate(pd.DataFrame(), schema)
def test_draft3_validator_is_chosen(self): pv = PandelVisitor({}) schema = {"$schema": "http://json-schema.org/draft-03/schema#"} with mock.patch.object(pv, "iter_errors", return_value=()) as chk_schema: pv.validate({}, schema) chk_schema.assert_called_once_with({}, schema) # Make sure it works without the empty fragment pv = PandelVisitor({}) schema = {"$schema": "http://json-schema.org/draft-03/schema"} with mock.patch.object(pv, "iter_errors", return_value=()) as chk_schema: pv.validate({}, schema) chk_schema.assert_called_once_with({}, schema)
def test_it_delegates_to_a_ref_resolver(self): resolver = RefResolver("", {}) schema = {"$ref": mock.Mock()} @contextmanager def resolving(): yield {"type": "integer"} with mock.patch.object(resolver, "resolve") as resolve: resolve.return_value = "url", {"type": "integer"} with self.assertRaises(ValidationError): PandelVisitor(schema, resolver=resolver).validate(None) resolve.assert_called_once_with(schema["$ref"])
def test_patternProperties(self): data = {"bar": 1, "foo": 2} schema = { "patternProperties": { "bar": {"type": "string"}, "foo": {"minimum": 5} } } validator = PandelVisitor(schema) for instance in wrap_in_pandas(data): errors = validator.iter_errors(instance) try: e1, e2 = sorted_errors(errors) except ValueError as ex: print(list(sorted_errors(validator.iter_errors(instance)))) raise ex self.assertEqual(e1.path, deque(["bar"])) self.assertEqual(e2.path, deque(["foo"])) self.assertEqual(e1.validator, "type") self.assertEqual(e2.validator, "minimum")
def model_validator( additional_properties=False, validate_wltc_data=False, validate_schema=False ): schema = _get_model_schema(additional_properties) wltc_schema = ( _get_wltc_schema() if validate_wltc_data else {} ) ## Do not supply wltc schema, for speedup. resolver = RefResolver(_model_url, schema, store={_wltc_url: wltc_schema}) validator = PandelVisitor(schema, resolver=resolver) if validate_schema: # See https://github.com/Julian/jsonschema/issues/268 stricter_metaschema = dict(validator.META_SCHEMA, additionalProperties=False) strictValidator = jsonschema.validators.validator_for(stricter_metaschema) strictValidator(stricter_metaschema).validate(schema) return validator
class TestIterErrors(unittest.TestCase): def iter_errors(self, instance, schema, *args, **kwds): self.validator = PandelVisitor(schema) return self.validator.iter_errors(instance, *args, **kwds) #@unittest.skip("For Draft3Validator only!") def test_iter_errors(self): data = [1, 2] for instance in wrap_in_pandas(data): schema = { "$schema": "http://json-schema.org/draft-03/schema#", u"disallow": u"array", u"enum": [["a", "b", "c"], ["d", "e", "f"]], u"minItems": 3 } got = (e for e in self.iter_errors(instance, schema)) expected = [ "disallow", "minItems", "enum", ] self.assertListEqual( sorted(e.validator for e in got), sorted(expected)) def test_iter_errors_multiple_failures_one_validator(self): tree1 = {"foo": 2, "bar": [1], "baz": 15, "quux": "spam"} tree2 = {"foo": 2, "bar": np.array([1]), "baz": 15, "quux": "spam"} for data in (tree1, tree2,): for instance in wrap_in_pandas(data): schema = { u"properties": { "foo": {u"type": "string"}, "bar": {u"minItems": 2}, "baz": {u"maximum": 10, u"enum": [2, 4, 6, 8]}, } } errors = list(self.iter_errors(instance, schema)) self.assertEqual(len(errors), 4, errors)
def test_draft4_validator_is_the_default(self): pv = PandelVisitor({}) with mock.patch.object(pv, "iter_errors", return_value=()) as chk_schema: pv.validate({}, {}) chk_schema.assert_called_once_with({}, {})
def test_anyOf(self): instance = 5 schema = { "anyOf": [ {"minimum": 20}, {"type": "string"} ] } validator = PandelVisitor(schema) errors = list(validator.iter_errors(instance)) self.assertEqual(len(errors), 1) e = errors[0] self.assertEqual(e.validator, "anyOf") self.assertEqual(e.validator_value, schema["anyOf"]) self.assertEqual(e.instance, instance) self.assertEqual(e.schema, schema) self.assertIsNone(e.parent) self.assertEqual(e.path, deque([])) self.assertEqual(e.relative_path, deque([])) self.assertEqual(e.absolute_path, deque([])) self.assertEqual(e.schema_path, deque(["anyOf"])) self.assertEqual(e.relative_schema_path, deque(["anyOf"])) self.assertEqual(e.absolute_schema_path, deque(["anyOf"])) self.assertEqual(len(e.context), 2) e1, e2 = sorted_errors(e.context) self.assertEqual(e1.validator, "minimum") self.assertEqual(e1.validator_value, schema["anyOf"][0]["minimum"]) self.assertEqual(e1.instance, instance) self.assertEqual(e1.schema, schema["anyOf"][0]) self.assertIs(e1.parent, e) self.assertEqual(e1.path, deque([])) self.assertEqual(e1.absolute_path, deque([])) self.assertEqual(e1.relative_path, deque([])) self.assertEqual(e1.schema_path, deque([0, "minimum"])) self.assertEqual(e1.relative_schema_path, deque([0, "minimum"])) self.assertEqual( e1.absolute_schema_path, deque(["anyOf", 0, "minimum"]), ) self.assertFalse(e1.context) self.assertEqual(e2.validator, "type") self.assertEqual(e2.validator_value, schema["anyOf"][1]["type"]) self.assertEqual(e2.instance, instance) self.assertEqual(e2.schema, schema["anyOf"][1]) self.assertIs(e2.parent, e) self.assertEqual(e2.path, deque([])) self.assertEqual(e2.relative_path, deque([])) self.assertEqual(e2.absolute_path, deque([])) self.assertEqual(e2.schema_path, deque([1, "type"])) self.assertEqual(e2.relative_schema_path, deque([1, "type"])) self.assertEqual(e2.absolute_schema_path, deque(["anyOf", 1, "type"])) self.assertEqual(len(e2.context), 0)
def test_type(self): instance = {"foo": 1} schema = { "$schema": "http://json-schema.org/draft-03/schema#", "type": [ {"type": "integer"}, { "type": "object", "properties": { "foo": {"enum": [2]} } } ] } validator = PandelVisitor(schema) data = {"foo": 1} for instance in wrap_in_pandas(data): errors = list(validator.iter_errors(instance)) self.assertEqual(len(errors), 1) e = errors[0] self.assertEqual(e.validator, "type") self.assertEqual(e.validator_value, schema["type"]) npt.assert_array_equal(e.instance, instance) self.assertEqual(e.schema, schema) self.assertIsNone(e.parent) self.assertEqual(e.path, deque([])) self.assertEqual(e.relative_path, deque([])) self.assertEqual(e.absolute_path, deque([])) self.assertEqual(e.schema_path, deque(["type"])) self.assertEqual(e.relative_schema_path, deque(["type"])) self.assertEqual(e.absolute_schema_path, deque(["type"])) self.assertEqual(len(e.context), 2) e1, e2 = sorted_errors(e.context) self.assertEqual(e1.validator, "type") self.assertEqual(e1.validator_value, schema["type"][0]["type"]) npt.assert_array_equal(e1.instance, instance) self.assertEqual(e1.schema, schema["type"][0]) self.assertIs(e1.parent, e) self.assertEqual(e1.path, deque([])) self.assertEqual(e1.relative_path, deque([])) self.assertEqual(e1.absolute_path, deque([])) self.assertEqual(e1.schema_path, deque([0, "type"])) self.assertEqual(e1.relative_schema_path, deque([0, "type"])) self.assertEqual( e1.absolute_schema_path, deque(["type", 0, "type"])) self.assertFalse(e1.context) self.assertEqual(e2.validator, "enum") self.assertEqual(e2.validator_value, [2]) npt.assert_array_equal(e2.instance, 1) self.assertEqual(e2.schema, {u"enum": [2]}) self.assertIs(e2.parent, e) self.assertEqual(e2.path, deque(["foo"])) self.assertEqual(e2.relative_path, deque(["foo"])) self.assertEqual(e2.absolute_path, deque(["foo"])) self.assertEqual( e2.schema_path, deque([1, "properties", "foo", "enum"]), ) self.assertEqual( e2.relative_schema_path, deque( [1, "properties", "foo", "enum"]), ) self.assertEqual( e2.absolute_schema_path, deque(["type", 1, "properties", "foo", "enum"]), ) self.assertFalse(e2.context)
def setUp(self): super().setUp() self.validator = PandelVisitor( {"$schema": "http://json-schema.org/draft-04/schema#"})
def setUp(self): super(TestDraft3lValidator, self).setUp() self.validator = PandelVisitor({ "$schema": "http://json-schema.org/draft-03/schema#" })
def test_type(self): instance = {"foo": 1} schema = { "$schema": "http://json-schema.org/draft-03/schema#", "type": [ { "type": "integer" }, { "type": "object", "properties": { "foo": { "enum": [2] } } }, ], } validator = PandelVisitor(schema) data = {"foo": 1} for instance in wrap_in_pandas(data): errors = list(validator.iter_errors(instance)) self.assertEqual(len(errors), 1) e = errors[0] self.assertEqual(e.validator, "type") self.assertEqual(e.validator_value, schema["type"]) npt.assert_array_equal(e.instance, instance) self.assertEqual(e.schema, schema) self.assertIsNone(e.parent) self.assertEqual(e.path, deque([])) self.assertEqual(e.relative_path, deque([])) self.assertEqual(e.absolute_path, deque([])) self.assertEqual(e.schema_path, deque(["type"])) self.assertEqual(e.relative_schema_path, deque(["type"])) self.assertEqual(e.absolute_schema_path, deque(["type"])) self.assertEqual(len(e.context), 2) e1, e2 = sorted_errors(e.context) self.assertEqual(e1.validator, "type") self.assertEqual(e1.validator_value, schema["type"][0]["type"]) npt.assert_array_equal(e1.instance, instance) self.assertEqual(e1.schema, schema["type"][0]) self.assertIs(e1.parent, e) self.assertEqual(e1.path, deque([])) self.assertEqual(e1.relative_path, deque([])) self.assertEqual(e1.absolute_path, deque([])) self.assertEqual(e1.schema_path, deque([0, "type"])) self.assertEqual(e1.relative_schema_path, deque([0, "type"])) self.assertEqual(e1.absolute_schema_path, deque(["type", 0, "type"])) self.assertFalse(e1.context) self.assertEqual(e2.validator, "enum") self.assertEqual(e2.validator_value, [2]) npt.assert_array_equal(e2.instance, 1) self.assertEqual(e2.schema, {u"enum": [2]}) self.assertIs(e2.parent, e) self.assertEqual(e2.path, deque(["foo"])) self.assertEqual(e2.relative_path, deque(["foo"])) self.assertEqual(e2.absolute_path, deque(["foo"])) self.assertEqual(e2.schema_path, deque([1, "properties", "foo", "enum"])) self.assertEqual(e2.relative_schema_path, deque([1, "properties", "foo", "enum"])) self.assertEqual(e2.absolute_schema_path, deque(["type", 1, "properties", "foo", "enum"])) self.assertFalse(e2.context)
def test_recursive(self): schema = { "definitions": { "node": { "anyOf": [{ "type": "object", "required": ["name", "children"], "properties": { "name": { "type": "string" }, "children": { "type": "object", "patternProperties": { "^.*$": { "$ref": "#/definitions/node" } }, }, }, }] } }, "type": "object", "required": ["root"], "properties": { "root": { "$ref": "#/definitions/node" } }, } instance = { "root": { "name": "root", "children": { "a": { "name": "a", "children": { "ab": { "name": "ab", # missing "children" } }, } }, } } validator = PandelVisitor(schema) (e, ) = validator.iter_errors(instance) self.assertEqual(e.absolute_path, deque(["root"])) self.assertEqual(e.absolute_schema_path, deque(["properties", "root", "anyOf"])) (e1, ) = e.context self.assertEqual(e1.absolute_path, deque(["root", "children", "a"])) self.assertEqual( e1.absolute_schema_path, deque([ "properties", "root", "anyOf", 0, "properties", "children", "patternProperties", "^.*$", "anyOf", ]), ) (e2, ) = e1.context self.assertEqual(e2.absolute_path, deque(["root", "children", "a", "children", "ab"])) self.assertEqual( e2.absolute_schema_path, deque([ "properties", "root", "anyOf", 0, "properties", "children", "patternProperties", "^.*$", "anyOf", 0, "properties", "children", "patternProperties", "^.*$", "anyOf", ]), )
def iter_errors(self, instance, schema, *args, **kwds): self.validator = PandelVisitor(schema) return self.validator.iter_errors(instance, *args, **kwds)
def iter_errors(instance, schema, *args, **kwds): validator = PandelVisitor(schema) return validator.iter_errors(instance, *args, **kwds)
def test_rule_requiredProperties_rule_for_pandas(self): schema = { 'type': ['object'], 'required': ['foo'] } pv = PandelVisitor(schema) pv.validate({'foo': 'bar'}) with assertRaisesRegex(self, ValidationError, "'foo' is a required property"): pv.validate({'foofoo': 'bar'}) pv.validate(pd.Series({'foo': 'bar', 'foofoo': 'bar'})) with assertRaisesRegex(self, ValidationError, "'foo' is a required property"): pv.validate(pd.Series({'foofoo': 'bar'})) pv.validate(pd.DataFrame({'foo': [1, 2], 'foofoo': [3, 4]})) with assertRaisesRegex(self, ValidationError, "'foo' is a required property"): pv.validate(pd.DataFrame({'foofoo': [1, 2], 'bar': [3, 4]}))
def validate(instance, schema, *args, **kws): return PandelVisitor(schema, *args, **kws).validate(instance)
def test_rule_additionalProperties_for_pandas(self): schema = { "type": ["object"], "additionalProperties": False, "properties": { "foo": {} }, } pv = PandelVisitor(schema) pv.validate({"foo": 1}) with self.assertRaisesRegex( ValidationError, r"Additional properties are not allowed \(u?'bar' was unexpected\)", ): pv.validate({"foo": 1, "bar": 2}) pv.validate(pd.Series({"foo": 1})) with self.assertRaisesRegex( ValidationError, r"Additional properties are not allowed \(u?'bar' was unexpected\)", ): pv.validate(pd.Series({"foo": 1, "bar": 2})) pv.validate(pd.DataFrame({"foo": [1]})) with self.assertRaisesRegex( ValidationError, r"Additional properties are not allowed \(u?'bar' was unexpected\)", ): pv.validate(pd.DataFrame({"foo": [1], "bar": [2]}))
def test_rule_additionalProperties_for_pandas(self): schema = { 'type': ['object'], 'additionalProperties': False, 'properties': { 'foo': {}, } } pv = PandelVisitor(schema) pv.validate({'foo': 1}) with assertRaisesRegex(self, ValidationError, "Additional properties are not allowed \(u?'bar' was unexpected\)"): pv.validate({'foo': 1, 'bar': 2}) pv.validate(pd.Series({'foo': 1})) with assertRaisesRegex(self, ValidationError, "Additional properties are not allowed \(u?'bar' was unexpected\)"): pv.validate(pd.Series({'foo': 1, 'bar': 2})) pv.validate(pd.DataFrame({'foo': [1]})) with assertRaisesRegex(self, ValidationError, "Additional properties are not allowed \(u?'bar' was unexpected\)"): pv.validate(pd.DataFrame({'foo': [1], 'bar': [2]}))
def test_rule_requiredProperties_rule_for_pandas(self): schema = {"type": ["object"], "required": ["foo"]} pv = PandelVisitor(schema) pv.validate({"foo": "bar"}) with self.assertRaisesRegex(ValidationError, "'foo' is a required property"): pv.validate({"foofoo": "bar"}) pv.validate(pd.Series({"foo": "bar", "foofoo": "bar"})) with self.assertRaisesRegex(ValidationError, "'foo' is a required property"): pv.validate(pd.Series({"foofoo": "bar"})) pv.validate(pd.DataFrame({"foo": [1, 2], "foofoo": [3, 4]})) with self.assertRaisesRegex(ValidationError, "'foo' is a required property"): pv.validate(pd.DataFrame({"foofoo": [1, 2], "bar": [3, 4]}))