- 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
|
||||
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)
|
||||
----------------
|
||||
|
||||
|
||||
@@ -27,12 +27,52 @@ class Invalid(Exception):
|
||||
self.msg = msg
|
||||
self.children = []
|
||||
|
||||
def add(self, exc):
|
||||
def add(self, exc, pos=None):
|
||||
""" 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
|
||||
if pos is not None:
|
||||
exc.pos = pos
|
||||
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):
|
||||
""" Return all paths through the exception graph """
|
||||
def traverse(node, stack):
|
||||
@@ -205,8 +245,7 @@ class Mapping(object):
|
||||
except Invalid, e:
|
||||
if error is None:
|
||||
error = Invalid(node)
|
||||
e.pos = num
|
||||
error.add(e)
|
||||
error.add(e, num)
|
||||
|
||||
if self.unknown_keys == 'raise':
|
||||
if value:
|
||||
@@ -280,8 +319,7 @@ class Tuple(Positional):
|
||||
except Invalid, e:
|
||||
if error is None:
|
||||
error = Invalid(node)
|
||||
e.pos = num
|
||||
error.add(e)
|
||||
error.add(e, num)
|
||||
|
||||
if error is not None:
|
||||
raise error
|
||||
@@ -339,8 +377,7 @@ class Sequence(Positional):
|
||||
except Invalid, e:
|
||||
if error is None:
|
||||
error = Invalid(node)
|
||||
e.pos = num
|
||||
error.add(e)
|
||||
error.add(e, num)
|
||||
|
||||
if error is not None:
|
||||
raise error
|
||||
|
||||
@@ -100,6 +100,23 @@ class TestInvalid(unittest.TestCase):
|
||||
"{'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):
|
||||
def _makeOne(self, validators):
|
||||
from colander import All
|
||||
|
||||
Reference in New Issue
Block a user