Skip to content

Commit

Permalink
Allow 'allow_unknown' for sub-documents
Browse files Browse the repository at this point in the history
  • Loading branch information
otibsa authored and nicolaiarocci committed Mar 25, 2015
1 parent c5541cb commit c289ff0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
17 changes: 13 additions & 4 deletions cerberus/cerberus.py
Expand Up @@ -115,7 +115,8 @@ class Validator(object):
.. versionadded:: 0.0.2
Support for addition and validation of custom data types.
"""
special_rules = "required", "nullable", "type", "dependencies", "readonly"
special_rules = "required", "nullable", "type", "dependencies", "readonly",\
"allow_unknown", "schema"

def __init__(self, schema=None, transparent_schema_rules=False,
ignore_none_values=False, allow_unknown=False):
Expand Down Expand Up @@ -226,6 +227,12 @@ def _validate(self, document, schema=None, update=False, context=None):
if self.errors.get(field):
continue

if 'schema' in definition:
self._validate_schema(definition['schema'],
field,
value,
definition.get('allow_unknown'))

definition_rules = [rule for rule in definition.keys()
if rule not in self.special_rules]
for rule in definition_rules:
Expand Down Expand Up @@ -290,8 +297,6 @@ def validate_schema(self, schema):
if not hasattr(self, '_validate_type_' + value):
raise SchemaError(
errors.ERROR_UNKNOWN_TYPE % value)
elif constraint in self.special_rules:
pass
elif constraint == 'schema':
constraint_type = constraints.get('type')
if constraint_type == 'list':
Expand All @@ -300,6 +305,8 @@ def validate_schema(self, schema):
self.validate_schema(value)
else:
raise SchemaError(errors.ERROR_SCHEMA_TYPE % field)
elif constraint in self.special_rules:
pass
elif constraint == 'items':
if isinstance(value, Mapping):
# list of dicts, deprecated
Expand Down Expand Up @@ -426,7 +433,7 @@ def _validate_empty(self, empty, field, value):
if isinstance(value, _str_type) and len(value) == 0 and not empty:
self._error(field, errors.ERROR_EMPTY_NOT_ALLOWED)

def _validate_schema(self, schema, field, value):
def _validate_schema(self, schema, field, value, nested_allow_unknown):
if isinstance(value, Sequence):
list_errors = {}
for i in range(len(value)):
Expand All @@ -439,6 +446,8 @@ def _validate_schema(self, schema, field, value):
elif isinstance(value, Mapping):
validator = copy.copy(self)
validator.schema = schema
if not validator.allow_unknown:
validator.allow_unknown = nested_allow_unknown
validator.validate(value, context=self.document,
update=self.update)
if len(validator.errors):
Expand Down
20 changes: 20 additions & 0 deletions cerberus/tests/tests.py
Expand Up @@ -514,6 +514,26 @@ def _validate_type_foo(self, field, value):
self.assertSuccess(document={"fred": "foo", "barney": "foo"},
validator=v)

def test_nested_unknown_keys(self):
schema = {
'field1': {
'type': 'dict',
'allow_unknown': True,
'schema': {'nested1': {'type': 'string'}}
}
}
document = {
'field1': {
'nested1': 'foo',
'arb1': 'bar',
'arb2': 42
}
}
self.assertSuccess(document=document, schema=schema)

schema['field1']['allow_unknown'] = {'type': 'string'}
self.assertFail(document=document, schema=schema)

def test_novalidate_noerrors(self):
'''In v0.1.0 and below `self.errors` raised an exception if no
validation had been performed yet.
Expand Down

0 comments on commit c289ff0

Please sign in to comment.