Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'All' does not lose children exceptions #27

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.txt
@@ -1,6 +1,11 @@
Changes
=======

Unreleased
----------

- ``All`` does not lose children exceptions.

0.9.4 (2011-10-14)
------------------

Expand Down
9 changes: 7 additions & 2 deletions colander/__init__.py
Expand Up @@ -147,7 +147,7 @@ def asdict(self):
keyparts = []
msgs = []
for exc in path:
exc.msg and msgs.append(exc.msg)
exc.msg and msgs.extend(exc.messages())
keyname = exc._keyname()
keyname and keyparts.append(keyname)
errors['.'.join(keyparts)] = '; '.join(interpolate(msgs))
Expand All @@ -166,14 +166,19 @@ def __init__(self, *validators):

def __call__(self, node, value):
msgs = []
excs = []
for validator in self.validators:
try:
validator(node, value)
except Invalid, e:
excs.append(e)
msgs.append(e.msg)

if msgs:
raise Invalid(node, msgs)
exc = Invalid(node, msgs)
for e in excs:
e.children and exc.children.extend(e.children)
raise exc

class Function(object):
""" Validator which accepts a function and an optional message;
Expand Down
41 changes: 39 additions & 2 deletions colander/tests.py
Expand Up @@ -89,6 +89,27 @@ def test_asdict(self):
self.assertEqual(d, {'node1.node2.3': 'exc1; exc2; exc3',
'node1.node4': 'exc1; exc4'})

def test_asdict_using_All(self):
from colander import All
from colander import Positional
node1 = DummySchemaNode(None, 'node1')
node2 = DummySchemaNode(Positional(), 'node2')
node3 = DummySchemaNode(Positional(), 'node3')
node1.children = [node3]
validator1 = DummyValidator('validator1')
validator2 = DummyValidator('validator2')
validator = All(validator1, validator2)
exc1 = self._makeOne(node1, 'exc1')
exc1.pos = 1
exc1['node3'] = 'message1'
exc2 = self._makeOne(node2, 'exc2')
exc3 = invalid_exc(validator, None, None)
exc1.add(exc2, 2)
exc2.add(exc3, 3)
d = exc1.asdict()
self.assertEqual(d, {'node1.node2.3': 'exc1; exc2; validator1; validator2',
'node1.node3': 'exc1; message1'})

def test___str__(self):
from colander import Positional
node1 = DummySchemaNode(None, 'node1')
Expand Down Expand Up @@ -154,6 +175,19 @@ def test_failure(self):
e = invalid_exc(validator, None, None)
self.assertEqual(e.msg, ['msg1', 'msg2'])

def test_Invalid_children(self):
from colander import Invalid
node1 = DummySchemaNode(None, 'node1')
node = DummySchemaNode(None, 'node')
node.children = [node1]
exc1 = Invalid(node1, 'exc1')
exc2 = Invalid(node1, 'exc2')
validator1 = DummyValidator('validator1', [exc1])
validator2 = DummyValidator('validator2', [exc2])
validator = self._makeOne([validator1, validator2])
exc = invalid_exc(validator, node, None)
self.assertEqual(exc.children, [exc1, exc2])

class TestFunction(unittest.TestCase):
def _makeOne(self, *arg, **kw):
from colander import Function
Expand Down Expand Up @@ -2419,13 +2453,16 @@ def __getitem__(self, name):
return child

class DummyValidator(object):
def __init__(self, msg=None):
def __init__(self, msg=None, children=None):
self.msg = msg
self.children = children

def __call__(self, node, value):
from colander import Invalid
if self.msg:
raise Invalid(node, self.msg)
e = Invalid(node, self.msg)
self.children and e.children.extend(self.children)
raise e

class Uncooperative(object):
def __str__(self):
Expand Down