diff --git a/colander/__init__.py b/colander/__init__.py index e035c303..0edec75f 100644 --- a/colander/__init__.py +++ b/colander/__init__.py @@ -40,6 +40,15 @@ def __reduce__(self): null = _null() +class _drop(object): + """ + Represents a value that should be dropped if it is missing during + deserialization. + """ + pass + +drop = _drop() + def interpolate(msgs): for s in msgs: if hasattr(s, 'interpolate'): @@ -531,11 +540,14 @@ def _impl(self, node, value, callback): name = subnode.name subval = value.pop(name, null) try: - result[name] = callback(subnode, subval) + sub_result = callback(subnode, subval) except Invalid as e: if error is None: error = Invalid(node) error.add(e, num) + else: + if sub_result is not drop: + result[name] = sub_result if self.unknown == 'raise': if value: diff --git a/colander/tests/test_colander.py b/colander/tests/test_colander.py index 127dce4a..ff1dbbe7 100644 --- a/colander/tests/test_colander.py +++ b/colander/tests/test_colander.py @@ -2895,6 +2895,16 @@ class MySchema(colander.Schema): self.assertEqual(node.children[2].title, '') self.assertEqual(node.children[3].title, 'thing2') + def test_deserialize_drop(self): + import colander + class MySchema(colander.Schema): + a = colander.SchemaNode(colander.String()) + b = colander.SchemaNode(colander.String(), missing=colander.drop) + node = MySchema() + expected = {'a': 'test'} + result = node.deserialize(expected) + self.assertEqual(result, expected) + class TestSequenceSchema(unittest.TestCase): def test_succeed(self): import colander