Allow String type to optionally deserialize empty strings

- Added optional keyword argument `allow_empty` to `colander.String`
  schema type. When True, deserializes an empty string to an
  empty string. When False (default), an empty string deserializes to
  `colander.null`.
This commit is contained in:
Lucas Taylor
2014-11-26 16:37:04 -07:00
parent 0b3d11aaca
commit 549c4ceb3b
4 changed files with 25 additions and 4 deletions

View File

@@ -21,6 +21,14 @@ Features
- Add a ``missing_msg`` argument to ``SchemaNode`` that specifies the error - Add a ``missing_msg`` argument to ``SchemaNode`` that specifies the error
message to be used when the node is required and missing message to be used when the node is required and missing
- ``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

@@ -122,6 +122,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

@@ -1113,7 +1113,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
@@ -1166,11 +1166,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:
@@ -1192,6 +1198,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

@@ -1439,9 +1439,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
@@ -1454,6 +1454,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()