colander
colander copied to clipboard
Validation for colander.Mapping() too liberal
In colander/init.py:405-412 (class Mapping(SchemaType)) there's this validation procedure:
def _validate(self, node, value):
try:
return dict(value)
except Exception, e:
raise Invalid(…)
The problem is that dict.init will convert to dictionary almost anything:
| dict(iterable) -> new dictionary initialized as if via: | d = {} | for k, v in iterable: | d[k] = v
Which means that all of these validate correctly:
- dict( "" )
- dict( [] )
- dict( () )
This is inconsistent with, for example, behavior of colander.String. Zero-value list will result in colander.null:
In colander/init.py:793-759 (class String(SchemaType))
def deserialize(self, node, cstruct):
if not cstruct:
return null
And any([bool( [] ), bool( {} ), bool( "" ), bool( set() ), bool( frozenset() )]) => False
I'd like to propose to either check explicitly for dict-like functionality (setitem, getitem), or to at least make the behavior consistent with colander.String (“if not cstruct” instead of “if cstruct is null” in colander/init.py:456).
All of those types(lists, strings, sets, frozensets) all implement getitem/setitem, so we can't explicitly check for those. So should we just allow a 'dict' to pass through?