Trying to create an api for allowing a list of validators, deferred or n... #95

Closed
wants to merge 1 commit into
from
Jump to file or symbol
Failed to load files and symbols.
+51 −7
Split
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
@tseaver

tseaver Nov 26, 2014

Owner

Please don't import the package at testcase module scope. Move this code inside a helper method, e.g.

def _makeDummyDeferredValidateor(self):
    from colander import deferred
    def _validator(node, kw):
        return DummyValidator(kw..get('message', 'Deferred'))
    return deferred(_validator)
+@deferred
+def DummyDeferredValidator(node, kw):
+ return DummyValidator(kw.get('message', 'Deferred'))
+
class Uncooperative(object):
def __str__(self):
raise ValueError('I wont cooperate')