Add Set schematype
This commit is contained in:
@@ -11,6 +11,8 @@ Bug Fixes
|
||||
Features
|
||||
~~~~~~~~
|
||||
|
||||
- Add ``colander.Set`` type, ported from ``deform.Set``
|
||||
|
||||
- Add Python 3.3 to tox configuration and use newer tox testing regime
|
||||
(setup.py dev).
|
||||
|
||||
|
||||
@@ -107,4 +107,4 @@ Contributors
|
||||
- Atsushi Odagiri, 2012/02/04
|
||||
- Daniel Nouri, 2012/03/28
|
||||
- Gary van der Merwe, 2012/04/05
|
||||
- Domen Kožar, 2012-04-16
|
||||
- Domen Kožar, 2012/04/16
|
||||
|
||||
@@ -733,6 +733,40 @@ class Tuple(Positional, SchemaType):
|
||||
return appstruct[index]
|
||||
|
||||
|
||||
class Set(SchemaType):
|
||||
""" A type representing a non-overlapping set of items.
|
||||
Deserializes an iterable to a ``set`` object.
|
||||
|
||||
If the :attr:`colander.null` value is passed to the serialize
|
||||
method of this class, the :attr:`colander.null` value will be
|
||||
returned.
|
||||
|
||||
.. versionadded: 0.9.9.1
|
||||
|
||||
"""
|
||||
|
||||
def serialize(self, node, appstruct):
|
||||
if appstruct is null:
|
||||
return null
|
||||
|
||||
return appstruct
|
||||
|
||||
def deserialize(self, node, cstruct):
|
||||
if cstruct is null:
|
||||
return null
|
||||
|
||||
if not hasattr(cstruct, '__iter__'):
|
||||
raise Invalid(
|
||||
node,
|
||||
_('${cstruct} is not iterable', mapping={'cstruct': cstruct})
|
||||
)
|
||||
|
||||
cstruct = set(cstruct)
|
||||
if not cstruct:
|
||||
return null
|
||||
return cstruct
|
||||
|
||||
|
||||
class SequenceItems(list):
|
||||
"""
|
||||
List marker subclass for use by Sequence.cstruct_children, which indicates
|
||||
|
||||
@@ -949,6 +949,52 @@ class TestTuple(unittest.TestCase):
|
||||
result = typ.cstruct_children(node1, ['one', 'two'])
|
||||
self.assertEqual(result, ['one', 'two'])
|
||||
|
||||
|
||||
class TestSet(unittest.TestCase):
|
||||
def _makeOne(self, **kw):
|
||||
from colander import Set
|
||||
return Set(**kw)
|
||||
|
||||
def test_serialize(self):
|
||||
typ = self._makeOne()
|
||||
node = DummySchemaNode(typ)
|
||||
provided = []
|
||||
result = typ.serialize(node, provided)
|
||||
self.assertTrue(result is provided)
|
||||
|
||||
def test_serialize_null(self):
|
||||
from colander import null
|
||||
typ = self._makeOne()
|
||||
node = DummySchemaNode(typ)
|
||||
result = typ.serialize(node, null)
|
||||
self.assertTrue(result is null)
|
||||
|
||||
def test_deserialize_no_iter(self):
|
||||
typ = self._makeOne()
|
||||
node = DummySchemaNode(typ)
|
||||
e = invalid_exc(typ.deserialize, node, 1)
|
||||
self.assertEqual(e.msg, '${cstruct} is not iterable')
|
||||
|
||||
def test_deserialize_null(self):
|
||||
from colander import null
|
||||
typ = self._makeOne()
|
||||
node = DummySchemaNode(typ)
|
||||
result = typ.deserialize(node, null)
|
||||
self.assertEqual(result, null)
|
||||
|
||||
def test_deserialize_valid(self):
|
||||
typ = self._makeOne()
|
||||
node = DummySchemaNode(typ)
|
||||
result = typ.deserialize(node, ('a',))
|
||||
self.assertEqual(result, set(('a',)))
|
||||
|
||||
def test_deserialize_empty_set(self):
|
||||
import colander
|
||||
typ = self._makeOne()
|
||||
node = DummySchemaNode(typ)
|
||||
result = typ.deserialize(node, set())
|
||||
self.assertEqual(result, colander.null)
|
||||
|
||||
class TestSequence(unittest.TestCase):
|
||||
def _makeOne(self, **kw):
|
||||
from colander import Sequence
|
||||
|
||||
@@ -74,6 +74,8 @@ Types
|
||||
|
||||
.. autoclass:: Tuple
|
||||
|
||||
.. autoclass:: Set
|
||||
|
||||
.. autoclass:: Sequence
|
||||
|
||||
.. autoclass:: Seq
|
||||
|
||||
Reference in New Issue
Block a user