Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Set schematype (backported from deform.Set) #71

Merged
merged 3 commits into from Nov 21, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.txt
Expand Up @@ -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).

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTORS.txt
Expand Up @@ -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
31 changes: 31 additions & 0 deletions colander/__init__.py
Expand Up @@ -733,6 +733,37 @@ def get_value(self, node, appstruct, path):
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 is_nonstr_iter(cstruct):
raise Invalid(
node,
_('${cstruct} is not iterable', mapping={'cstruct': cstruct})
)

return set(cstruct)


class SequenceItems(list):
"""
List marker subclass for use by Sequence.cstruct_children, which indicates
Expand Down
52 changes: 52 additions & 0 deletions colander/tests/test_colander.py
Expand Up @@ -949,6 +949,58 @@ def test_cstruct_children_justright(self):
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_str_no_iter(self):
typ = self._makeOne()
node = DummySchemaNode(typ)
e = invalid_exc(typ.deserialize, node, "foo")
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, set())

class TestSequence(unittest.TestCase):
def _makeOne(self, **kw):
from colander import Sequence
Expand Down
2 changes: 2 additions & 0 deletions docs/api.rst
Expand Up @@ -74,6 +74,8 @@ Types

.. autoclass:: Tuple

.. autoclass:: Set

.. autoclass:: Sequence

.. autoclass:: Seq
Expand Down