def test_bad_list_of_dicts(schema, validator): field = "a_list_of_dicts" subschema = schema["a_list_of_dicts"]["schema"] value = [{"sku": "KT123", "price": "100"}] exp_child_errors = [((field, 0, "price"), (field, "schema", "schema", "price", "type"), errors.BAD_TYPE, "integer")] assert_fail( {field: value}, validator=validator, error=(field, (field, "schema"), errors.SEQUENCE_SCHEMA, subschema), child_errors=exp_child_errors, ) assert field in validator.errors assert 0 in validator.errors[field][-1] assert "price" in validator.errors[field][-1][0][-1] exp_msg = errors.BasicErrorHandler.messages[errors.BAD_TYPE.code].format(constraint="integer") assert exp_msg in validator.errors[field][-1][0][-1]["price"] value = ["not a dict"] exp_child_errors = [((field, 0), (field, "schema", "type"), errors.BAD_TYPE, "dict", ())] assert_fail( {field: value}, error=(field, (field, "schema"), errors.SEQUENCE_SCHEMA, subschema), child_errors=exp_child_errors, )
def test_dependencies_on_boolean_field_with_value_in_list(): # https://github.com/nicolaiarocci/cerberus/issues/138 schema = {"deleted": {"type": "boolean"}, "text": {"dependencies": {"deleted": [False]}}} assert_success({"text": "foo", "deleted": False}, schema) assert_fail({"text": "foo", "deleted": True}, schema) assert_fail({"text": "foo"}, schema)
def test_a_dict_with_valueschema(validator): assert_success({"a_dict_with_valueschema": {"an integer": 99, "another integer": 100}}) error = ( "a_dict_with_valueschema", ("a_dict_with_valueschema", "valueschema"), errors.VALUESCHEMA, {"type": "integer"}, ) child_errors = [ ( ("a_dict_with_valueschema", "a string"), ("a_dict_with_valueschema", "valueschema", "type"), errors.BAD_TYPE, "integer", ) ] assert_fail( {"a_dict_with_valueschema": {"a string": "99"}}, validator=validator, error=error, child_errors=child_errors ) assert "valueschema" in validator.schema_error_tree["a_dict_with_valueschema"] v = validator.schema_error_tree assert len(v["a_dict_with_valueschema"]["valueschema"].descendants) == 1
def test_required_field(schema): field = "a_required_string" required_string_extension = { "a_required_string": {"type": "string", "minlength": 2, "maxlength": 10, "required": True} } schema.update(required_string_extension) assert_fail({"an_integer": 1}, schema, error=(field, (field, "required"), errors.REQUIRED_FIELD, True))
def test_nested_readonly_field_with_default_value(): schema = { "some_field": { "type": "dict", "schema": { "created": {"type": "string", "readonly": True, "default": "today"}, "modified": {"type": "string", "readonly": True, "default_setter": lambda d: d["created"]}, }, } } assert_success({"some_field": {}}, schema) expected_errors = [ ( ("some_field", "created"), ("some_field", "schema", "created", "readonly"), errors.READONLY_FIELD, schema["some_field"]["schema"]["created"]["readonly"], ), ( ("some_field", "modified"), ("some_field", "schema", "modified", "readonly"), errors.READONLY_FIELD, schema["some_field"]["schema"]["modified"]["readonly"], ), ] assert_fail({"some_field": {"created": "tomorrow", "modified": "now"}}, schema, errors=expected_errors) assert_fail({"some_field": {"created": "today", "modified": "today"}}, schema, errors=expected_errors)
def test_nested_unknown_keys(): schema = {"field1": {"type": "dict", "allow_unknown": True, "schema": {"nested1": {"type": "string"}}}} document = {"field1": {"nested1": "foo", "arb1": "bar", "arb2": 42}} assert_success(document=document, schema=schema) schema["field1"]["allow_unknown"] = {"type": "string"} assert_fail(document=document, schema=schema)
def test_allow_unknown_with_of_rules(): # https://github.com/pyeve/cerberus/issues/251 schema = { 'test': { 'oneof': [ { 'type': 'dict', 'allow_unknown': True, 'schema': {'known': {'type': 'string'}}, }, {'type': 'dict', 'schema': {'known': {'type': 'string'}}}, ] } } # check regression and that allow unknown does not cause any different # than expected behaviour for one-of. document = {'test': {'known': 's'}} assert_fail( document, schema, error=('test', ('test', 'oneof'), errors.ONEOF, schema['test']['oneof']), ) # check that allow_unknown is actually applied document = {'test': {'known': 's', 'unknown': 'asd'}} assert_success(document, schema)
def test_noneof(): # prop1 can not be: # - greater than 10 # - greater than 0 # - equal to -5, 5, or 15 schema = {"prop1": {"type": "integer", "noneof": [{"min": 0}, {"min": 10}, {"allowed": [-5, 5, 15]}]}} # document is valid doc = {"prop1": -1} assert_success(doc, schema) # document is not valid # prop1 is equal to -5 doc = {"prop1": -5} assert_fail(doc, schema) # document is not valid # prop1 greater than 0 doc = {"prop1": 1} assert_fail(doc, schema) # document is not valid doc = {"prop1": 5} assert_fail(doc, schema) # document is not valid doc = {"prop1": 11} assert_fail(doc, schema) # document is not valid # and equal to 15 doc = {"prop1": 15} assert_fail(doc, schema)
def test_bad_min_length(schema): field = 'a_string' min_length = schema[field]['minlength'] value = "".join(choice(ascii_lowercase) for i in range(min_length - 1)) assert_fail({field: value}, error=(field, (field, 'minlength'), errors.MIN_LENGTH, min_length, (len(value),)))
def test_nested_readonly_field_with_default_value(): schema = { 'some_field': { 'type': 'dict', 'schema': { 'created': { 'type': 'string', 'readonly': True, 'default': 'today' }, 'modified': { 'type': 'string', 'readonly': True, 'default_setter': lambda d: d['created'] } } } } assert_success({'some_field': {}}, schema) expected_errors = [ (('some_field', 'created'), ('some_field', 'schema', 'created', 'readonly'), errors.READONLY_FIELD, schema['some_field']['schema']['created']['readonly']), (('some_field', 'modified'), ('some_field', 'schema', 'modified', 'readonly'), errors.READONLY_FIELD, schema['some_field']['schema']['modified']['readonly'])] assert_fail({'some_field': {'created': 'tomorrow', 'modified': 'now'}}, schema, errors=expected_errors) assert_fail({'some_field': {'created': 'today', 'modified': 'today'}}, schema, errors=expected_errors)
def test_bad_min_length_binary(schema): field = 'a_binary' min_length = schema[field]['minlength'] value = b'\x00' * (min_length - 1) assert_fail({field: value}, error=(field, (field, 'minlength'), errors.MIN_LENGTH, min_length, (len(value),)))
def test_bad_list_of_dicts(schema, validator): field = 'a_list_of_dicts' subschema = schema['a_list_of_dicts']['schema'] value = [{'sku': 'KT123', 'price': '100'}] exp_child_errors = [((field, 0, 'price'), (field, 'schema', 'schema', 'price', 'type'), errors.BAD_TYPE, 'integer')] assert_fail({field: value}, validator=validator, error=(field, (field, 'schema'), errors.SEQUENCE_SCHEMA, subschema), child_errors=exp_child_errors) assert field in validator.errors assert 0 in validator.errors[field][-1] assert 'price' in validator.errors[field][-1][0][-1] exp_msg = errors.BasicErrorHandler.messages[errors.BAD_TYPE.code] \ .format(constraint='integer') assert exp_msg in validator.errors[field][-1][0][-1]['price'] value = ["not a dict"] exp_child_errors = [((field, 0), (field, 'schema', 'type'), errors.BAD_TYPE, 'dict', ())] assert_fail({field: value}, error=(field, (field, 'schema'), errors.SEQUENCE_SCHEMA, subschema), child_errors=exp_child_errors)
def test_ignore_none_values(): field = 'test' schema = {field: {'type': 'string', 'empty': False, 'required': False}} document = {field: None} # Test normal behaviour validator = Validator(schema, ignore_none_values=False) assert_fail(document, validator=validator) validator.schema[field]['required'] = True validator.schema.validate() _errors = assert_fail(document, validator=validator) assert_not_has_error(_errors, field, (field, 'required'), errors.REQUIRED_FIELD, True) # Test ignore None behaviour validator = Validator(schema, ignore_none_values=True) validator.schema[field]['required'] = False validator.schema.validate() assert_success(document, validator=validator) validator.schema[field]['required'] = True _errors = assert_fail(schema=schema, document=document, validator=validator) assert_has_error(_errors, field, (field, 'required'), errors.REQUIRED_FIELD, True) assert_not_has_error(_errors, field, (field, 'type'), errors.BAD_TYPE, 'string')
def test_anyof_2(): # these two schema should be the same schema1 = { "prop": { "anyof": [ {"type": "dict", "schema": {"val": {"type": "integer"}}}, {"type": "dict", "schema": {"val": {"type": "string"}}}, ] } } schema2 = { "prop": { "type": "dict", "anyof": [{"schema": {"val": {"type": "integer"}}}, {"schema": {"val": {"type": "string"}}}], } } doc = {"prop": {"val": 0}} assert_success(doc, schema1) assert_success(doc, schema2) doc = {"prop": {"val": "0"}} assert_success(doc, schema1) assert_success(doc, schema2) doc = {"prop": {"val": 1.1}} assert_fail(doc, schema1) assert_fail(doc, schema2)
def test_array_unallowed(): field = "an_array" value = ["agent", "client", "profit"] assert_fail( {field: value}, error=(field, (field, "allowed"), errors.UNALLOWED_VALUES, ["agent", "client", "vendor"], ["profit"]), )
def test_dependencies_errors(): v = Validator({'field1': {'required': False}, 'field2': {'required': True, 'dependencies': {'field1': ['one', 'two']}}}) assert_fail({'field1': 'three', 'field2': 7}, validator=v, error=('field2', ('field2', 'dependencies'), errors.DEPENDENCIES_FIELD_VALUE, {'field1': ['one', 'two']}, ({'field1': 'three'},)))
def test_dependencies_on_boolean_field_with_value_in_list(): # https://github.com/pyeve/cerberus/issues/138 schema = {'deleted': {'type': 'boolean'}, 'text': {'dependencies': {'deleted': [False]}}} assert_success({'text': 'foo', 'deleted': False}, schema) assert_fail({'text': 'foo', 'deleted': True}, schema) assert_fail({'text': 'foo'}, schema)
def test_regex(validator): field = "a_regex_email" assert_success({field: "*****@*****.**"}, validator=validator) assert_fail( {field: "invalid"}, update=True, error=(field, (field, "regex"), errors.REGEX_MISMATCH, "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"), )
def test_excludes(): schema = {'this_field': {'type': 'dict', 'excludes': 'that_field'}, 'that_field': {'type': 'dict'}} assert_success({'this_field': {}}, schema) assert_success({'that_field': {}}, schema) assert_success({}, schema) assert_fail({'that_field': {}, 'this_field': {}}, schema)
def test_dependencies_list_with_subodcuments_fields(): schema = { "test_field": {"dependencies": ["a_dict.foo", "a_dict.bar"]}, "a_dict": {"type": "dict", "schema": {"foo": {"type": "string"}, "bar": {"type": "string"}}}, } assert_success({"test_field": "foobar", "a_dict": {"foo": "foo", "bar": "bar"}}, schema) assert_fail({"test_field": "foobar", "a_dict": {}}, schema) assert_fail({"test_field": "foobar", "a_dict": {"foo": "foo"}}, schema)
def test_a_dict(): assert_success({'a_dict': {'address': 'i live here', 'city': 'in my own town'}}) assert_fail({'a_dict': {'address': 8545}}, errors=[ (('a_dict', 'address'), ('a_dict', 'schema', 'address', 'type'), errors.BAD_TYPE, 'string'), (('a_dict', 'city'), ('a_dict', 'schema', 'city', 'required'), errors.REQUIRED_FIELD, True) ])
def test_required_excludes(): schema = { "this_field": {"type": "dict", "excludes": "that_field", "required": True}, "that_field": {"type": "dict", "excludes": "this_field", "required": True}, } assert_success({"this_field": {}}, schema, update=False) assert_success({"that_field": {}}, schema, update=False) assert_fail({}, schema) assert_fail({"that_field": {}, "this_field": {}}, schema)
def test_a_dict(): assert_success({"a_dict": {"address": "i live here", "city": "in my own town"}}) assert_fail( {"a_dict": {"address": 8545}}, errors=[ (("a_dict", "address"), ("a_dict", "schema", "address", "type"), errors.BAD_TYPE, "string"), (("a_dict", "city"), ("a_dict", "schema", "city", "required"), errors.REQUIRED_FIELD, True), ], )
def test_mutual_excludes(): schema = { "this_field": {"type": "dict", "excludes": "that_field"}, "that_field": {"type": "dict", "excludes": "this_field"}, } assert_success({"this_field": {}}, schema) assert_success({"that_field": {}}, schema) assert_success({}, schema) assert_fail({"that_field": {}, "this_field": {}}, schema)
def test_unicode_allowed_py2(): """ Python 2.x encodes value of allowed using default encoding if the string includes characters outside ASCII range. Produced string does not match input which is an unicode string.""" # issue 280 doc = {'letters': u'♄εℓł☺'} schema = {'letters': {'type': 'string', 'allowed': ['♄εℓł☺']}} assert_fail(doc, schema)
def test_dependencies_list(): schema = { 'test_field': {'dependencies': ['foo', 'bar']}, 'foo': {'type': 'string'}, 'bar': {'type': 'string'} } assert_success({'test_field': 'foobar', 'foo': 'bar', 'bar': 'foo'}, schema) assert_fail({'test_field': 'foobar', 'foo': 'bar'}, schema)
def test_root_relative_dependencies(): # https://github.com/pyeve/cerberus/issues/288 schema = {'package': {'allow_unknown': True, 'schema': {'version': {'dependencies': '^repo'}}}, 'repo': {}} assert_fail({'package': {'repo': 'somewhere', 'version': 0}}, schema, error=(('package', 'version'), ('package', 'schema', 'version', 'dependencies'), errors.DEPENDENCIES_FIELD, '^repo', ('^repo',))) assert_success({'repo': 'somewhere', 'package': {'version': 1}}, schema)
def test_oneof_schema(): schema = {'oneof_schema': {'type': 'dict', 'oneof_schema': [{'digits': {'type': 'integer', 'min': 0, 'max': 99}}, {'text': {'type': 'string', 'regex': '^[0-9]{2}$'}}]}} assert_success({'oneof_schema': {'digits': 19}}, schema) assert_success({'oneof_schema': {'text': '84'}}, schema) assert_fail({'oneof_schema': {'digits': 19, 'text': '84'}}, schema)
def test_required_field(schema): field = 'a_required_string' required_string_extension = { 'a_required_string': {'type': 'string', 'minlength': 2, 'maxlength': 10, 'required': True}} schema.update(required_string_extension) assert_fail({'an_integer': 1}, schema, error=(field, (field, 'required'), errors.REQUIRED_FIELD, True))
def test_bad_valueschema(): field = 'a_dict_with_valueschema' schema_field = 'a_string' value = {schema_field: 'not an integer'} exp_child_errors = [ ((field, schema_field), (field, 'valueschema', 'type'), errors.BAD_TYPE, 'integer')] assert_fail({field: value}, error=(field, (field, 'valueschema'), errors.VALUESCHEMA, {'type': 'integer'}), child_errors=exp_child_errors)
def test_coerce_catches_TypeError(): schema = {'name': {'coerce': str.lower}} _errors = assert_fail({'name': 1234}, schema) _errors[0].info = () # ignore exception message here assert_has_error(_errors, 'name', ('name', 'coerce'), errors.COERCION_FAILED, str.lower)
def test_coerce_catches_ValueError(): schema = {'amount': {'coerce': int}} _errors = assert_fail({'amount': 'not_a_number'}, schema) _errors[0].info = () # ignore exception message here assert_has_error(_errors, 'amount', ('amount', 'coerce'), errors.COERCION_FAILED, int)
def test_nested_error_paths(validator): # interpreters of the same version on some platforms showed different sort results # over various runs: def assert_has_all_errors(errors, *ref_errs): for ref_err in ref_errs: for error in errors: if error == ref_err: break else: raise AssertionError schema = { 'a_dict': { 'keysrules': {'type': 'integer'}, 'valuesrules': {'regex': '[a-z]*'}, }, 'a_list': { 'itemsrules': {'type': 'string', 'oneof_regex': ['[a-z]*$', '[A-Z]*']} }, } document = { 'a_dict': {0: 'abc', 'one': 'abc', 2: 'aBc', 'three': 'abC'}, 'a_list': [0, 'abc', 'abC'], } assert_fail(document, schema, validator=validator) det = validator.document_error_tree set = validator.schema_error_tree assert len(det.errors) == 0 assert len(set.errors) == 0 assert len(det['a_dict'].errors) == 2 assert len(set['a_dict'].errors) == 0 assert det['a_dict'][0] is None assert len(det['a_dict']['one'].errors) == 1 assert len(det['a_dict'][2].errors) == 1 assert len(det['a_dict']['three'].errors) == 2 assert len(set['a_dict']['keysrules'].errors) == 1 assert len(set['a_dict']['valuesrules'].errors) == 1 assert len(set['a_dict']['keysrules']['type'].errors) == 2 assert len(set['a_dict']['valuesrules']['regex'].errors) == 2 ref_err1 = ValidationError( ('a_dict', 'one'), ('a_dict', 'keysrules', 'type'), errors.TYPE.code, 'type', 'integer', 'one', (), ) ref_err2 = ValidationError( ('a_dict', 2), ('a_dict', 'valuesrules', 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'aBc', (), ) ref_err3 = ValidationError( ('a_dict', 'three'), ('a_dict', 'keysrules', 'type'), errors.TYPE.code, 'type', 'integer', 'three', (), ) ref_err4 = ValidationError( ('a_dict', 'three'), ('a_dict', 'valuesrules', 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'abC', (), ) assert det['a_dict'][2].errors[0] == ref_err2 assert det['a_dict']['one'].errors[0] == ref_err1 assert_has_all_errors(det['a_dict']['three'].errors, ref_err3, ref_err4) assert_has_all_errors(set['a_dict']['keysrules']['type'].errors, ref_err1, ref_err3) assert_has_all_errors( set['a_dict']['valuesrules']['regex'].errors, ref_err2, ref_err4 ) assert len(det['a_list'].errors) == 1 assert len(det['a_list'][0].errors) == 1 assert det['a_list'][1] is None assert len(det['a_list'][2].errors) == 3 assert len(set['a_list'].errors) == 0 assert len(set['a_list']['itemsrules'].errors) == 1 assert len(set['a_list']['itemsrules']['type'].errors) == 1 assert len(set['a_list']['itemsrules']['oneof'][0]['regex'].errors) == 1 assert len(set['a_list']['itemsrules']['oneof'][1]['regex'].errors) == 1 ref_err5 = ValidationError( ('a_list', 0), ('a_list', 'itemsrules', 'type'), errors.TYPE.code, 'type', 'string', 0, (), ) ref_err6 = ValidationError( ('a_list', 2), ('a_list', 'itemsrules', 'oneof'), errors.ONEOF.code, 'oneof', 'irrelevant_at_this_point', 'abC', (), ) ref_err7 = ValidationError( ('a_list', 2), ('a_list', 'itemsrules', 'oneof', 0, 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'abC', (), ) ref_err8 = ValidationError( ('a_list', 2), ('a_list', 'itemsrules', 'oneof', 1, 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'abC', (), ) assert det['a_list'][0].errors[0] == ref_err5 assert_has_all_errors(det['a_list'][2].errors, ref_err6, ref_err7, ref_err8) assert set['a_list']['itemsrules']['oneof'].errors[0] == ref_err6 assert set['a_list']['itemsrules']['oneof'][0]['regex'].errors[0] == ref_err7 assert set['a_list']['itemsrules']['oneof'][1]['regex'].errors[0] == ref_err8 assert set['a_list']['itemsrules']['type'].errors[0] == ref_err5
def test_nullable_skips_type(validator): assert_fail({'an_integer': None}, validator=validator) assert validator.errors == {'an_integer': ['null value not allowed']}
def test_sequence_with_mapping_schema(): schema = {'list': {'schema': {'foo': {'allowed': ['a', 'b', 'c']}}, 'type': 'dict'}} document = {'list': ['a', 'b', 'c']} assert_fail(document, schema)
def test_type_error_aborts_validation(): schema = {'foo': {'type': 'string', 'allowed': ['a']}} document = {'foo': 0} assert_fail(document, schema, error=('foo', ('foo', 'type'), errors.BAD_TYPE, 'string'))
def test_unknown_field(validator): field = 'surname' assert_fail({field: 'doe'}, validator=validator, error=(field, (), errors.UNKNOWN_FIELD, None)) assert validator.errors == {field: ['unknown field']}
def test_a_dict_with_keyschema(): assert_success({'a_dict_with_keyschema': {'key': 'value'}}) assert_fail({'a_dict_with_keyschema': {'KEY': 'value'}})
def test_regex(validator): field = 'a_regex_email' assert_success({field: '*****@*****.**'}, validator=validator) assert_fail({field: 'invalid'}, update=True, error=(field, (field, 'regex'), errors.REGEX_MISMATCH, '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'))
def test_readonly_field(): field = 'a_readonly_string' assert_fail({field: 'update me if you can'}, error=(field, (field, 'readonly'), errors.READONLY_FIELD, True))
def test_nested_error_paths(validator): schema = { 'a_dict': { 'keyschema': { 'type': 'integer' }, 'valueschema': { 'regex': '[a-z]*' } }, 'a_list': { 'schema': { 'type': 'string', 'oneof_regex': ['[a-z]*$', '[A-Z]*'] } } } document = { 'a_dict': { 0: 'abc', 'one': 'abc', 2: 'aBc', 'three': 'abC' }, 'a_list': [0, 'abc', 'abC'] } assert_fail(document, schema, validator=validator) _det = validator.document_error_tree _set = validator.schema_error_tree assert len(_det.errors) == 0 assert len(_set.errors) == 0 assert len(_det['a_dict'].errors) == 2 assert len(_set['a_dict'].errors) == 0 assert _det['a_dict'][0] is None assert len(_det['a_dict']['one'].errors) == 1 assert len(_det['a_dict'][2].errors) == 1 assert len(_det['a_dict']['three'].errors) == 2 assert len(_set['a_dict']['keyschema'].errors) == 1 assert len(_set['a_dict']['valueschema'].errors) == 1 assert len(_set['a_dict']['keyschema']['type'].errors) == 2 assert len(_set['a_dict']['valueschema']['regex'].errors) == 2 _ref_err = ValidationError( ('a_dict', 'one'), ('a_dict', 'keyschema', 'type'), errors.BAD_TYPE.code, 'type', 'integer', 'one', ()) assert _det['a_dict']['one'].errors[0] == _ref_err assert _set['a_dict']['keyschema']['type'].errors[0] == _ref_err _ref_err = ValidationError( ('a_dict', 2), ('a_dict', 'valueschema', 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'aBc', ()) assert _det['a_dict'][2].errors[0] == _ref_err assert _set['a_dict']['valueschema']['regex'].errors[0] == _ref_err _ref_err = ValidationError( ('a_dict', 'three'), ('a_dict', 'keyschema', 'type'), errors.BAD_TYPE.code, 'type', 'integer', 'three', ()) assert _det['a_dict']['three'].errors[0] == _ref_err assert _set['a_dict']['keyschema']['type'].errors[1] == _ref_err _ref_err = ValidationError( ('a_dict', 'three'), ('a_dict', 'valueschema', 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'abC', ()) assert _det['a_dict']['three'].errors[1] == _ref_err assert _set['a_dict']['valueschema']['regex'].errors[1] == _ref_err assert len(_det['a_list'].errors) == 1 assert len(_det['a_list'][0].errors) == 1 assert _det['a_list'][1] is None assert len(_det['a_list'][2].errors) == 3 assert len(_set['a_list'].errors) == 0 assert len(_set['a_list']['schema'].errors) == 1 assert len(_set['a_list']['schema']['type'].errors) == 1 assert len(_set['a_list']['schema']['oneof'][0]['regex'].errors) == 1 assert len(_set['a_list']['schema']['oneof'][1]['regex'].errors) == 1 _ref_err = ValidationError(('a_list', 0), ('a_list', 'schema', 'type'), errors.BAD_TYPE.code, 'type', 'string', 0, ()) assert _det['a_list'][0].errors[0] == _ref_err assert _set['a_list']['schema']['type'].errors[0] == _ref_err _ref_err = ValidationError(('a_list', 2), ('a_list', 'schema', 'oneof'), errors.ONEOF.code, 'oneof', 'irrelevant_at_this_point', 'abC', ()) assert _det['a_list'][2].errors[0] == _ref_err assert _set['a_list']['schema']['oneof'].errors[0] == _ref_err _ref_err = ValidationError( ('a_list', 2), ('a_list', 'schema', 'oneof', 0, 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'abC', ()) assert _det['a_list'][2].errors[1] == _ref_err assert _set['a_list']['schema']['oneof'][0]['regex'].errors[0] == _ref_err _ref_err = ValidationError( ('a_list', 2), ('a_list', 'schema', 'oneof', 1, 'regex'), errors.REGEX_MISMATCH.code, 'regex', '[a-z]*$', 'abC', ()) assert _det['a_list'][2].errors[2] == _ref_err assert _set['a_list']['schema']['oneof'][1]['regex'].errors[0] == _ref_err
def test_max(schema, field, increment): max_value = schema[field]['max'] value = max_value + increment assert_fail({field: value}, error=(field, (field, 'max'), errors.MAX_VALUE, max_value))
def test_array_unallowed(): field = 'an_array' value = ['agent', 'client', 'profit'] assert_fail({field: value}, error=(field, (field, 'allowed'), errors.UNALLOWED_VALUES, ['agent', 'client', 'vendor'], ['profit']))
def test_forbidden_number(document): assert_fail(schema={'amount': {'forbidden': (0, 0.0)}}, document=document)
def test_anyof_in_itemsrules(validator): # test that a list of schemas can be specified. valid_parts = ( { 'schema': { 'model number': { 'type': 'string' }, 'count': { 'type': 'integer' } } }, { 'schema': { 'serial number': { 'type': 'string' }, 'count': { 'type': 'integer' } } }, ) valid_item = {'type': ['dict', 'string'], 'anyof': valid_parts} schema = {'parts': {'type': 'list', 'itemsrules': valid_item}} document = { 'parts': [ { 'model number': 'MX-009', 'count': 100 }, { 'serial number': '898-001' }, 'misc', ] } # document is valid. each entry in 'parts' matches a type or schema assert_success(document=document, schema=schema, validator=validator) document['parts'].append({'product name': "Monitors", 'count': 18}) # document is invalid. 'product name' does not match any valid schemas assert_fail(document=document, schema=schema, validator=validator) document['parts'].pop() # document is valid again assert_success(document=document, schema=schema, validator=validator) document['parts'].append({'product name': "Monitors", 'count': 18}) document['parts'].append(10) # and invalid. numbers are not allowed. _errors = assert_fail( document, schema, validator=validator, error=('parts', ('parts', 'itemsrules'), errors.ITEMSRULES, valid_item), child_errors=[ (('parts', 3), ('parts', 'itemsrules', 'anyof'), errors.ANYOF, valid_parts), ( ('parts', 4), ('parts', 'itemsrules', 'type'), errors.TYPE, ('dict', 'string'), ), ], ) assert_not_has_error( _errors, ('parts', 4), ('parts', 'itemsrules', 'anyof'), errors.ANYOF, valid_parts, ) # tests errors.BasicErrorHandler's tree representation _errors = validator.errors assert 'parts' in _errors assert 3 in _errors['parts'][-1] assert _errors['parts'][-1][3][0] == "no definitions validate" scope = _errors['parts'][-1][3][-1] assert 'anyof definition 0' in scope assert 'anyof definition 1' in scope assert scope['anyof definition 0'] == [{"product name": ["unknown field"]}] assert scope['anyof definition 1'] == [{"product name": ["unknown field"]}] assert _errors['parts'][-1][4] == [ "must be one of these types: ('dict', 'string')" ]
def test_bad_list_of_integers(): field = 'a_list_of_integers' value = [34, 'not an integer'] assert_fail({field: value})
def test_min_and_max_with_date(): schema = {'date': {'min': date(1900, 1, 1), 'max': date(1999, 12, 31)}} assert_success({'date': date(1945, 5, 8)}, schema) assert_fail({'date': date(1871, 5, 10)}, schema)
def test_dependencies_field(): schema = {'test_field': {'dependencies': 'foo'}, 'foo': {'type': 'string'}} assert_success({'test_field': 'foobar', 'foo': 'bar'}, schema) assert_fail({'test_field': 'foobar'}, schema)
def test_boolean_is_not_a_number(): # https://github.com/pyeve/cerberus/issues/144 assert_fail(schema={'value': {'type': 'number'}}, document={'value': True})
def test_rules_set_simple(): rules_set_registry.add('foo', {'type': 'integer'}) assert_success({'bar': 1}, {'bar': 'foo'}) assert_fail({'bar': 'one'}, {'bar': 'foo'})
def assert_bad_min_value(field, inc): min_value = schema[field]['min'] value = min_value - inc assert_fail({field: value}, error=(field, (field, 'min'), errors.MIN_VALUE, min_value))
def test_allow_unknown_as_reference(): rules_set_registry.add('foo', {'type': 'number'}) v = Validator(allow_unknown='foo') assert_success({0: 1}, {}, v) assert_fail({0: 'one'}, {}, v)
def assert_bad_max_value(field, inc): max_value = schema[field]['max'] value = max_value + inc assert_fail({field: value}, error=(field, (field, 'max'), errors.MAX_VALUE, max_value))
def test_dependencies_dict_with_required_field(): schema = { 'test_field': { 'required': True, 'dependencies': {'foo': 'foo', 'bar': 'bar'} }, 'foo': {'type': 'string'}, 'bar': {'type': 'string'} } # False: all dependencies missing assert_fail({'test_field': 'foobar'}, schema) # False: one of dependencies missing assert_fail({'test_field': 'foobar', 'foo': 'foo'}, schema) assert_fail({'test_field': 'foobar', 'bar': 'bar'}, schema) # False: dependencies are validated and field is required assert_fail({'foo': 'foo', 'bar': 'bar'}, schema) # False: All dependencies are optional, but field is still required assert_fail({}, schema) # False: dependency missing assert_fail({'foo': 'bar'}, schema) assert_success({'test_field': 'foobar', 'foo': 'foo', 'bar': 'bar'}, schema) # True: dependencies are validated but field is not required schema['test_field']['required'] = False assert_success({'foo': 'bar', 'bar': 'foo'}, schema)
def test_itemsrules(): assert_fail(document={'a_list_of_integers': [34, 'not an integer']})
def test_min(schema, field, decrement): min_value = schema[field]['min'] value = min_value - decrement assert_fail({field: value}, error=(field, (field, 'min'), errors.MIN_VALUE, min_value))
def test_integer_unallowed(): field = 'a_restricted_integer' value = 2 assert_fail({field: value}, error=(field, (field, 'allowed'), errors.UNALLOWED_VALUE, [-1, 0, 1], value))
def test_string_unallowed(): field = 'a_restricted_string' value = 'profit' assert_fail({field: value}, error=(field, (field, 'allowed'), errors.UNALLOWED_VALUE, ['agent', 'client', 'vendor'], value))
def test_mapping_with_sequence_schema(): schema = {'list': {'schema': {'allowed': ['a', 'b', 'c']}}} document = {'list': {'is_a': 'mapping'}} assert_fail(document, schema, error=('list', ('list', 'schema'), errors.BAD_TYPE_FOR_SCHEMA, schema['list']['schema']))
def test_minlength_with_dict(): schema = {'dict': {'minlength': 1}} assert_fail(document={'dict': {}}, schema=schema) assert_success(document={'dict': {'foo': 'bar'}}, schema=schema)