- Add a `pos argument to the colander.Invalid.add` method.
- Add a ``__setitem__`` method to the ``colander.Invalid`` class.
This commit is contained in:
@@ -10,6 +10,10 @@ Next release
|
|||||||
- Allow ``colander.Date`` and ``colander.DateTime`` invalid error
|
- Allow ``colander.Date`` and ``colander.DateTime`` invalid error
|
||||||
messages to be customized.
|
messages to be customized.
|
||||||
|
|
||||||
|
- Add a ``pos`` argument to the ``colander.Invalid.add`` method.
|
||||||
|
|
||||||
|
- Add a ``__setitem__`` method to the ``colander.Invalid`` class.
|
||||||
|
|
||||||
0.5 (2010-03-31)
|
0.5 (2010-03-31)
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,52 @@ class Invalid(Exception):
|
|||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.children = []
|
self.children = []
|
||||||
|
|
||||||
def add(self, exc):
|
def add(self, exc, pos=None):
|
||||||
""" Add a child exception; ``exc`` must be an instance of
|
""" Add a child exception; ``exc`` must be an instance of
|
||||||
:class:`colander.Invalid`"""
|
:class:`colander.Invalid` or a subclass.
|
||||||
|
|
||||||
|
``pos`` is a value important for accurate error reporting. If
|
||||||
|
it is provided, it must be an integer representing the
|
||||||
|
position of ``exc`` relative to all other subexceptions of
|
||||||
|
this exception node. For example, if the exception being
|
||||||
|
added is about the third child of the exception which is
|
||||||
|
``self``, ``pos`` might be passed as ``3``.
|
||||||
|
|
||||||
|
If ``pos`` is provided, it will be assigned to the ``pos``
|
||||||
|
attribute of the provided ``exc`` object.
|
||||||
|
|
||||||
|
The ``parent`` attribute of the provided ``exc`` will be set
|
||||||
|
as a reference to ``self``.
|
||||||
|
"""
|
||||||
exc.parent = self
|
exc.parent = self
|
||||||
|
if pos is not None:
|
||||||
|
exc.pos = pos
|
||||||
self.children.append(exc)
|
self.children.append(exc)
|
||||||
|
|
||||||
|
def __setitem__(self, name, msg):
|
||||||
|
""" Add a subexception related to a child node with the
|
||||||
|
message ``msg``. ``name`` must be present in the names of the
|
||||||
|
set of child nodes of this exception's node; if this is not so,
|
||||||
|
a ``KeyError`` is raised.
|
||||||
|
|
||||||
|
For example, if the exception upon which ``__setitem__`` is
|
||||||
|
called has a node attribute with children, and that node
|
||||||
|
attribute has children that have the names ``name`` and
|
||||||
|
``title``, you may successfully call ``__setitem__('name',
|
||||||
|
'Bad name')`` or ``__setitem__('title', 'Bad title')``. But
|
||||||
|
calling ``__setitem__('wrong', 'whoops')`` will result in a
|
||||||
|
KeyError.
|
||||||
|
|
||||||
|
This method is typically only useful if the ``node`` it wraps
|
||||||
|
is a schema node representing a mapping.
|
||||||
|
"""
|
||||||
|
for num, child in enumerate(self.node.children):
|
||||||
|
if child.name == name:
|
||||||
|
exc = Invalid(child, msg)
|
||||||
|
self.add(exc, num)
|
||||||
|
return
|
||||||
|
raise KeyError(name)
|
||||||
|
|
||||||
def paths(self):
|
def paths(self):
|
||||||
""" Return all paths through the exception graph """
|
""" Return all paths through the exception graph """
|
||||||
def traverse(node, stack):
|
def traverse(node, stack):
|
||||||
@@ -205,8 +245,7 @@ class Mapping(object):
|
|||||||
except Invalid, e:
|
except Invalid, e:
|
||||||
if error is None:
|
if error is None:
|
||||||
error = Invalid(node)
|
error = Invalid(node)
|
||||||
e.pos = num
|
error.add(e, num)
|
||||||
error.add(e)
|
|
||||||
|
|
||||||
if self.unknown_keys == 'raise':
|
if self.unknown_keys == 'raise':
|
||||||
if value:
|
if value:
|
||||||
@@ -280,8 +319,7 @@ class Tuple(Positional):
|
|||||||
except Invalid, e:
|
except Invalid, e:
|
||||||
if error is None:
|
if error is None:
|
||||||
error = Invalid(node)
|
error = Invalid(node)
|
||||||
e.pos = num
|
error.add(e, num)
|
||||||
error.add(e)
|
|
||||||
|
|
||||||
if error is not None:
|
if error is not None:
|
||||||
raise error
|
raise error
|
||||||
@@ -339,8 +377,7 @@ class Sequence(Positional):
|
|||||||
except Invalid, e:
|
except Invalid, e:
|
||||||
if error is None:
|
if error is None:
|
||||||
error = Invalid(node)
|
error = Invalid(node)
|
||||||
e.pos = num
|
error.add(e, num)
|
||||||
error.add(e)
|
|
||||||
|
|
||||||
if error is not None:
|
if error is not None:
|
||||||
raise error
|
raise error
|
||||||
|
|||||||
@@ -100,6 +100,23 @@ class TestInvalid(unittest.TestCase):
|
|||||||
"{'node1.node2.3': 'exc1; exc2; exc3', 'node1.node4': 'exc1; exc4'}"
|
"{'node1.node2.3': 'exc1; exc2; exc3', 'node1.node4': 'exc1; exc4'}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test___setitem__fails(self):
|
||||||
|
node = DummySchemaNode(None)
|
||||||
|
exc = self._makeOne(node, 'msg')
|
||||||
|
self.assertRaises(KeyError, exc.__setitem__, 'notfound', 'msg')
|
||||||
|
|
||||||
|
def test___setitem__succeeds(self):
|
||||||
|
node = DummySchemaNode(None)
|
||||||
|
child = DummySchemaNode(None)
|
||||||
|
child.name = 'found'
|
||||||
|
node.children = [child]
|
||||||
|
exc = self._makeOne(node, 'msg')
|
||||||
|
exc['found'] = 'msg2'
|
||||||
|
self.assertEqual(len(exc.children), 1)
|
||||||
|
childexc = exc.children[0]
|
||||||
|
self.assertEqual(childexc.pos, 0)
|
||||||
|
self.assertEqual(childexc.node.name, 'found')
|
||||||
|
|
||||||
class TestAll(unittest.TestCase):
|
class TestAll(unittest.TestCase):
|
||||||
def _makeOne(self, validators):
|
def _makeOne(self, validators):
|
||||||
from colander import All
|
from colander import All
|
||||||
|
|||||||
Reference in New Issue
Block a user