Permalink
Browse files

Trying to create an api for allowing a list of validators, deferred o…

…r not.
  • Loading branch information...
1 parent ff6d8c2 commit 966f116d190dcf82ba2f825a9af7bd03cd786fc7 @jayd3e jayd3e committed Mar 19, 2013
Showing with 51 additions and 7 deletions.
  1. +24 −7 colander/__init__.py
  2. +27 −0 colander/tests/test_colander.py
View
@@ -1813,10 +1813,10 @@ def deserialize(self, cstruct=null):
appstruct = self.typ.deserialize(self, cstruct)
if self.preparer is not None:
- # if the preparer is a function, call a single preparer
+ # if the preparer is a callable, call a single preparer
if hasattr(self.preparer, '__call__'):
appstruct = self.preparer(appstruct)
- # if the preparer is a list, call each separate preparer
+ # if the preparer is an iterable, call each separate preparer
elif is_nonstr_iter(self.preparer):
for preparer in self.preparer:
appstruct = preparer(appstruct)
@@ -1831,8 +1831,14 @@ def deserialize(self, cstruct=null):
return appstruct
if self.validator is not None:
- if not isinstance(self.validator, deferred): # unbound
- self.validator(self, appstruct)
+ # if the validator is not an iterable, turn it into one
+ if not is_nonstr_iter(self.validator):
+ self.validator = [self.validator]
+
+ for validator in self.validator:
+ if not isinstance(validator, deferred):
+ validator(self, appstruct)
+
return appstruct
def add(self, node):
@@ -1888,12 +1894,23 @@ def _bind(self, kw):
names = dir(self)
for k in names:
v = getattr(self, k)
- if isinstance(v, deferred):
- v = v(self, kw)
- setattr(self, k, v)
+ self._find_deferreds(kw, k, v)
if getattr(self, 'after_bind', None):
self.after_bind(self, kw)
+ def _find_deferreds(self, kw, k, v):
+ if isinstance(v, deferred):
+ v = v(self, kw)
+ setattr(self, k, v)
+ elif is_nonstr_iter(v):
+ new_v = []
+ for item in v:
+ if isinstance(v, deferred):
+ new_v.append(item(self, kw))
+ else:
+ new_v.append(item)
+ setattr(self, k, new_v)
+
def cstruct_children(self, cstruct):
""" Will call the node's type's ``cstruct_children`` method with this
node as a first argument, and ``cstruct`` as a second argument."""
@@ -2242,6 +2242,28 @@ def test_deserialize_with_validator(self):
e = invalid_exc(node.deserialize, 1)
self.assertEqual(e.msg, 'Wrong')
+ def test_deserialize_deferred_validator(self):
+ typ = DummyType()
+ node = self._makeOne(typ, validator=DummyDeferredValidator)
+ node = node.bind(message='good')
+ e = invalid_exc(node.deserialize, 1)
+ self.assertEqual(e.msg, 'good')
+
+ def test_deserialize_all_with_deferred_validator(self):
+ typ = DummyType()
+ node = self._makeOne(typ, validator=[DummyDeferredValidator])
+ node = node.bind(message='good')
+ e = invalid_exc(node.deserialize, 1)
+ self.assertEqual(e.msg, 'good')
+
+ def test_deserialize_all_with_deferred_and_normal_validator(self):
+ typ = DummyType()
+ validator = DummyValidator(msg='Wrong')
+ node = self._makeOne(typ, validator=[DummyDeferredValidator, validator])
+ node = node.bind(message='good')
+ e = invalid_exc(node.deserialize, 1)
+ self.assertEqual(e.msg, 'good')
+
def test_deserialize_value_is_null_no_missing(self):
from colander import null
from colander import Invalid
@@ -3363,6 +3385,11 @@ def __call__(self, node, value):
self.children and e.children.extend(self.children)
raise e
+from colander import deferred
+@deferred
+def DummyDeferredValidator(node, kw):
+ return DummyValidator(kw.get('message', 'Deferred'))
+
class Uncooperative(object):
def __str__(self):
raise ValueError('I wont cooperate')

0 comments on commit 966f116

Please sign in to comment.