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
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
---------

View File

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

View File

@@ -1113,7 +1113,7 @@ Seq = Sequence
class String(SchemaType):
""" A type representing a Unicode string.
This type constructor accepts one argument:
This type constructor accepts two arguments:
``encoding``
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`
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
this type are ignored.
"""
def __init__(self, encoding=None):
def __init__(self, encoding=None, allow_empty=False):
self.encoding = encoding
self.allow_empty = allow_empty
def serialize(self, node, appstruct):
if appstruct is null:
@@ -1192,6 +1198,9 @@ class String(SchemaType):
mapping={'val':appstruct, 'err':e})
)
def deserialize(self, node, cstruct):
if cstruct == '' and self.allow_empty:
return text_type('')
if not cstruct:
return null

View File

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