Skip to content

Commit

Permalink
Trying to create an api for allowing a list of validators, deferred o…
Browse files Browse the repository at this point in the history
…r not.
  • Loading branch information
jayd3e committed Mar 19, 2013
1 parent ff6d8c2 commit 966f116
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 7 deletions.
31 changes: 24 additions & 7 deletions colander/__init__.py
Expand Up @@ -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)
Expand All @@ -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):
Expand Down Expand Up @@ -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."""
Expand Down
27 changes: 27 additions & 0 deletions colander/tests/test_colander.py
Expand Up @@ -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
Expand Down Expand Up @@ -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')
Expand Down

0 comments on commit 966f116

Please sign in to comment.