Merge branch '146-deserialize-empty-string' of ltvolks/colander into pr/199

This commit is contained in:
Michael Merickel
2016-01-19 10:47:28 -06:00
4 changed files with 25 additions and 4 deletions

View File

@@ -60,6 +60,14 @@ Features
- Add ``normalize`` option to ``Decimal``, stripping the rightmost - Add ``normalize`` option to ``Decimal``, stripping the rightmost
trailing zeros. trailing zeros.
- ``colander.String`` schema type now supports an optional keyword argument
``allow_empty`` which, when True, deserializes an empty string to an
empty string. When False (default), an empty string deserializes to
``colander.null``. This allows for a node to be explicitly required, but
allow an empty ('') value to be provided.
https://github.com/Pylons/colander/issues/199
Bug Fixes Bug Fixes
--------- ---------

View File

@@ -124,6 +124,7 @@ Contributors
- Gouji Ochiai, 2014/08/21 - Gouji Ochiai, 2014/08/21
- Tim Tisdall, 2014/09/10 - Tim Tisdall, 2014/09/10
- Romain Commandé, 2014/10/11 - Romain Commandé, 2014/10/11
- Lucas Taylor, 2014/11/26
- Nando Florestan, 2014/11/27 - Nando Florestan, 2014/11/27
- Amos Latteier, 2014/11/30 - Amos Latteier, 2014/11/30
- Jimmy Thrasibule, 2014/12/11 - Jimmy Thrasibule, 2014/12/11

View File

@@ -1159,7 +1159,7 @@ Seq = Sequence
class String(SchemaType): class String(SchemaType):
""" A type representing a Unicode string. """ A type representing a Unicode string.
This type constructor accepts one argument: This type constructor accepts two arguments:
``encoding`` ``encoding``
Represents the encoding which should be applied to value Represents the encoding which should be applied to value
@@ -1212,11 +1212,17 @@ class String(SchemaType):
encoding. If this is not true, an :exc:`colander.Invalid` encoding. If this is not true, an :exc:`colander.Invalid`
error will result. error will result.
``allow_empty``
Boolean, if True allows deserialization of an empty string. If
False (default), empty strings will deserialize to
:attr:`colander.null`
The subnodes of the :class:`colander.SchemaNode` that wraps The subnodes of the :class:`colander.SchemaNode` that wraps
this type are ignored. this type are ignored.
""" """
def __init__(self, encoding=None): def __init__(self, encoding=None, allow_empty=False):
self.encoding = encoding self.encoding = encoding
self.allow_empty = allow_empty
def serialize(self, node, appstruct): def serialize(self, node, appstruct):
if appstruct is null: if appstruct is null:
@@ -1240,6 +1246,9 @@ class String(SchemaType):
mapping={'val':appstruct, 'err':e}) mapping={'val':appstruct, 'err':e})
) )
def deserialize(self, node, cstruct): def deserialize(self, node, cstruct):
if cstruct == '' and self.allow_empty:
return text_type('')
if not cstruct: if not cstruct:
return null return null

View File

@@ -1466,9 +1466,9 @@ class TestSequence(unittest.TestCase):
self.assertEqual(result, SequenceItems(['a'])) self.assertEqual(result, SequenceItems(['a']))
class TestString(unittest.TestCase): class TestString(unittest.TestCase):
def _makeOne(self, encoding=None): def _makeOne(self, encoding=None, allow_empty=False):
from colander import String from colander import String
return String(encoding) return String(encoding, allow_empty)
def test_alias(self): def test_alias(self):
from colander import Str from colander import Str
@@ -1481,6 +1481,9 @@ class TestString(unittest.TestCase):
typ = self._makeOne(None) typ = self._makeOne(None)
result = typ.deserialize(node, '') result = typ.deserialize(node, '')
self.assertEqual(result, null) self.assertEqual(result, null)
typ = self._makeOne(None, allow_empty=True)
result = typ.deserialize(node, '')
self.assertEqual(result, '')
def test_deserialize_uncooperative(self): def test_deserialize_uncooperative(self):
val = Uncooperative() val = Uncooperative()