# -*- coding:utf-8 -*- import unittest from colander.compat import text_, text_type def invalid_exc(func, *arg, **kw): from colander import Invalid try: func(*arg, **kw) except Invalid as e: return e else: raise AssertionError('Invalid not raised') # pragma: no cover class TestInvalid(unittest.TestCase): def _makeOne(self, node, msg=None, val=None): from colander import Invalid exc = Invalid(node, msg, val) return exc def test_ctor(self): exc = self._makeOne(None, 'msg', 'val') self.assertEqual(exc.node, None) self.assertEqual(exc.msg, 'msg') self.assertEqual(exc.value, 'val') self.assertEqual(exc.children, []) def test_add(self): exc = self._makeOne(None, 'msg') other = Dummy() exc.add(other) self.assertFalse(hasattr(other, 'positional')) self.assertEqual(exc.children, [other]) def test_add_positional(self): from colander import Positional p = Positional() node = DummySchemaNode(p) exc = self._makeOne(node, 'msg') other = Dummy() exc.add(other) self.assertEqual(other.positional, True) self.assertEqual(exc.children, [other]) def test__keyname_no_parent(self): node = DummySchemaNode(None, name='name') exc = self._makeOne(None, '') exc.node = node self.assertEqual(exc._keyname(), 'name') def test__keyname_positional(self): exc = self._makeOne(None, '') exc.positional = True exc.pos = 2 self.assertEqual(exc._keyname(), '2') def test__keyname_nonpositional_parent(self): parent = Dummy() parent.node = DummySchemaNode(None) exc = self._makeOne(None, 'me') exc.parent = parent exc.pos = 2 exc.node = DummySchemaNode(None, name='name') self.assertEqual(exc._keyname(), 'name') def test_paths(self): exc1 = self._makeOne(None, 'exc1') exc2 = self._makeOne(None, 'exc2') exc3 = self._makeOne(None, 'exc3') exc4 = self._makeOne(None, 'exc4') exc1.add(exc2) exc2.add(exc3) exc1.add(exc4) paths = list(exc1.paths()) self.assertEqual(paths, [(exc1, exc2, exc3), (exc1, exc4)]) def test_asdict(self): from colander import Positional node1 = DummySchemaNode(None, 'node1') node2 = DummySchemaNode(Positional(), 'node2') node3 = DummySchemaNode(Positional(), 'node3') node4 = DummySchemaNode(Positional(), 'node4') exc1 = self._makeOne(node1, 'exc1') exc1.pos = 1 exc2 = self._makeOne(node2, 'exc2') exc3 = self._makeOne(node3, 'exc3') exc4 = self._makeOne(node4, 'exc4') exc1.add(exc2, 2) exc2.add(exc3, 3) exc1.add(exc4, 4) d = exc1.asdict() self.assertEqual(d, {'node1.node2.3': 'exc1; exc2; exc3', 'node1.node4': 'exc1; exc4'}) def test_asdict_with_all_validator(self): # see https://github.com/Pylons/colander/pull/27 from colander import All from colander import Positional node1 = DummySchemaNode(None, 'node1') node2 = DummySchemaNode(Positional(), 'node2') node3 = DummySchemaNode(Positional(), 'node3') node1.children = [node3] validator1 = DummyValidator('validator1') validator2 = DummyValidator('validator2') validator = All(validator1, validator2) exc1 = self._makeOne(node1, 'exc1') exc1.pos = 1 exc1['node3'] = 'message1' exc2 = self._makeOne(node2, 'exc2') exc3 = invalid_exc(validator, None, None) exc1.add(exc2, 2) exc2.add(exc3, 3) d = exc1.asdict() self.assertEqual(d, {'node1.node2.3': 'exc1; exc2; validator1; validator2', 'node1.node3': 'exc1; message1'}) def test_asdict_with_all_validator_functional(self): # see https://github.com/Pylons/colander/issues/2 import colander as c class MySchema(c.MappingSchema): number1 = c.SchemaNode(c.Int(), validator=c.Range(min=1)) number2 = c.SchemaNode(c.Int(), validator=c.Range(min=1)) def validate_higher(node, val): if val['number1'] >= val['number2']: raise c.Invalid(node, 'Number 1 must be lower than number 2') def validate_different(node, val): if val['number1'] == val['number2']: raise c.Invalid(node, "They can't be the same, either") schema = MySchema(validator=c.All(validate_higher, validate_different)) try: schema.deserialize(dict(number1=2, number2=2)) except c.Invalid as e: result = e.asdict() self.assertEqual( result, {'': ("Number 1 must be lower than number 2; " "They can't be the same, either")}) def test___str__(self): from colander import Positional node1 = DummySchemaNode(None, 'node1') node2 = DummySchemaNode(Positional(), 'node2') node3 = DummySchemaNode(Positional(), 'node3') node4 = DummySchemaNode(Positional(), 'node4') exc1 = self._makeOne(node1, 'exc1') exc1.pos = 1 exc2 = self._makeOne(node2, 'exc2') exc3 = self._makeOne(node3, 'exc3') exc4 = self._makeOne(node4, 'exc4') exc1.add(exc2, 2) exc2.add(exc3, 3) exc1.add(exc4, 4) result = str(exc1) self.assertEqual( result, "{'node1.node2.3': 'exc1; exc2; exc3', 'node1.node4': 'exc1; exc4'}" ) def test___setitem__fails(self): node = DummySchemaNode(None) exc = self._makeOne(node, 'msg') self.assertRaises(KeyError, exc.__setitem__, 'notfound', 'msg') def test___setitem__succeeds(self): node = DummySchemaNode(None) child = DummySchemaNode(None) child.name = 'found' node.children = [child] exc = self._makeOne(node, 'msg') exc['found'] = 'msg2' self.assertEqual(len(exc.children), 1) childexc = exc.children[0] self.assertEqual(childexc.pos, 0) self.assertEqual(childexc.node.name, 'found') def test_messages_msg_iterable(self): node = DummySchemaNode(None) exc = self._makeOne(node, [123, 456]) self.assertEqual(exc.messages(), [123, 456]) def test_messages_msg_not_iterable(self): node = DummySchemaNode(None) exc = self._makeOne(node, 'msg') self.assertEqual(exc.messages(), ['msg']) def test_messages_msg_None(self): node = DummySchemaNode(None) exc = self._makeOne(node, None) self.assertEqual(exc.messages(), []) class TestAll(unittest.TestCase): def _makeOne(self, validators): from colander import All return All(*validators) def test_success(self): validator1 = DummyValidator() validator2 = DummyValidator() validator = self._makeOne([validator1, validator2]) self.assertEqual(validator(None, None), None) def test_failure(self): validator1 = DummyValidator('msg1') validator2 = DummyValidator('msg2') validator = self._makeOne([validator1, validator2]) e = invalid_exc(validator, None, None) self.assertEqual(e.msg, ['msg1', 'msg2']) def test_Invalid_children(self): from colander import Invalid node1 = DummySchemaNode(None, 'node1') node = DummySchemaNode(None, 'node') node.children = [node1] exc1 = Invalid(node1, 'exc1') exc2 = Invalid(node1, 'exc2') validator1 = DummyValidator('validator1', [exc1]) validator2 = DummyValidator('validator2', [exc2]) validator = self._makeOne([validator1, validator2]) exc = invalid_exc(validator, node, None) self.assertEqual(exc.children, [exc1, exc2]) class TestAny(unittest.TestCase): def _makeOne(self, validators): from colander import Any return Any(*validators) def test_success(self): validator1 = DummyValidator('msg1') validator2 = DummyValidator() validator = self._makeOne([validator1, validator2]) self.assertEqual(validator(None, None), None) def test_failure(self): validator1 = DummyValidator('msg1') validator2 = DummyValidator('msg2') validator = self._makeOne([validator1, validator2]) e = invalid_exc(validator, None, None) self.assertEqual(e.msg, ['msg1', 'msg2']) def test_Invalid_children(self): from colander import Invalid node1 = DummySchemaNode(None, 'node1') node = DummySchemaNode(None, 'node') node.children = [node1] exc1 = Invalid(node1, 'exc1') validator1 = DummyValidator('validator1', [exc1]) validator2 = DummyValidator() validator = self._makeOne([validator1, validator2]) self.assertEqual(validator(None, None), None) class TestFunction(unittest.TestCase): def _makeOne(self, *arg, **kw): from colander import Function return Function(*arg, **kw) def test_success_function_returns_True(self): validator = self._makeOne(lambda x: True) self.assertEqual(validator(None, None), None) def test_fail_function_returns_empty_string(self): validator = self._makeOne(lambda x: '') e = invalid_exc(validator, None, None) self.assertEqual(e.msg, 'Invalid value') def test_fail_function_returns_False(self): validator = self._makeOne(lambda x: False) e = invalid_exc(validator, None, None) self.assertEqual(e.msg, 'Invalid value') def test_fail_function_returns_string(self): validator = self._makeOne(lambda x: 'fail') e = invalid_exc(validator, None, None) self.assertEqual(e.msg, 'fail') def test_deprecated_message(self): import warnings orig_warn = warnings.warn log = [] def warn(message, category=None, stacklevel=1): log.append((message, category, stacklevel)) try: # Monkey patching warn so that tests run quietly warnings.warn = warn validator = self._makeOne(lambda x: False, message='depr') e = invalid_exc(validator, None, None) self.assertEqual(e.msg.interpolate(), 'depr') finally: warnings.warn = orig_warn def test_deprecated_message_warning(self): import warnings orig_warn = warnings.warn log = [] def warn(message, category=None, stacklevel=1): log.append((message, category, stacklevel)) try: # Monkey patching warn since catch_warnings context manager # is not working when running the full suite warnings.warn = warn validator = self._makeOne(lambda x: False, message='depr') invalid_exc(validator, None, None) self.assertEqual(len(log), 1) finally: warnings.warn = orig_warn def test_msg_and_message_error(self): self.assertRaises(ValueError, self._makeOne, lambda x: False, msg='one', message='two') def test_error_message_adds_mapping_to_configured_message(self): validator = self._makeOne(lambda x: False, msg='fail ${val}') e = invalid_exc(validator, None, None) self.assertEqual(e.msg.interpolate(), 'fail None') def test_error_message_adds_mapping_to_return_message(self): validator = self._makeOne(lambda x: 'fail ${val}') e = invalid_exc(validator, None, None) self.assertEqual(e.msg.interpolate(), 'fail None') def test_error_message_does_not_overwrite_configured_domain(self): import translationstring _ = translationstring.TranslationStringFactory('fnord') validator = self._makeOne(lambda x: False, msg=_('fail ${val}')) e = invalid_exc(validator, None, None) self.assertEqual(e.msg.domain, 'fnord') def test_error_message_does_not_overwrite_returned_domain(self): import translationstring _ = translationstring.TranslationStringFactory('fnord') validator = self._makeOne(lambda x: _('fail ${val}')) e = invalid_exc(validator, None, None) self.assertEqual(e.msg.domain, 'fnord') def test_propagation(self): validator = self._makeOne(lambda x: 'a' in x, 'msg') self.assertRaises(TypeError, validator, None, None) class TestRange(unittest.TestCase): def _makeOne(self, **kw): from colander import Range return Range(**kw) def test_success_no_bounds(self): validator = self._makeOne() self.assertEqual(validator(None, 1), None) def test_success_upper_bound_only(self): validator = self._makeOne(max=1) self.assertEqual(validator(None, -1), None) def test_success_minimum_bound_only(self): validator = self._makeOne(min=0) self.assertEqual(validator(None, 1), None) def test_success_min_and_max(self): validator = self._makeOne(min=1, max=1) self.assertEqual(validator(None, 1), None) def test_min_failure(self): validator = self._makeOne(min=1) e = invalid_exc(validator, None, 0) self.assertEqual(e.msg.interpolate(), '0 is less than minimum value 1') def test_min_failure_msg_override(self): validator = self._makeOne(min=1, min_err='wrong') e = invalid_exc(validator, None, 0) self.assertEqual(e.msg, 'wrong') def test_max_failure(self): validator = self._makeOne(max=1) e = invalid_exc(validator, None, 2) self.assertEqual(e.msg.interpolate(), '2 is greater than maximum value 1') def test_max_failure_msg_override(self): validator = self._makeOne(max=1, max_err='wrong') e = invalid_exc(validator, None, 2) self.assertEqual(e.msg, 'wrong') class TestRegex(unittest.TestCase): def _makeOne(self, pattern): from colander import Regex return Regex(pattern) def test_valid_regex(self): self.assertEqual(self._makeOne('a')(None, 'a'), None) self.assertEqual(self._makeOne('[0-9]+')(None, '1111'), None) self.assertEqual(self._makeOne('')(None, ''), None) self.assertEqual(self._makeOne('.*')(None, ''), None) def test_invalid_regexs(self): from colander import Invalid self.assertRaises(Invalid, self._makeOne('[0-9]+'), None, 'a') self.assertRaises(Invalid, self._makeOne('a{2,4}'), None, 'ba') def test_regex_not_string(self): from colander import Invalid import re regex = re.compile('[0-9]+') self.assertEqual(self._makeOne(regex)(None, '01'), None) self.assertRaises(Invalid, self._makeOne(regex), None, 't') class TestEmail(unittest.TestCase): def _makeOne(self): from colander import Email return Email() def test_valid_emails(self): validator = self._makeOne() self.assertEqual(validator(None, 'me@here.com'), None) self.assertEqual(validator(None, 'me1@here1.com'), None) self.assertEqual(validator(None, 'name@here1.us'), None) self.assertEqual(validator(None, 'name@here1.info'), None) self.assertEqual(validator(None, 'foo@bar.baz.biz'), None) self.assertEqual(validator(None, "tip'oneill@house.gov"), None) def test_empty_email(self): validator = self._makeOne() e = invalid_exc(validator, None, '') self.assertEqual(e.msg, 'Invalid email address') def test_invalid_emails(self): validator = self._makeOne() from colander import Invalid self.assertRaises(Invalid, validator, None, 'me@here.') self.assertRaises(Invalid, validator, None, 'name@here.tldiswaytoolooooooooong') self.assertRaises(Invalid, validator, None, '@here.us') self.assertRaises(Invalid, validator, None, 'me@here..com') self.assertRaises(Invalid, validator, None, 'me@we-here-.com') class TestLength(unittest.TestCase): def _makeOne(self, min=None, max=None): from colander import Length return Length(min=min, max=max) def test_success_no_bounds(self): validator = self._makeOne() self.assertEqual(validator(None, ''), None) def test_success_upper_bound_only(self): validator = self._makeOne(max=1) self.assertEqual(validator(None, 'a'), None) def test_success_minimum_bound_only(self): validator = self._makeOne(min=0) self.assertEqual(validator(None, ''), None) def test_success_min_and_max(self): validator = self._makeOne(min=1, max=1) self.assertEqual(validator(None, 'a'), None) def test_min_failure(self): validator = self._makeOne(min=1) e = invalid_exc(validator, None, '') self.assertEqual(e.msg.interpolate(), 'Shorter than minimum length 1') def test_max_failure(self): validator = self._makeOne(max=1) e = invalid_exc(validator, None, 'ab') self.assertEqual(e.msg.interpolate(), 'Longer than maximum length 1') class TestOneOf(unittest.TestCase): def _makeOne(self, values): from colander import OneOf return OneOf(values) def test_success(self): validator = self._makeOne([1]) self.assertEqual(validator(None, 1), None) def test_failure(self): validator = self._makeOne([1, 2]) e = invalid_exc(validator, None, None) self.assertEqual(e.msg.interpolate(), '"None" is not one of 1, 2') class TestContainsOnly(unittest.TestCase): def _makeOne(self, values): from colander import ContainsOnly return ContainsOnly(values) def test_success(self): validator = self._makeOne([1]) self.assertEqual(validator(None, [1]), None) def test_failure(self): validator = self._makeOne([1]) e = invalid_exc(validator, None, [2]) self.assertEqual( e.msg.interpolate(), 'One or more of the choices you made was not acceptable' ) def test_failure_with_custom_error_template(self): validator = self._makeOne([1]) from colander import _ validator.err_template = _('${val}: ${choices}') e = invalid_exc(validator, None, [2]) self.assertTrue('[2]' in e.msg.interpolate()) class Test_luhnok(unittest.TestCase): def _callFUT(self, node, value): from colander import luhnok return luhnok(node, value) def test_fail(self): import colander val = '10' self.assertRaises(colander.Invalid, self._callFUT, None, val) def test_fail2(self): import colander val = '99999999999999999999999' self.assertRaises(colander.Invalid, self._callFUT, None, val) def test_fail3(self): import colander val = 'abcdefghij' self.assertRaises(colander.Invalid, self._callFUT, None, val) def test_success(self): val = '4111111111111111' self.assertFalse(self._callFUT(None, val)) class Test_url_validator(unittest.TestCase): def _callFUT(self, val): from colander import url return url(None, val) def test_it_success(self): val = 'http://example.com' result = self._callFUT(val) self.assertEqual(result, None) def test_it_failure(self): val = 'not-a-url' from colander import Invalid self.assertRaises(Invalid, self._callFUT, val) class TestSchemaType(unittest.TestCase): def _makeOne(self, *arg, **kw): from colander import SchemaType return SchemaType(*arg, **kw) def test_flatten(self): node = DummySchemaNode(None, name='node') typ = self._makeOne() result = typ.flatten(node, 'appstruct') self.assertEqual(result, {'node':'appstruct'}) def test_flatten_listitem(self): node = DummySchemaNode(None, name='node') typ = self._makeOne() result = typ.flatten(node, 'appstruct', listitem=True) self.assertEqual(result, {'':'appstruct'}) def test_unflatten(self): node = DummySchemaNode(None, name='node') typ = self._makeOne() result = typ.unflatten(node, ['node'], {'node': 'appstruct'}) self.assertEqual(result, 'appstruct') def test_set_value(self): typ = self._makeOne() self.assertRaises( AssertionError, typ.set_value, None, None, None, None) def test_get_value(self): typ = self._makeOne() self.assertRaises( AssertionError, typ.get_value, None, None, None) def test_cstruct_children(self): typ = self._makeOne() self.assertEqual(typ.cstruct_children(None, None), []) class TestMapping(unittest.TestCase): def _makeOne(self, *arg, **kw): from colander import Mapping return Mapping(*arg, **kw) def test_ctor_bad_unknown(self): self.assertRaises(ValueError, self._makeOne, 'badarg') def test_ctor_good_unknown(self): try: self._makeOne('ignore') self._makeOne('raise') self._makeOne('preserve') except ValueError as e: # pragma: no cover raise AssertionError(e) def test_deserialize_not_a_mapping(self): node = DummySchemaNode(None) typ = self._makeOne() # None e = invalid_exc(typ.deserialize, node, None) self.assertTrue( e.msg.interpolate().startswith('"None" is not a mapping type')) # list e = invalid_exc(typ.deserialize, node, []) self.assertTrue( e.msg.interpolate().startswith('"[]" is not a mapping type')) # str e = invalid_exc(typ.deserialize, node, "") self.assertTrue( e.msg.interpolate().startswith('"" is not a mapping type')) # tuple e = invalid_exc(typ.deserialize, node, ()) self.assertTrue( e.msg.interpolate().startswith('"()" is not a mapping type')) def test_deserialize_null(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, colander.null) self.assertEqual(result, colander.null) def test_deserialize_no_subnodes(self): node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, {}) self.assertEqual(result, {}) def test_deserialize_ok(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() result = typ.deserialize(node, {'a':1}) self.assertEqual(result, {'a':1}) def test_deserialize_unknown_raise(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne(unknown='raise') e = invalid_exc(typ.deserialize, node, {'a':1, 'b':2}) self.assertEqual(e.msg.interpolate(), "Unrecognized keys in mapping: \"{'b': 2}\"") def test_deserialize_unknown_preserve(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne(unknown='preserve') result = typ.deserialize(node, {'a':1, 'b':2}) self.assertEqual(result, {'a':1, 'b':2}) def test_deserialize_subnodes_raise(self): node = DummySchemaNode(None) node.children = [ DummySchemaNode(None, name='a', exc='Wrong 2'), DummySchemaNode(None, name='b', exc='Wrong 2'), ] typ = self._makeOne() e = invalid_exc(typ.deserialize, node, {'a':1, 'b':2}) self.assertEqual(e.msg, None) self.assertEqual(len(e.children), 2) def test_deserialize_subnode_missing_default(self): import colander node = DummySchemaNode(None) node.children = [ DummySchemaNode(None, name='a'), DummySchemaNode(None, name='b', default='abc'), ] typ = self._makeOne() result = typ.deserialize(node, {'a':1}) self.assertEqual(result, {'a':1, 'b':colander.null}) def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, {}) def test_serialize_not_a_mapping(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, None) self.assertTrue( e.msg.interpolate().startswith('"None" is not a mapping type')) def test_serialize_no_subnodes(self): node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, {}) self.assertEqual(result, {}) def test_serialize_ok(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() result = typ.serialize(node, {'a':1}) self.assertEqual(result, {'a':1}) def test_serialize_with_unknown(self): node = DummySchemaNode(None) node.children = [ DummySchemaNode(None, name='a'), ] typ = self._makeOne() result = typ.serialize(node, {'a':1, 'b':2}) self.assertEqual(result, {'a':1}) def test_serialize_value_is_null(self): node = DummySchemaNode(None) from colander import null node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() result = typ.serialize(node, null) self.assertEqual(result, {'a':null}) def test_serialize_value_has_drop(self): from colander import drop node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() result = typ.serialize(node, {'a':drop}) self.assertEqual(result, {}) def test_flatten(self): node = DummySchemaNode(None, name='node') int1 = DummyType() int2 = DummyType() node.children = [ DummySchemaNode(int1, name='a'), DummySchemaNode(int2, name='b'), ] typ = self._makeOne() result = typ.flatten(node, {'a':1, 'b':2}) self.assertEqual(result, {'node.appstruct': 2}) def test_flatten_listitem(self): node = DummySchemaNode(None, name='node') int1 = DummyType() int2 = DummyType() node.children = [ DummySchemaNode(int1, name='a'), DummySchemaNode(int2, name='b'), ] typ = self._makeOne() result = typ.flatten(node, {'a':1, 'b':2}, listitem=True) self.assertEqual(result, {'appstruct': 2}) def test_unflatten(self): node = DummySchemaNode(None, name='node') int1 = DummyType() int2 = DummyType() node.children = [ DummySchemaNode(int1, name='a'), DummySchemaNode(int2, name='b'), ] typ = self._makeOne() result = typ.unflatten(node, ['node', 'node.a', 'node.b'], {'node': {'a':1, 'b':2}, 'node.a':1, 'node.b':2}) self.assertEqual(result, {'a': 1, 'b': 2}) def test_unflatten_nested(self): node = DummySchemaNode(None, name='node') inttype = DummyType() one = DummySchemaNode(self._makeOne(), name='one') one.children = [ DummySchemaNode(inttype, name='a'), DummySchemaNode(inttype, name='b'), ] two = DummySchemaNode(self._makeOne(), name='two') two.children = [ DummySchemaNode(inttype, name='c'), DummySchemaNode(inttype, name='d'), ] node.children = [one, two] typ = self._makeOne() result = typ.unflatten( node, ['node', 'node.one', 'node.one.a', 'node.one.b', 'node.two', 'node.two.c', 'node.two.d'], {'node': {'one': {'a': 1, 'b': 2}, 'two': {'c': 3, 'd': 4}}, 'node.one': {'a': 1, 'b': 2}, 'node.two': {'c': 3, 'd': 4}, 'node.one.a': 1, 'node.one.b': 2, 'node.two.c': 3, 'node.two.d': 4,}) self.assertEqual(result, { 'one': {'a': 1, 'b': 2}, 'two': {'c': 3, 'd': 4}}) def test_set_value(self): typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node1.children = [node2] appstruct = {'node2': {'foo': 'foo', 'baz': 'baz'}} typ.set_value(node1, appstruct, 'node2.foo', 'bar') self.assertEqual(appstruct, {'node2': {'foo': 'bar', 'baz': 'baz'}}) def test_get_value(self): typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node1.children = [node2] appstruct = {'node2': {'foo': 'bar', 'baz': 'baz'}} self.assertEqual(typ.get_value(node1, appstruct, 'node2'), {'foo': 'bar', 'baz': 'baz'}) self.assertEqual(typ.get_value(node1, appstruct, 'node2.foo'), 'bar') def test_cstruct_children_cstruct_is_null(self): from colander import null typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node1.children = [node2] result = typ.cstruct_children(node1, null) self.assertEqual(result, [null]) def test_cstruct_children(self): from colander import null typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node3 = DummySchemaNode(typ, name='node3') node1.children = [node2, node3] result = typ.cstruct_children(node1, {'node2':'abc'}) self.assertEqual(result, ['abc', null]) class TestTuple(unittest.TestCase): def _makeOne(self): from colander import Tuple return Tuple() def test_deserialize_not_iterable(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, None) self.assertEqual( e.msg.interpolate(), '"None" is not iterable') self.assertEqual(e.node, node) def test_deserialize_no_subnodes(self): node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, ()) self.assertEqual(result, ()) def test_deserialize_null(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, colander.null) self.assertEqual(result, colander.null) def test_deserialize_ok(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() result = typ.deserialize(node, ('a',)) self.assertEqual(result, ('a',)) def test_deserialize_toobig(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() e = invalid_exc(typ.deserialize, node, ('a','b')) self.assertEqual(e.msg.interpolate(), "\"('a', 'b')\" has an incorrect number of elements (expected 1, was 2)") def test_deserialize_toosmall(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() e = invalid_exc(typ.deserialize, node, ()) self.assertEqual(e.msg.interpolate(), '"()" has an incorrect number of elements (expected 1, was 0)') def test_deserialize_subnodes_raise(self): node = DummySchemaNode(None) node.children = [ DummySchemaNode(None, name='a', exc='Wrong 2'), DummySchemaNode(None, name='b', exc='Wrong 2'), ] typ = self._makeOne() e = invalid_exc(typ.deserialize, node, ('1', '2')) self.assertEqual(e.msg, None) self.assertEqual(len(e.children), 2) def test_serialize_null(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, colander.null) self.assertEqual(result, colander.null) def test_serialize_not_iterable(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, None) self.assertEqual( e.msg.interpolate(), '"None" is not iterable') self.assertEqual(e.node, node) def test_serialize_no_subnodes(self): node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, ()) self.assertEqual(result, ()) def test_serialize_ok(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() result = typ.serialize(node, ('a',)) self.assertEqual(result, ('a',)) def test_serialize_toobig(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() e = invalid_exc(typ.serialize, node, ('a','b')) self.assertEqual(e.msg.interpolate(), "\"('a', 'b')\" has an incorrect number of elements (expected 1, was 2)") def test_serialize_toosmall(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() e = invalid_exc(typ.serialize, node, ()) self.assertEqual(e.msg.interpolate(), '"()" has an incorrect number of elements (expected 1, was 0)' ) def test_serialize_subnodes_raise(self): node = DummySchemaNode(None) node.children = [ DummySchemaNode(None, name='a', exc='Wrong 2'), DummySchemaNode(None, name='b', exc='Wrong 2'), ] typ = self._makeOne() e = invalid_exc(typ.serialize, node, ('1', '2')) self.assertEqual(e.msg, None) self.assertEqual(len(e.children), 2) def test_flatten(self): node = DummySchemaNode(None, name='node') int1 = DummyType() int2 = DummyType() node.children = [ DummySchemaNode(int1, name='a'), DummySchemaNode(int2, name='b'), ] typ = self._makeOne() result = typ.flatten(node, (1, 2)) self.assertEqual(result, {'node.appstruct': 2}) def test_flatten_listitem(self): node = DummySchemaNode(None, name='node') int1 = DummyType() int2 = DummyType() node.children = [ DummySchemaNode(int1, name='a'), DummySchemaNode(int2, name='b'), ] typ = self._makeOne() result = typ.flatten(node, (1, 2), listitem=True) self.assertEqual(result, {'appstruct': 2}) def test_unflatten(self): node = DummySchemaNode(None, name='node') int1 = DummyType() int2 = DummyType() node.children = [ DummySchemaNode(int1, name='a'), DummySchemaNode(int2, name='b'), ] typ = self._makeOne() result = typ.unflatten(node, ['node', 'node.a', 'node.b'], {'node': (1, 2), 'node.a': 1, 'node.b': 2}) self.assertEqual(result, (1, 2)) def test_set_value(self): typ = self._makeOne() node = DummySchemaNode(typ, name='node') node.children = [ DummySchemaNode(typ, name='foo'), DummySchemaNode(typ, name='bar') ] node['foo'].children = [ DummySchemaNode(None, name='a'), DummySchemaNode(None, name='b'), ] node['bar'].children = [ DummySchemaNode(None, name='c'), DummySchemaNode(None, name='d'), ] appstruct = ((1, 2), (3, 4)) result = typ.set_value(node, appstruct, 'bar.c', 34) self.assertEqual(result, ((1, 2), (34, 4))) def test_set_value_bad_path(self): typ = self._makeOne() node = DummySchemaNode(typ, name='node') node.children = [ DummySchemaNode(None, name='foo'), DummySchemaNode(None, name='bar') ] self.assertRaises( KeyError, typ.set_value, node, (1, 2), 'foobar', 34) def test_get_value(self): typ = self._makeOne() node = DummySchemaNode(typ, name='node') node.children = [ DummySchemaNode(typ, name='foo'), DummySchemaNode(typ, name='bar') ] node['foo'].children = [ DummySchemaNode(None, name='a'), DummySchemaNode(None, name='b'), ] node['bar'].children = [ DummySchemaNode(None, name='c'), DummySchemaNode(None, name='d'), ] appstruct = ((1, 2), (3, 4)) self.assertEqual(typ.get_value(node, appstruct, 'foo'), (1, 2)) self.assertEqual(typ.get_value(node, appstruct, 'foo.b'), 2) def test_get_value_bad_path(self): typ = self._makeOne() node = DummySchemaNode(typ, name='node') node.children = [ DummySchemaNode(None, name='foo'), DummySchemaNode(None, name='bar') ] self.assertRaises( KeyError, typ.get_value, node, (1, 2), 'foobar') def test_cstruct_children_cstruct_is_null(self): from colander import null typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node1.children = [node2] result = typ.cstruct_children(node1, null) self.assertEqual(result, [null]) def test_cstruct_children_toomany(self): typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node3 = DummySchemaNode(typ, name='node3') node1.children = [node2, node3] result = typ.cstruct_children(node1, ['one', 'two', 'three']) self.assertEqual(result, ['one', 'two']) def test_cstruct_children_toofew(self): from colander import null typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node3 = DummySchemaNode(typ, name='node3') node1.children = [node2, node3] result = typ.cstruct_children(node1, ['one']) self.assertEqual(result, ['one', null]) def test_cstruct_children_justright(self): typ = self._makeOne() node1 = DummySchemaNode(typ, name='node1') node2 = DummySchemaNode(typ, name='node2') node3 = DummySchemaNode(typ, name='node3') node1.children = [node2, node3] 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 TestList(unittest.TestCase): def _makeOne(self, **kw): from colander import List return List(**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', 'z', 'b')) self.assertEqual(result, ['a', 'z', 'b']) def test_deserialize_empty_set(self): import colander typ = self._makeOne() node = DummySchemaNode(typ) result = typ.deserialize(node, ()) self.assertEqual(result, []) class TestSequence(unittest.TestCase): def _makeOne(self, **kw): from colander import Sequence return Sequence(**kw) def test_alias(self): from colander import Seq from colander import Sequence self.assertEqual(Seq, Sequence) def test_deserialize_not_iterable(self): node = DummySchemaNode(None) typ = self._makeOne() node.children = [node] e = invalid_exc(typ.deserialize, node, None) self.assertEqual( e.msg.interpolate(), '"None" is not iterable') self.assertEqual(e.node, node) def test_deserialize_not_iterable_accept_scalar(self): node = DummySchemaNode(None) typ = self._makeOne(accept_scalar=True) node.children = [node] result = typ.deserialize(node, None) self.assertEqual(result, [None]) def test_deserialize_string_accept_scalar(self): node = DummySchemaNode(None) typ = self._makeOne(accept_scalar=True) node.children = [node] result = typ.deserialize(node, 'abc') self.assertEqual(result, ['abc']) def test_deserialize_no_subnodes(self): typ = self._makeOne() node = DummySchemaNode(None) node.children = [node] result = typ.deserialize(node, ()) self.assertEqual(result, []) def test_deserialize_no_null(self): import colander typ = self._makeOne() result = typ.deserialize(None, colander.null) self.assertEqual(result, colander.null) def test_deserialize_ok(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() node.children = [node] result = typ.deserialize(node, ('a',)) self.assertEqual(result, ['a']) def test_deserialize_subnodes_raise(self): node = DummySchemaNode(None, exc='Wrong') typ = self._makeOne() node.children = [node] e = invalid_exc(typ.deserialize, node, ('1', '2')) self.assertEqual(e.msg, None) self.assertEqual(len(e.children), 2) def test_serialize_null(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, colander.null) self.assertEqual(result, colander.null) def test_serialize_not_iterable(self): node = DummySchemaNode(None) typ = self._makeOne() node.children = [node] e = invalid_exc(typ.serialize, node, None) self.assertEqual( e.msg.interpolate(), '"None" is not iterable') self.assertEqual(e.node, node) def test_serialize_not_iterable_accept_scalar(self): node = DummySchemaNode(None) typ = self._makeOne(accept_scalar=True) node.children = [node] result = typ.serialize(node, None) self.assertEqual(result, [None]) def test_serialize_string_accept_scalar(self): node = DummySchemaNode(None) typ = self._makeOne(accept_scalar=True) node.children = [node] result = typ.serialize(node, 'abc') self.assertEqual(result, ['abc']) def test_serialize_no_subnodes(self): node = DummySchemaNode(None) node.children = [node] typ = self._makeOne() result = typ.serialize(node, ()) self.assertEqual(result, []) def test_serialize_ok(self): node = DummySchemaNode(None) node.children = [DummySchemaNode(None, name='a')] typ = self._makeOne() result = typ.serialize(node, ('a',)) self.assertEqual(result, ['a']) def test_serialize_subnodes_raise(self): node = DummySchemaNode(None, exc='Wrong') typ = self._makeOne() node.children = [node] e = invalid_exc(typ.serialize, node, ('1', '2')) self.assertEqual(e.msg, None) self.assertEqual(len(e.children), 2) def test_flatten(self): node = DummySchemaNode(None, name='node') node.children = [ DummySchemaNode(DummyType(), name='foo'), ] typ = self._makeOne() result = typ.flatten(node, [1, 2]) self.assertEqual(result, {'node.0': 1, 'node.1': 2}) def test_flatten_listitem(self): node = DummySchemaNode(None, name='node') node.children = [ DummySchemaNode(DummyType(), name='foo'), ] typ = self._makeOne() result = typ.flatten(node, [1, 2], listitem=True) self.assertEqual(result, {'0': 1, '1': 2}) def test_unflatten(self): node = DummySchemaNode(None, name='node') node.children = [ DummySchemaNode(DummyType(), name='foo'), ] typ = self._makeOne() result = typ.unflatten(node, ['node.0', 'node.1',], {'node.0': 'a', 'node.1': 'b'}) self.assertEqual(result, ['a', 'b']) def test_setvalue(self): typ = self._makeOne() node1 = DummySchemaNode(typ, name='seq1') node2 = DummySchemaNode(typ, name='seq2') node1.children = [node2] node2.children = DummySchemaNode(None, name='items') appstruct = [[1, 2], [3, 4]] typ.set_value(node1, appstruct, '1.0', 34) self.assertEqual(appstruct, [[1, 2], [34, 4]]) def test_getvalue(self): typ = self._makeOne() node1 = DummySchemaNode(typ, name='seq1') node2 = DummySchemaNode(typ, name='seq2') node1.children = [node2] node2.children = DummySchemaNode(None, name='items') appstruct = [[1, 2], [3, 4]] self.assertEqual(typ.get_value(node1, appstruct, '1'), [3, 4]) self.assertEqual(typ.get_value(node1, appstruct, '1.0'), 3) def test_cstruct_children_cstruct_is_null(self): from colander import null from colander import SequenceItems typ = self._makeOne() result = typ.cstruct_children(None, null) self.assertEqual(result, SequenceItems([])) def test_cstruct_children_cstruct_is_non_null(self): from colander import SequenceItems typ = self._makeOne() result = typ.cstruct_children(None, ['a']) self.assertEqual(result, SequenceItems(['a'])) class TestString(unittest.TestCase): def _makeOne(self, encoding=None): from colander import String return String(encoding) def test_alias(self): from colander import Str from colander import String self.assertEqual(Str, String) def test_deserialize_emptystring(self): from colander import null node = DummySchemaNode(None) typ = self._makeOne(None) result = typ.deserialize(node, '') self.assertEqual(result, null) def test_deserialize_uncooperative(self): val = Uncooperative() node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) self.assertTrue(e.msg) def test_deserialize_unicode_from_None(self): uni = text_(b'\xe3\x81\x82', 'utf-8') node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, uni) self.assertEqual(result, uni) def test_deserialize_nonunicode_from_None(self): import colander value = object() node = DummySchemaNode(None) typ = self._makeOne() self.assertRaises(colander.Invalid, typ.deserialize, node, value) def test_deserialize_from_utf8(self): uni = text_(b'\xe3\x81\x82', encoding='utf-8') utf8 = uni.encode('utf-8') node = DummySchemaNode(None) typ = self._makeOne('utf-8') result = typ.deserialize(node, utf8) self.assertEqual(result, uni) def test_deserialize_from_utf16(self): uni = text_(b'\xe3\x81\x82', encoding='utf-8') utf16 = uni.encode('utf-16') node = DummySchemaNode(None) typ = self._makeOne('utf-16') result = typ.deserialize(node, utf16) self.assertEqual(result, uni) def test_deserialize_from_nonstring_obj(self): import colander value = object() node = DummySchemaNode(None) typ = self._makeOne() self.assertRaises(colander.Invalid, typ.deserialize, node, value) def test_serialize_null(self): from colander import null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, null) self.assertEqual(result, null) def test_serialize_emptystring(self): val = '' node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, val) def test_serialize_uncooperative(self): val = Uncooperative() node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) self.assertTrue(e.msg) def test_serialize_nonunicode_to_None(self): value = object() node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, value) self.assertEqual(result, text_type(value)) def test_serialize_unicode_to_None(self): value = text_('abc') node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, value) self.assertEqual(result, value) def test_serialize_to_utf8(self): uni = text_(b'\xe3\x81\x82', encoding='utf-8') utf8 = uni.encode('utf-8') node = DummySchemaNode(None) typ = self._makeOne('utf-8') result = typ.serialize(node, uni) self.assertEqual(result, utf8) def test_serialize_to_utf16(self): uni = text_(b'\xe3\x81\x82', encoding='utf-8') utf16 = uni.encode('utf-16') node = DummySchemaNode(None) typ = self._makeOne('utf-16') result = typ.serialize(node, uni) self.assertEqual(result, utf16) def test_serialize_string_with_high_unresolveable_high_order_chars(self): not_utf8 = b'\xff\xfe\xf8\x00' node = DummySchemaNode(None) typ = self._makeOne('utf-8') e = invalid_exc(typ.serialize, node, not_utf8) self.assertTrue('cannot be serialized' in e.msg) class TestInteger(unittest.TestCase): def _makeOne(self): from colander import Integer return Integer() def test_alias(self): from colander import Int from colander import Integer self.assertEqual(Int, Integer) def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_emptystring(self): import colander val = '' node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, val) self.assertEqual(result, colander.null) def test_deserialize_fails(self): val = 'P' node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) self.assertTrue(e.msg) def test_deserialize_ok(self): val = '1' node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, val) self.assertEqual(result, 1) def test_serialize_fails(self): val = 'P' node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) self.assertTrue(e.msg) def test_serialize_ok(self): val = 1 node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, '1') def test_serialize_zero(self): val = 0 node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, '0') class TestFloat(unittest.TestCase): def _makeOne(self): from colander import Float return Float() def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_emptystring(self): import colander val = '' node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, val) self.assertEqual(result, colander.null) def test_deserialize_fails(self): val = 'P' node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) self.assertTrue(e.msg) def test_deserialize_ok(self): val = '1.0' node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, val) self.assertEqual(result, 1.0) def test_serialize_fails(self): val = 'P' node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) self.assertTrue(e.msg) def test_serialize_ok(self): val = 1.0 node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, '1.0') class TestDecimal(unittest.TestCase): def _makeOne(self, quant=None, rounding=None): from colander import Decimal return Decimal(quant, rounding) def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_emptystring(self): import colander val = '' node = DummySchemaNode(None) typ = self._makeOne() self.assertRaises(colander.Invalid, typ.serialize, node, val) def test_serialize_quantize_no_rounding(self): val = '.000001' node = DummySchemaNode(None) typ = self._makeOne('.01') result = typ.serialize(node, val) self.assertEqual(result, '0.00') def test_serialize_quantize_with_rounding_up(self): import decimal val = '.000001' node = DummySchemaNode(None) typ = self._makeOne('.01', decimal.ROUND_UP) result = typ.serialize(node, val) self.assertEqual(result, '0.01') def test_deserialize_fails(self): val = 'P' node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) self.assertTrue(e.msg) def test_deserialize_ok(self): import decimal val = '1.0' node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, val) self.assertEqual(result, decimal.Decimal('1.0')) def test_deserialize_with_quantize(self): import decimal val = '1.00000001' node = DummySchemaNode(None) typ = self._makeOne('.01', decimal.ROUND_UP) result = typ.deserialize(node, val) self.assertEqual(result, decimal.Decimal('1.01')) def test_serialize_fails(self): val = 'P' node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) self.assertTrue(e.msg) def test_serialize_ok(self): val = 1.0 node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, '1.0') class TestMoney(unittest.TestCase): def _makeOne(self): from colander import Money return Money() def test_serialize_rounds_up(self): val = '1.000001' node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, '1.01') def test_deserialize_rounds_up(self): import decimal val = '1.00000001' node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, val) self.assertEqual(result, decimal.Decimal('1.01')) class TestBoolean(unittest.TestCase): def _makeOne(self): from colander import Boolean return Boolean() def test_alias(self): from colander import Bool from colander import Boolean self.assertEqual(Bool, Boolean) def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_deserialize(self): typ = self._makeOne() node = DummySchemaNode(None) self.assertEqual(typ.deserialize(node, 'false'), False) self.assertEqual(typ.deserialize(node, 'FALSE'), False) self.assertEqual(typ.deserialize(node, '0'), False) self.assertEqual(typ.deserialize(node, 'true'), True) self.assertEqual(typ.deserialize(node, 'other'), True) def test_deserialize_unstringable(self): typ = self._makeOne() node = DummySchemaNode(None) e = invalid_exc(typ.deserialize, node, Uncooperative()) self.assertTrue(e.msg.endswith('not a string')) def test_deserialize_null(self): import colander typ = self._makeOne() node = DummySchemaNode(None) result = typ.deserialize(node, colander.null) self.assertEqual(result, colander.null) def test_serialize(self): typ = self._makeOne() node = DummySchemaNode(None) self.assertEqual(typ.serialize(node, 1), 'true') self.assertEqual(typ.serialize(node, True), 'true') self.assertEqual(typ.serialize(node, None), 'false') self.assertEqual(typ.serialize(node, False), 'false') class TestBooleanCustomFalseReprs(unittest.TestCase): def _makeOne(self): from colander import Boolean return Boolean(false_choices=('n','f')) def test_deserialize(self): import colander typ = self._makeOne() node = DummySchemaNode(None) self.assertEqual(typ.deserialize(node, 'f'), False) self.assertEqual(typ.deserialize(node, 'N'), False) self.assertEqual(typ.deserialize(node, 'other'), True) class TestBooleanCustomFalseAndTrueReprs(unittest.TestCase): def _makeOne(self): from colander import Boolean return Boolean(false_choices=('n','f'), true_choices=('y','t')) def test_deserialize(self): import colander typ = self._makeOne() node = DummySchemaNode(None) self.assertEqual(typ.deserialize(node, 'f'), False) self.assertEqual(typ.deserialize(node, 'N'), False) self.assertEqual(typ.deserialize(node, 'T'), True) self.assertEqual(typ.deserialize(node, 'y'), True) self.assertRaises(colander.Invalid, typ.deserialize, node, 'other') try: _val = typ.deserialize(node, 'other') except colander.Invalid as exc: self.assertEqual(exc.msg.mapping['false_choices'], "'n', 'f'") self.assertEqual(exc.msg.mapping['true_choices'], "'y', 't'") class TestBooleanCustomSerializations(unittest.TestCase): def _makeOne(self): from colander import Boolean return Boolean(false_val='no', true_val='yes') def test_serialize(self): typ = self._makeOne() node = DummySchemaNode(None) self.assertEqual(typ.serialize(node, 1), 'yes') self.assertEqual(typ.serialize(node, True), 'yes') self.assertEqual(typ.serialize(node, None), 'no') self.assertEqual(typ.serialize(node, False), 'no') class TestGlobalObject(unittest.TestCase): def _makeOne(self, package=None): from colander import GlobalObject return GlobalObject(package) def test_zope_dottedname_style_resolve_absolute(self): typ = self._makeOne() result = typ._zope_dottedname_style(None, 'colander.tests.test_colander.TestGlobalObject') self.assertEqual(result, self.__class__) def test_zope_dottedname_style_irrresolveable_absolute(self): typ = self._makeOne() self.assertRaises(ImportError, typ._zope_dottedname_style, None, 'colander.tests.nonexisting') def test__zope_dottedname_style_resolve_relative(self): import colander typ = self._makeOne(package=colander) node = DummySchemaNode(None) result = typ._zope_dottedname_style( node, '.tests.test_colander.TestGlobalObject') self.assertEqual(result, self.__class__) def test__zope_dottedname_style_resolve_relative_leading_dots(self): import colander typ = self._makeOne(package=colander.tests) node = DummySchemaNode(None) result = typ._zope_dottedname_style( node, '..tests.test_colander.TestGlobalObject') self.assertEqual(result, self.__class__) def test__zope_dottedname_style_resolve_relative_is_dot(self): import colander.tests typ = self._makeOne(package=colander.tests) result = typ._zope_dottedname_style(None, '.') self.assertEqual(result, colander.tests) def test__zope_dottedname_style_irresolveable_relative_is_dot(self): typ = self._makeOne() e = invalid_exc(typ._zope_dottedname_style, None, '.') self.assertEqual( e.msg.interpolate(), 'relative name "." irresolveable without package') def test_zope_dottedname_style_resolve_relative_nocurrentpackage(self): typ = self._makeOne() e = invalid_exc(typ._zope_dottedname_style, None, '.whatever') self.assertEqual( e.msg.interpolate(), 'relative name ".whatever" irresolveable without package') def test_zope_dottedname_style_irrresolveable_relative(self): import colander.tests typ = self._makeOne(package=colander) self.assertRaises(ImportError, typ._zope_dottedname_style, None, '.notexisting') def test__zope_dottedname_style_resolveable_relative(self): import colander typ = self._makeOne(package=colander) result = typ._zope_dottedname_style(None, '.tests') from colander import tests self.assertEqual(result, tests) def test__zope_dottedname_style_irresolveable_absolute(self): typ = self._makeOne() self.assertRaises( ImportError, typ._zope_dottedname_style, None, 'colander.fudge.bar') def test__zope_dottedname_style_resolveable_absolute(self): typ = self._makeOne() result = typ._zope_dottedname_style( None, 'colander.tests.test_colander.TestGlobalObject') self.assertEqual(result, self.__class__) def test__pkg_resources_style_resolve_absolute(self): typ = self._makeOne() result = typ._pkg_resources_style(None, 'colander.tests.test_colander:TestGlobalObject') self.assertEqual(result, self.__class__) def test__pkg_resources_style_irrresolveable_absolute(self): typ = self._makeOne() self.assertRaises(ImportError, typ._pkg_resources_style, None, 'colander.tests.test_colander:nonexisting') def test__pkg_resources_style_resolve_relative_startswith_colon(self): import colander.tests typ = self._makeOne(package=colander.tests) result = typ._pkg_resources_style(None, ':fixture') self.assertEqual(result, 1) def test__pkg_resources_style_resolve_relative_startswith_dot(self): import colander typ = self._makeOne(package=colander) result = typ._pkg_resources_style( None, '.tests.test_colander:TestGlobalObject') self.assertEqual(result, self.__class__) def test__pkg_resources_style_resolve_relative_is_dot(self): import colander.tests typ = self._makeOne(package=colander.tests) result = typ._pkg_resources_style(None, '.') self.assertEqual(result, colander.tests) def test__pkg_resources_style_resolve_relative_nocurrentpackage(self): typ = self._makeOne() import colander self.assertRaises(colander.Invalid, typ._pkg_resources_style, None, '.whatever') def test__pkg_resources_style_irrresolveable_relative(self): import colander.tests typ = self._makeOne(package=colander) self.assertRaises(ImportError, typ._pkg_resources_style, None, ':notexisting') def test_deserialize_None(self): import colander typ = self._makeOne() node = DummySchemaNode(None) result = typ.deserialize(node, None) self.assertEqual(result, colander.null) def test_deserialize_null(self): import colander typ = self._makeOne() node = DummySchemaNode(None) result = typ.deserialize(node, colander.null) self.assertEqual(result, colander.null) def test_deserialize_notastring(self): import colander typ = self._makeOne() node = DummySchemaNode(None) self.assertRaises(colander.Invalid, typ.deserialize, node, True) def test_deserialize_using_pkgresources_style(self): typ = self._makeOne() node = DummySchemaNode(None) result = typ.deserialize( node, 'colander.tests.test_colander:TestGlobalObject') self.assertEqual(result, self.__class__) def test_deserialize_using_zope_dottedname_style(self): typ = self._makeOne() node = DummySchemaNode(None) result = typ.deserialize( node, 'colander.tests.test_colander.TestGlobalObject') self.assertEqual(result, self.__class__) def test_deserialize_style_raises(self): typ = self._makeOne() node = DummySchemaNode(None) e = invalid_exc(typ.deserialize, node, 'cant.be.found') self.assertEqual(e.msg.interpolate(), 'The dotted name "cant.be.found" cannot be imported') def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_ok(self): import colander.tests typ = self._makeOne() node = DummySchemaNode(None) result = typ.serialize(node, colander.tests) self.assertEqual(result, 'colander.tests') def test_serialize_fail(self): typ = self._makeOne() node = DummySchemaNode(None) e = invalid_exc(typ.serialize, node, None) self.assertEqual(e.msg.interpolate(), '"None" has no __name__') class TestDateTime(unittest.TestCase): def _makeOne(self, *arg, **kw): from colander import DateTime return DateTime(*arg, **kw) def _dt(self): import datetime return datetime.datetime(2010, 4, 26, 10, 48) def _today(self): import datetime return datetime.date.today() def test_ctor_default_tzinfo_not_specified(self): from .. import iso8601 typ = self._makeOne() self.assertEqual(typ.default_tzinfo.__class__, iso8601.Utc) def test_ctor_default_tzinfo_None(self): typ = self._makeOne(default_tzinfo=None) self.assertEqual(typ.default_tzinfo, None) def test_ctor_default_tzinfo_non_None(self): from .. import iso8601 tzinfo = iso8601.FixedOffset(1, 0, 'myname') typ = self._makeOne(default_tzinfo=tzinfo) self.assertEqual(typ.default_tzinfo, tzinfo) def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_none(self): import colander val = None node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_with_garbage(self): typ = self._makeOne() node = DummySchemaNode(None) e = invalid_exc(typ.serialize, node, 'garbage') self.assertEqual(e.msg.interpolate(), '"garbage" is not a datetime object') def test_serialize_with_date(self): import datetime typ = self._makeOne() date = self._today() node = DummySchemaNode(None) result = typ.serialize(node, date) expected = datetime.datetime.combine(date, datetime.time()) expected = expected.replace(tzinfo=typ.default_tzinfo).isoformat() self.assertEqual(result, expected) def test_serialize_with_naive_datetime(self): typ = self._makeOne() node = DummySchemaNode(None) dt = self._dt() result = typ.serialize(node, dt) expected = dt.replace(tzinfo=typ.default_tzinfo).isoformat() self.assertEqual(result, expected) def test_serialize_with_none_tzinfo_naive_datetime(self): typ = self._makeOne(default_tzinfo=None) node = DummySchemaNode(None) dt = self._dt() result = typ.serialize(node, dt) self.assertEqual(result, dt.isoformat()) def test_serialize_with_tzware_datetime(self): from .. import iso8601 typ = self._makeOne() dt = self._dt() tzinfo = iso8601.FixedOffset(1, 0, 'myname') dt = dt.replace(tzinfo=tzinfo) node = DummySchemaNode(None) result = typ.serialize(node, dt) expected = dt.isoformat() self.assertEqual(result, expected) def test_deserialize_date(self): import datetime from .. import iso8601 date = self._today() typ = self._makeOne() formatted = date.isoformat() node = DummySchemaNode(None) result = typ.deserialize(node, formatted) expected = datetime.datetime.combine(result, datetime.time()) tzinfo = iso8601.Utc() expected = expected.replace(tzinfo=tzinfo) self.assertEqual(result.isoformat(), expected.isoformat()) def test_deserialize_invalid_ParseError(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, 'garbage') self.assertTrue('Invalid' in e.msg) def test_deserialize_slashes_invalid(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, '2013/05/31') self.assertTrue('Invalid' in e.msg) def test_deserialize_null(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, colander.null) self.assertEqual(result, colander.null) def test_deserialize_empty(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, '') self.assertEqual(result, colander.null) def test_deserialize_success(self): from .. import iso8601 typ = self._makeOne() dt = self._dt() tzinfo = iso8601.FixedOffset(1, 0, 'myname') dt = dt.replace(tzinfo=tzinfo) iso = dt.isoformat() node = DummySchemaNode(None) result = typ.deserialize(node, iso) self.assertEqual(result.isoformat(), iso) def test_deserialize_naive_with_default_tzinfo(self): from .. import iso8601 tzinfo = iso8601.FixedOffset(1, 0, 'myname') typ = self._makeOne(default_tzinfo=tzinfo) dt = self._dt() dt_with_tz = dt.replace(tzinfo=tzinfo) iso = dt.isoformat() node = DummySchemaNode(None) result = typ.deserialize(node, iso) self.assertEqual(result.isoformat(), dt_with_tz.isoformat()) def test_deserialize_none_tzinfo(self): typ = self._makeOne(default_tzinfo=None) dt = self._dt() iso = dt.isoformat() node = DummySchemaNode(None) result = typ.deserialize(node, iso) self.assertEqual(result.isoformat(), dt.isoformat()) self.assertEqual(result.tzinfo, None) class TestDate(unittest.TestCase): def _makeOne(self, *arg, **kw): from colander import Date return Date(*arg, **kw) def _dt(self): import datetime return datetime.datetime(2010, 4, 26, 10, 48) def _today(self): import datetime return datetime.date.today() def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_none(self): import colander val = None node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_with_garbage(self): typ = self._makeOne() node = DummySchemaNode(None) e = invalid_exc(typ.serialize, node, 'garbage') self.assertEqual(e.msg.interpolate(), '"garbage" is not a date object') def test_serialize_with_date(self): typ = self._makeOne() date = self._today() node = DummySchemaNode(None) result = typ.serialize(node, date) expected = date.isoformat() self.assertEqual(result, expected) def test_serialize_with_datetime(self): typ = self._makeOne() dt = self._dt() node = DummySchemaNode(None) result = typ.serialize(node, dt) expected = dt.date().isoformat() self.assertEqual(result, expected) def test_deserialize_invalid_ParseError(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, 'garbage') self.assertTrue('Invalid' in e.msg) def test_deserialize_invalid_weird(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, '10-10-10-10') self.assertTrue('Invalid' in e.msg) def test_deserialize_null(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, colander.null) self.assertEqual(result, colander.null) def test_deserialize_empty(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, '') self.assertEqual(result, colander.null) def test_deserialize_success_date(self): typ = self._makeOne() date = self._today() iso = date.isoformat() node = DummySchemaNode(None) result = typ.deserialize(node, iso) self.assertEqual(result.isoformat(), iso) def test_deserialize_success_datetime(self): dt = self._dt() typ = self._makeOne() iso = dt.isoformat() node = DummySchemaNode(None) result = typ.deserialize(node, iso) self.assertEqual(result.isoformat(), dt.date().isoformat()) class TestTime(unittest.TestCase): def _makeOne(self, *arg, **kw): from colander import Time return Time(*arg, **kw) def _dt(self): import datetime return datetime.datetime(2010, 4, 26, 10, 48) def _now(self): import datetime return datetime.datetime.now().time() def test_serialize_null(self): import colander val = colander.null node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_none(self): import colander val = None node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, val) self.assertEqual(result, colander.null) def test_serialize_with_garbage(self): typ = self._makeOne() node = DummySchemaNode(None) e = invalid_exc(typ.serialize, node, 'garbage') self.assertEqual(e.msg.interpolate(), '"garbage" is not a time object') def test_serialize_with_time(self): typ = self._makeOne() time = self._now() node = DummySchemaNode(None) result = typ.serialize(node, time) expected = time.isoformat().split('.')[0] self.assertEqual(result, expected) def test_serialize_with_zero_time(self): import datetime typ = self._makeOne() time = datetime.time(0) node = DummySchemaNode(None) result = typ.serialize(node, time) expected = time.isoformat().split('.')[0] self.assertEqual(result, expected) def test_serialize_with_datetime(self): typ = self._makeOne() dt = self._dt() node = DummySchemaNode(None) result = typ.serialize(node, dt) expected = dt.time().isoformat().split('.')[0] self.assertEqual(result, expected) def test_deserialize_invalid_ParseError(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, 'garbage') self.assertTrue('Invalid' in e.msg) def test_deserialize_three_digit_string(self): import datetime node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, '11:00:11') self.assertEqual(result, datetime.time(11, 0, 11)) def test_deserialize_two_digit_string(self): import datetime node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, '11:00') self.assertEqual(result, datetime.time(11, 0)) def test_deserialize_null(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, colander.null) self.assertEqual(result, colander.null) def test_deserialize_empty(self): import colander node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, '') self.assertEqual(result, colander.null) def test_deserialize_missing_seconds(self): import datetime typ = self._makeOne() node = DummySchemaNode(None) result = typ.deserialize(node, '10:12') self.assertEqual(result, datetime.time(10, 12)) def test_deserialize_success_time(self): import datetime typ = self._makeOne() node = DummySchemaNode(None) result = typ.deserialize(node, '10:12:13') self.assertEqual(result, datetime.time(10, 12, 13)) def test_deserialize_success_datetime(self): dt = self._dt() typ = self._makeOne() iso = dt.isoformat() node = DummySchemaNode(None) result = typ.deserialize(node, iso) self.assertEqual(result.isoformat(), dt.time().isoformat().split('.')[0]) class TestSchemaNode(unittest.TestCase): def _makeOne(self, *arg, **kw): from colander import SchemaNode return SchemaNode(*arg, **kw) def test_new_sets_order(self): node = self._makeOne(None) self.assertTrue(hasattr(node, '_order')) def test_ctor_no_title(self): child = DummySchemaNode(None, name='fred') node = self._makeOne(None, child, validator=1, default=2, name='name_a', missing='missing') self.assertEqual(node.typ, None) self.assertEqual(node.children, [child]) self.assertEqual(node.validator, 1) self.assertEqual(node.default, 2) self.assertEqual(node.missing, 'missing') self.assertEqual(node.name, 'name_a') self.assertEqual(node.title, 'Name A') def test_ctor_with_title(self): child = DummySchemaNode(None, name='fred') node = self._makeOne(None, child, validator=1, default=2, name='name', title='title') self.assertEqual(node.typ, None) self.assertEqual(node.children, [child]) self.assertEqual(node.validator, 1) self.assertEqual(node.default, 2) self.assertEqual(node.name, 'name') self.assertEqual(node.title, 'title') def test_ctor_with_description(self): node = self._makeOne(None, validator=1, default=2, name='name', title='title', description='desc') self.assertEqual(node.description, 'desc') def test_ctor_with_widget(self): node = self._makeOne(None, widget='abc') self.assertEqual(node.widget, 'abc') def test_ctor_with_preparer(self): node = self._makeOne(None, preparer='abc') self.assertEqual(node.preparer, 'abc') def test_ctor_without_preparer(self): node = self._makeOne(None) self.assertEqual(node.preparer, None) def test_ctor_with_unknown_kwarg(self): node = self._makeOne(None, foo=1) self.assertEqual(node.foo, 1) def test_ctor_with_kwarg_typ(self): node = self._makeOne(typ='foo') self.assertEqual(node.typ, 'foo') def test_ctor_children_kwarg_typ(self): subnode1 = DummySchemaNode(None, name='sub1') subnode2 = DummySchemaNode(None, name='sub2') node = self._makeOne(subnode1, subnode2, typ='foo') self.assertEqual(node.children, [subnode1, subnode2]) def test_ctor_without_type(self): self.assertRaises(NotImplementedError, self._makeOne) def test_required_true(self): node = self._makeOne(None) self.assertEqual(node.required, True) def test_required_false(self): node = self._makeOne(None, missing=1) self.assertEqual(node.required, False) def test_required_deferred(self): from colander import deferred node = self._makeOne(None, missing=deferred(lambda: '123')) self.assertEqual(node.required, True) def test_deserialize_no_validator(self): typ = DummyType() node = self._makeOne(typ) result = node.deserialize(1) self.assertEqual(result, 1) def test_deserialize_with_preparer(self): from colander import Invalid typ = DummyType() def preparer(value): return 'prepared_'+value def validator(node, value): if not value.startswith('prepared'): raise Invalid(node, 'not prepared') # pragma: no cover node = self._makeOne(typ, preparer=preparer, validator=validator) self.assertEqual(node.deserialize('value'), 'prepared_value') def test_deserialize_with_multiple_preparers(self): from colander import Invalid typ = DummyType() def preparer1(value): return 'prepared1_'+value def preparer2(value): return 'prepared2_'+value def validator(node, value): if not value.startswith('prepared2_prepared1'): raise Invalid(node, 'not prepared') # pragma: no cover node = self._makeOne(typ, preparer=[preparer1, preparer2], validator=validator) self.assertEqual(node.deserialize('value'), 'prepared2_prepared1_value') def test_deserialize_preparer_before_missing_check(self): from colander import null typ = DummyType() def preparer(value): return null node = self._makeOne(typ,preparer=preparer) e = invalid_exc(node.deserialize, 1) self.assertEqual(e.msg, 'Required') def test_deserialize_with_validator(self): typ = DummyType() validator = DummyValidator(msg='Wrong') node = self._makeOne(typ, validator=validator) e = invalid_exc(node.deserialize, 1) self.assertEqual(e.msg, 'Wrong') def test_deserialize_with_unbound_validator(self): from colander import Invalid from colander import deferred from colander import UnboundDeferredError typ = DummyType() def validator(node, kw): def _validate(node, value): node.raise_invalid('Invalid') return _validate node = self._makeOne(typ, validator=deferred(validator)) self.assertRaises(UnboundDeferredError, node.deserialize, None) self.assertRaises(Invalid, node.bind(foo='foo').deserialize, None) def test_deserialize_value_is_null_no_missing(self): from colander import null from colander import Invalid typ = DummyType() node = self._makeOne(typ) self.assertRaises(Invalid, node.deserialize, null) def test_deserialize_value_is_null_with_missing(self): from colander import null typ = DummyType() node = self._makeOne(typ) node.missing = 'abc' self.assertEqual(node.deserialize(null), 'abc') def test_deserialize_value_is_null_with_missing_msg(self): from colander import null typ = DummyType() node = self._makeOne(typ, missing_msg='Missing') e = invalid_exc(node.deserialize, null) self.assertEqual(e.msg, 'Missing') def test_deserialize_noargs_uses_default(self): typ = DummyType() node = self._makeOne(typ) node.missing = 'abc' self.assertEqual(node.deserialize(), 'abc') def test_deserialize_null_can_be_used_as_missing(self): from colander import null typ = DummyType() node = self._makeOne(typ) node.missing = null self.assertEqual(node.deserialize(null), null) def test_deserialize_appstruct_deferred(self): from colander import null from colander import deferred from colander import Invalid typ = DummyType() node = self._makeOne(typ) node.missing = deferred(lambda: '123') self.assertRaises(Invalid, node.deserialize, null) def test_serialize(self): typ = DummyType() node = self._makeOne(typ) result = node.serialize(1) self.assertEqual(result, 1) def test_serialize_value_is_null_no_default(self): from colander import null typ = DummyType() node = self._makeOne(typ) result = node.serialize(null) self.assertEqual(result, null) def test_serialize_value_is_null_with_default(self): from colander import null typ = DummyType() node = self._makeOne(typ) node.default = 1 result = node.serialize(null) self.assertEqual(result, 1) def test_serialize_noargs_uses_default(self): typ = DummyType() node = self._makeOne(typ) node.default = 'abc' self.assertEqual(node.serialize(), 'abc') def test_serialize_default_deferred(self): from colander import deferred from colander import null typ = DummyType() node = self._makeOne(typ) node.default = deferred(lambda: 'abc') self.assertEqual(node.serialize(), null) def test_add(self): node = self._makeOne(None) node.add(1) self.assertEqual(node.children, [1]) def test_insert(self): node = self._makeOne(None) node.children = [99, 99] node.insert(1, 'foo') self.assertEqual(node.children, [99, 'foo', 99]) def test_repr(self): node = self._makeOne(None, name='flub') result = repr(node) self.assertTrue(result.startswith('")) def test___getitem__success(self): node = self._makeOne(None) another = self._makeOne(None, name='another') node.add(another) self.assertEqual(node['another'], another) def test___getitem__failure(self): node = self._makeOne(None) self.assertRaises(KeyError, node.__getitem__, 'another') def test___delitem__success(self): node = self._makeOne(None) another = self._makeOne(None, name='another') node.add(another) del node['another'] self.assertEqual(node.children, []) def test___delitem__failure(self): node = self._makeOne(None) self.assertRaises(KeyError, node.__delitem__, 'another') def test___setitem__override(self): node = self._makeOne(None) another = self._makeOne(None, name='another') node.add(another) andanother = self._makeOne(None, name='andanother') node['another'] = andanother self.assertEqual(node['another'], andanother) self.assertEqual(andanother.name, 'another') def test___setitem__no_override(self): another = self._makeOne(None, name='another') node = self._makeOne(None) node['another'] = another self.assertEqual(node['another'], another) self.assertEqual(node.children[0], another) def test___iter__(self): node = self._makeOne(None) node.children = ['a', 'b', 'c'] it = node.__iter__() self.assertEqual(list(it), ['a', 'b', 'c']) def test___contains__(self): node = self._makeOne(None) another = self._makeOne(None, name='another') node.add(another) self.assertEqual('another' in node, True) self.assertEqual('b' in node, False) def test_clone(self): inner_typ = DummyType() outer_typ = DummyType() outer_node = self._makeOne(outer_typ, name='outer') inner_node = self._makeOne(inner_typ, name='inner') outer_node.foo = 1 inner_node.foo = 2 outer_node.children = [inner_node] outer_clone = outer_node.clone() self.assertFalse(outer_clone is outer_node) self.assertEqual(outer_clone.typ, outer_typ) self.assertEqual(outer_clone.name, 'outer') self.assertEqual(outer_node.foo, 1) self.assertEqual(len(outer_clone.children), 1) inner_clone = outer_clone.children[0] self.assertFalse(inner_clone is inner_node) self.assertEqual(inner_clone.typ, inner_typ) self.assertEqual(inner_clone.name, 'inner') self.assertEqual(inner_clone.foo, 2) def test_bind(self): from colander import deferred inner_typ = DummyType() outer_typ = DummyType() def dv(node, kw): self.assertTrue(node.name in ['outer', 'inner']) self.assertTrue('a' in kw) return '123' dv = deferred(dv) outer_node = self._makeOne(outer_typ, name='outer', missing=dv) inner_node = self._makeOne(inner_typ, name='inner', validator=dv, missing=dv) outer_node.children = [inner_node] outer_clone = outer_node.bind(a=1) self.assertFalse(outer_clone is outer_node) self.assertEqual(outer_clone.missing, '123') inner_clone = outer_clone.children[0] self.assertFalse(inner_clone is inner_node) self.assertEqual(inner_clone.missing, '123') self.assertEqual(inner_clone.validator, '123') def test_bind_with_after_bind(self): from colander import deferred inner_typ = DummyType() outer_typ = DummyType() def dv(node, kw): self.assertTrue(node.name in ['outer', 'inner']) self.assertTrue('a' in kw) return '123' dv = deferred(dv) def remove_inner(node, kw): self.assertEqual(kw, {'a':1}) del node['inner'] outer_node = self._makeOne(outer_typ, name='outer', missing=dv, after_bind=remove_inner) inner_node = self._makeOne(inner_typ, name='inner', validator=dv, missing=dv) outer_node.children = [inner_node] outer_clone = outer_node.bind(a=1) self.assertFalse(outer_clone is outer_node) self.assertEqual(outer_clone.missing, '123') self.assertEqual(len(outer_clone.children), 0) self.assertEqual(len(outer_node.children), 1) def test_declarative_name_reassignment(self): # see https://github.com/Pylons/colander/issues/39 import colander class FnordSchema(colander.Schema): fnord = colander.SchemaNode( colander.Sequence(), colander.SchemaNode(colander.Integer(), name=''), name="fnord[]" ) schema = FnordSchema() self.assertEqual(schema['fnord[]'].name, 'fnord[]') def test_cstruct_children(self): typ = DummyType() typ.cstruct_children = lambda *arg: ['foo'] node = self._makeOne(typ) self.assertEqual(node.cstruct_children(None), ['foo']) def test_cstruct_children_warning(self): import warnings with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') typ = None node = self._makeOne(typ) self.assertEqual(node.cstruct_children(None), []) self.assertEqual(len(w), 1) def test_raise_invalid(self): import colander typ = DummyType() node = self._makeOne(typ) self.assertRaises(colander.Invalid, node.raise_invalid, 'Wrong') class TestSchemaNodeSubclassing(unittest.TestCase): def test_subclass_uses_validator_method(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int name = 'my' def validator(self, node, cstruct): if cstruct > 10: self.raise_invalid('Wrong') node = MyNode() self.assertRaises(colander.Invalid, node.deserialize, 20) def test_subclass_uses_missing(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int name = 'my' missing = 10 node = MyNode() result = node.deserialize(colander.null) self.assertEqual(result, 10) def test_subclass_uses_title(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int title = 'some title' node = MyNode(name='my') self.assertEqual(node.title, 'some title') def test_subclass_title_overwritten_by_constructor(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int title = 'some title' node = MyNode(name='my', title='other title') self.assertEqual(node.title, 'other title') def test_subclass_value_overridden_by_constructor(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int name = 'my' missing = 10 node = MyNode(missing=5) result = node.deserialize(colander.null) self.assertEqual(result, 5) def test_method_values_can_rely_on_binding(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int def amethod(self): return self.bindings['request'] node = MyNode() newnode = node.bind(request=True) self.assertEqual(newnode.amethod(), True) def test_nonmethod_values_can_rely_on_after_bind(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int def after_bind(self, node, kw): self.missing = kw['missing'] node = MyNode() newnode = node.bind(missing=10) self.assertEqual(newnode.deserialize(colander.null), 10) def test_deferred_methods_dont_quite_work_yet(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int @colander.deferred def avalidator(self, node, kw): # pragma: no cover def _avalidator(node, cstruct): self.raise_invalid('Foo') return _avalidator node = MyNode() self.assertRaises(TypeError, node.bind) def test_nonmethod_values_can_be_deferred_though(self): import colander def _missing(node, kw): return 10 class MyNode(colander.SchemaNode): schema_type = colander.Int missing = colander.deferred(_missing) node = MyNode() bound_node = node.bind() self.assertEqual(bound_node.deserialize(colander.null), 10) def test_functions_can_be_deferred(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Int @colander.deferred def missing(node, kw): return 10 node = MyNode() bound_node = node.bind() self.assertEqual(bound_node.deserialize(colander.null), 10) def test_schema_child_names_conflict_with_value_names_notused(self): import colander class MyNode(colander.SchemaNode): schema_type = colander.Mapping title = colander.SchemaNode( colander.String(), ) node = MyNode() self.assertEqual(node.title, '') def test_schema_child_names_conflict_with_value_names_used(self): import colander doesntmatter = colander.SchemaNode( colander.String(), name='name', ) class MyNode(colander.SchemaNode): schema_type = colander.Mapping name = 'fred' wontmatter = doesntmatter node = MyNode() self.assertEqual(node.name, 'fred') self.assertEqual(node['name'], doesntmatter) def test_schema_child_names_conflict_with_value_names_in_superclass(self): import colander doesntmatter = colander.SchemaNode( colander.String(), name='name', ) _name = colander.SchemaNode( colander.String(), ) class MyNode(colander.SchemaNode): schema_type = colander.Mapping name = 'fred' wontmatter = doesntmatter class AnotherNode(MyNode): name = _name node = AnotherNode() self.assertEqual(node.name, 'fred') self.assertEqual(node['name'], _name) def test_schema_child_names_conflict_with_value_names_in_subclass(self): import colander class MyNode(colander.SchemaNode): name = colander.SchemaNode( colander.String(), id='name', ) class AnotherNode(MyNode): schema_type = colander.Mapping name = 'fred' doesntmatter = colander.SchemaNode( colander.String(), name='name', id='doesntmatter', ) node = AnotherNode() self.assertEqual(node.name, 'fred') self.assertEqual(node['name'].id, 'doesntmatter') class TestMappingSchemaInheritance(unittest.TestCase): def test_single_inheritance(self): import colander class Friend(colander.Schema): rank = colander.SchemaNode( colander.Int(), id='rank', ) name = colander.SchemaNode( colander.String(), id='name' ) serial = colander.SchemaNode( colander.Bool(), id='serial2', ) class SpecialFriend(Friend): iwannacomefirst = colander.SchemaNode( colander.Int(), id='iwannacomefirst2', ) class SuperSpecialFriend(SpecialFriend): iwannacomefirst = colander.SchemaNode( colander.String(), id='iwannacomefirst1', ) another = colander.SchemaNode( colander.String(), id='another', ) serial = colander.SchemaNode( colander.Int(), id='serial1', ) inst = SuperSpecialFriend() self.assertEqual( [ x.id for x in inst.children], [ 'rank', 'name', 'serial1', 'iwannacomefirst1', 'another', ] ) def test_single_inheritance_with_insert_before(self): import colander class Friend(colander.Schema): rank = colander.SchemaNode( colander.Int(), id='rank', ) name = colander.SchemaNode( colander.String(), id='name' ) serial = colander.SchemaNode( colander.Bool(), insert_before='name', id='serial2', ) class SpecialFriend(Friend): iwannacomefirst = colander.SchemaNode( colander.Int(), id='iwannacomefirst2', ) class SuperSpecialFriend(SpecialFriend): iwannacomefirst = colander.SchemaNode( colander.String(), insert_before='rank', id='iwannacomefirst1', ) another = colander.SchemaNode( colander.String(), id='another', ) serial = colander.SchemaNode( colander.Int(), id='serial1', ) inst = SuperSpecialFriend() self.assertEqual( [ x.id for x in inst.children], [ 'iwannacomefirst1', 'rank', 'serial1', 'name', 'another', ] ) def test_single_inheritance2(self): import colander class One(colander.Schema): a = colander.SchemaNode( colander.Int(), id='a1', ) b = colander.SchemaNode( colander.Int(), id='b1', ) d = colander.SchemaNode( colander.Int(), id='d1', ) class Two(One): a = colander.SchemaNode( colander.String(), id='a2', ) c = colander.SchemaNode( colander.String(), id='c2', ) e = colander.SchemaNode( colander.String(), id='e2', ) class Three(Two): b = colander.SchemaNode( colander.Bool(), id='b3', ) d = colander.SchemaNode( colander.Bool(), id='d3', ) f = colander.SchemaNode( colander.Bool(), id='f3', ) inst = Three() c = inst.children self.assertEqual(len(c), 6) result = [ x.id for x in c ] self.assertEqual(result, ['a2', 'b3', 'd3', 'c2', 'e2', 'f3']) def test_multiple_inheritance(self): import colander class One(colander.Schema): a = colander.SchemaNode( colander.Int(), id='a1', ) b = colander.SchemaNode( colander.Int(), id='b1', ) d = colander.SchemaNode( colander.Int(), id='d1', ) class Two(colander.Schema): a = colander.SchemaNode( colander.String(), id='a2', ) c = colander.SchemaNode( colander.String(), id='c2', ) e = colander.SchemaNode( colander.String(), id='e2', ) class Three(Two, One): b = colander.SchemaNode( colander.Bool(), id='b3', ) d = colander.SchemaNode( colander.Bool(), id='d3', ) f = colander.SchemaNode( colander.Bool(), id='f3', ) inst = Three() c = inst.children self.assertEqual(len(c), 6) result = [ x.id for x in c ] self.assertEqual(result, ['a2', 'b3', 'd3', 'c2', 'e2', 'f3']) def test_insert_before_failure(self): import colander class One(colander.Schema): a = colander.SchemaNode( colander.Int(), ) b = colander.SchemaNode( colander.Int(), insert_before='c' ) self.assertRaises(KeyError, One) class TestDeferred(unittest.TestCase): def _makeOne(self, wrapped): from colander import deferred return deferred(wrapped) def test_ctor(self): wrapped = lambda: 'foo' inst = self._makeOne(wrapped) self.assertEqual(inst.wrapped, wrapped) def test___call__(self): n = object() k = object() def wrapped(node, kw): self.assertEqual(node, n) self.assertEqual(kw, k) return 'abc' inst = self._makeOne(wrapped) result= inst(n, k) self.assertEqual(result, 'abc') def test_retain_func_details(self): def wrapped_func(node, kw): """Can you hear me now?""" pass # pragma: no cover inst = self._makeOne(wrapped_func) self.assertEqual(inst.__doc__, 'Can you hear me now?') self.assertEqual(inst.__name__, 'wrapped_func') def test_w_callable_instance_no_name(self): from colander import deferred class Wrapped(object): """CLASS""" def __call__(self, node, kw): """METHOD""" pass # pragma: no cover wrapped = Wrapped() inst = self._makeOne(wrapped) self.assertEqual(inst.__doc__, wrapped.__doc__) self.assertFalse('__name__' in inst.__dict__) def test_w_callable_instance_no_name_or_doc(self): from colander import deferred class Wrapped(object): def __call__(self, node, kw): pass # pragma: no cover wrapped = Wrapped() inst = self._makeOne(wrapped) self.assertEqual(inst.__doc__, None) self.assertFalse('__name__' in inst.__dict__) class TestSchema(unittest.TestCase): def test_alias(self): from colander import Schema from colander import MappingSchema self.assertEqual(Schema, MappingSchema) def test_it(self): import colander class MySchema(colander.Schema): thing_a = colander.SchemaNode(colander.String()) thing2 = colander.SchemaNode(colander.String(), title='bar') node = MySchema(default='abc') self.assertTrue(hasattr(node, '_order')) self.assertEqual(node.default, 'abc') self.assertTrue(isinstance(node, colander.SchemaNode)) self.assertEqual(node.typ.__class__, colander.Mapping) self.assertEqual(node.children[0].typ.__class__, colander.String) self.assertEqual(node.children[0].title, 'Thing A') self.assertEqual(node.children[1].title, 'bar') def test_title_munging(self): import colander class MySchema(colander.Schema): thing1 = colander.SchemaNode(colander.String()) thing2 = colander.SchemaNode(colander.String(), title=None) thing3 = colander.SchemaNode(colander.String(), title='') thing4 = colander.SchemaNode(colander.String(), title='thing2') node = MySchema() self.assertEqual(node.children[0].title, 'Thing1') self.assertEqual(node.children[1].title, None) self.assertEqual(node.children[2].title, '') self.assertEqual(node.children[3].title, 'thing2') def test_deserialize_drop(self): import colander class MySchema(colander.Schema): a = colander.SchemaNode(colander.String()) b = colander.SchemaNode(colander.String(), missing=colander.drop) node = MySchema() expected = {'a': 'test'} result = node.deserialize(expected) self.assertEqual(result, expected) def test_serialize_drop_default(self): import colander class MySchema(colander.Schema): a = colander.SchemaNode(colander.String()) b = colander.SchemaNode(colander.String(), default=colander.drop) node = MySchema() expected = {'a': 'foo'} result = node.serialize(expected) self.assertEqual(result, expected) class TestSequenceSchema(unittest.TestCase): def test_succeed(self): import colander _inner = colander.SchemaNode(colander.String()) class MySchema(colander.SequenceSchema): inner = _inner node = MySchema() self.assertTrue(hasattr(node, '_order')) self.assertTrue(isinstance(node, colander.SchemaNode)) self.assertEqual(node.typ.__class__, colander.Sequence) self.assertEqual(node.children[0], _inner) def test_fail_toomany(self): import colander thingnode = colander.SchemaNode(colander.String()) thingnode2 = colander.SchemaNode(colander.String()) class MySchema(colander.SequenceSchema): thing = thingnode thing2 = thingnode2 e = invalid_exc(MySchema) self.assertEqual( e.msg, 'Sequence schemas must have exactly one child node') def test_fail_toofew(self): import colander class MySchema(colander.SequenceSchema): pass e = invalid_exc(MySchema) self.assertEqual( e.msg, 'Sequence schemas must have exactly one child node') class TestTupleSchema(unittest.TestCase): def test_it(self): import colander class MySchema(colander.TupleSchema): thing = colander.SchemaNode(colander.String()) node = MySchema() self.assertTrue(hasattr(node, '_order')) self.assertTrue(isinstance(node, colander.SchemaNode)) self.assertEqual(node.typ.__class__, colander.Tuple) self.assertEqual(node.children[0].typ.__class__, colander.String) class TestFunctional(object): def test_deserialize_ok(self): import colander.tests data = { 'int':'10', 'ob':'colander.tests', 'seq':[('1', 's'),('2', 's'), ('3', 's'), ('4', 's')], 'seq2':[{'key':'1', 'key2':'2'}, {'key':'3', 'key2':'4'}], 'tup':('1', 's'), } schema = self._makeSchema() result = schema.deserialize(data) self.assertEqual(result['int'], 10) self.assertEqual(result['ob'], colander.tests) self.assertEqual(result['seq'], [(1, 's'), (2, 's'), (3, 's'), (4, 's')]) self.assertEqual(result['seq2'], [{'key':1, 'key2':2}, {'key':3, 'key2':4}]) self.assertEqual(result['tup'], (1, 's')) def test_flatten_ok(self): import colander appstruct = { 'int':10, 'ob':colander.tests, 'seq':[(1, 's'),(2, 's'), (3, 's'), (4, 's')], 'seq2':[{'key':1, 'key2':2}, {'key':3, 'key2':4}], 'tup':(1, 's'), } schema = self._makeSchema() result = schema.flatten(appstruct) expected = { 'schema.seq.2.tupstring': 's', 'schema.seq2.0.key2': 2, 'schema.ob': colander.tests, 'schema.seq2.1.key2': 4, 'schema.seq.1.tupstring': 's', 'schema.seq2.0.key': 1, 'schema.seq.1.tupint': 2, 'schema.seq.0.tupstring': 's', 'schema.seq.3.tupstring': 's', 'schema.seq.3.tupint': 4, 'schema.seq2.1.key': 3, 'schema.int': 10, 'schema.seq.0.tupint': 1, 'schema.tup.tupint': 1, 'schema.tup.tupstring': 's', 'schema.seq.2.tupint': 3, } for k, v in expected.items(): self.assertEqual(result[k], v) for k, v in result.items(): self.assertEqual(expected[k], v) def test_flatten_mapping_has_no_name(self): import colander appstruct = { 'int':10, 'ob':colander.tests, 'seq':[(1, 's'),(2, 's'), (3, 's'), (4, 's')], 'seq2':[{'key':1, 'key2':2}, {'key':3, 'key2':4}], 'tup':(1, 's'), } schema = self._makeSchema(name='') result = schema.flatten(appstruct) expected = { 'seq.2.tupstring': 's', 'seq2.0.key2': 2, 'ob': colander.tests, 'seq2.1.key2': 4, 'seq.1.tupstring': 's', 'seq2.0.key': 1, 'seq.1.tupint': 2, 'seq.0.tupstring': 's', 'seq.3.tupstring': 's', 'seq.3.tupint': 4, 'seq2.1.key': 3, 'int': 10, 'seq.0.tupint': 1, 'tup.tupint': 1, 'tup.tupstring': 's', 'seq.2.tupint': 3, } for k, v in expected.items(): self.assertEqual(result[k], v) for k, v in result.items(): self.assertEqual(expected[k], v) def test_unflatten_ok(self): import colander fstruct = { 'schema.seq.2.tupstring': 's', 'schema.seq2.0.key2': 2, 'schema.ob': colander.tests, 'schema.seq2.1.key2': 4, 'schema.seq.1.tupstring': 's', 'schema.seq2.0.key': 1, 'schema.seq.1.tupint': 2, 'schema.seq.0.tupstring': 's', 'schema.seq.3.tupstring': 's', 'schema.seq.3.tupint': 4, 'schema.seq2.1.key': 3, 'schema.int': 10, 'schema.seq.0.tupint': 1, 'schema.tup.tupint': 1, 'schema.tup.tupstring': 's', 'schema.seq.2.tupint': 3, } schema = self._makeSchema() result = schema.unflatten(fstruct) expected = { 'int':10, 'ob':colander.tests, 'seq':[(1, 's'),(2, 's'), (3, 's'), (4, 's')], 'seq2':[{'key':1, 'key2':2}, {'key':3, 'key2':4}], 'tup':(1, 's'), } for k, v in expected.items(): self.assertEqual(result[k], v) for k, v in result.items(): self.assertEqual(expected[k], v) def test_unflatten_mapping_no_name(self): import colander fstruct = { 'seq.2.tupstring': 's', 'seq2.0.key2': 2, 'ob': colander.tests, 'seq2.1.key2': 4, 'seq.1.tupstring': 's', 'seq2.0.key': 1, 'seq.1.tupint': 2, 'seq.0.tupstring': 's', 'seq.3.tupstring': 's', 'seq.3.tupint': 4, 'seq2.1.key': 3, 'int': 10, 'seq.0.tupint': 1, 'tup.tupint': 1, 'tup.tupstring': 's', 'seq.2.tupint': 3, } schema = self._makeSchema(name='') result = schema.unflatten(fstruct) expected = { 'int':10, 'ob':colander.tests, 'seq':[(1, 's'),(2, 's'), (3, 's'), (4, 's')], 'seq2':[{'key':1, 'key2':2}, {'key':3, 'key2':4}], 'tup':(1, 's'), } for k, v in expected.items(): self.assertEqual(result[k], v) for k, v in result.items(): self.assertEqual(expected[k], v) def test_flatten_unflatten_roundtrip(self): import colander appstruct = { 'int':10, 'ob':colander.tests, 'seq':[(1, 's'),(2, 's'), (3, 's'), (4, 's')], 'seq2':[{'key':1, 'key2':2}, {'key':3, 'key2':4}], 'tup':(1, 's'), } schema = self._makeSchema(name='') self.assertEqual( schema.unflatten(schema.flatten(appstruct)), appstruct) def test_set_value(self): import colander appstruct = { 'int':10, 'ob':colander.tests, 'seq':[(1, 's'),(2, 's'), (3, 's'), (4, 's')], 'seq2':[{'key':1, 'key2':2}, {'key':3, 'key2':4}], 'tup':(1, 's'), } schema = self._makeSchema() schema.set_value(appstruct, 'seq2.1.key', 6) self.assertEqual(appstruct['seq2'][1], {'key':6, 'key2':4}) def test_get_value(self): import colander appstruct = { 'int':10, 'ob':colander.tests, 'seq':[(1, 's'),(2, 's'), (3, 's'), (4, 's')], 'seq2':[{'key':1, 'key2':2}, {'key':3, 'key2':4}], 'tup':(1, 's'), } schema = self._makeSchema() self.assertEqual(schema.get_value(appstruct, 'seq'), [(1, 's'),(2, 's'), (3, 's'), (4, 's')]) self.assertEqual(schema.get_value(appstruct, 'seq2.1.key'), 3) def test_invalid_asdict(self): expected = { 'schema.int': '20 is greater than maximum value 10', 'schema.ob': 'The dotted name "no.way.this.exists" cannot be imported', 'schema.seq.0.0': '"q" is not a number', 'schema.seq.1.0': '"w" is not a number', 'schema.seq.2.0': '"e" is not a number', 'schema.seq.3.0': '"r" is not a number', 'schema.seq2.0.key': '"t" is not a number', 'schema.seq2.0.key2': '"y" is not a number', 'schema.seq2.1.key': '"u" is not a number', 'schema.seq2.1.key2': '"i" is not a number', 'schema.tup.0': '"s" is not a number'} data = { 'int':'20', 'ob':'no.way.this.exists', 'seq':[('q', 's'),('w', 's'), ('e', 's'), ('r', 's')], 'seq2':[{'key':'t', 'key2':'y'}, {'key':'u', 'key2':'i'}], 'tup':('s', 's'), } schema = self._makeSchema() e = invalid_exc(schema.deserialize, data) errors = e.asdict() self.assertEqual(errors, expected) def test_invalid_asdict_translation_callback(self): from translationstring import TranslationString expected = { 'schema.int': 'translated', 'schema.ob': 'translated', 'schema.seq.0.0': 'translated', 'schema.seq.1.0': 'translated', 'schema.seq.2.0': 'translated', 'schema.seq.3.0': 'translated', 'schema.seq2.0.key': 'translated', 'schema.seq2.0.key2': 'translated', 'schema.seq2.1.key': 'translated', 'schema.seq2.1.key2': 'translated', 'schema.tup.0': 'translated', } data = { 'int': '20', 'ob': 'no.way.this.exists', 'seq': [('q', 's'), ('w', 's'), ('e', 's'), ('r', 's')], 'seq2': [{'key': 't', 'key2': 'y'}, {'key':'u', 'key2':'i'}], 'tup': ('s', 's'), } schema = self._makeSchema() e = invalid_exc(schema.deserialize, data) def translation_function(string): return TranslationString('translated') errors = e.asdict(translate=translation_function) self.assertEqual(errors, expected) class TestImperative(unittest.TestCase, TestFunctional): def _makeSchema(self, name='schema'): import colander integer = colander.SchemaNode( colander.Integer(), name='int', validator=colander.Range(0, 10) ) ob = colander.SchemaNode( colander.GlobalObject(package=colander), name='ob', ) tup = colander.SchemaNode( colander.Tuple(), colander.SchemaNode( colander.Integer(), name='tupint', ), colander.SchemaNode( colander.String(), name='tupstring', ), name='tup', ) seq = colander.SchemaNode( colander.Sequence(), tup, name='seq', ) seq2 = colander.SchemaNode( colander.Sequence(), colander.SchemaNode( colander.Mapping(), colander.SchemaNode( colander.Integer(), name='key', ), colander.SchemaNode( colander.Integer(), name='key2', ), name='mapping', ), name='seq2', ) schema = colander.SchemaNode( colander.Mapping(), integer, ob, tup, seq, seq2, name=name) return schema class TestDeclarative(unittest.TestCase, TestFunctional): def _makeSchema(self, name='schema'): import colander class TupleSchema(colander.TupleSchema): tupint = colander.SchemaNode(colander.Int()) tupstring = colander.SchemaNode(colander.String()) class MappingSchema(colander.MappingSchema): key = colander.SchemaNode(colander.Int()) key2 = colander.SchemaNode(colander.Int()) class SequenceOne(colander.SequenceSchema): tup = TupleSchema() class SequenceTwo(colander.SequenceSchema): mapping = MappingSchema() class MainSchema(colander.MappingSchema): int = colander.SchemaNode(colander.Int(), validator=colander.Range(0, 10)) ob = colander.SchemaNode(colander.GlobalObject(package=colander)) seq = SequenceOne() tup = TupleSchema() seq2 = SequenceTwo() schema = MainSchema(name=name) return schema class TestUltraDeclarative(unittest.TestCase, TestFunctional): def _makeSchema(self, name='schema'): import colander class IntSchema(colander.SchemaNode): schema_type = colander.Int class StringSchema(colander.SchemaNode): schema_type = colander.String class TupleSchema(colander.TupleSchema): tupint = IntSchema() tupstring = StringSchema() class MappingSchema(colander.MappingSchema): key = IntSchema() key2 = IntSchema() class SequenceOne(colander.SequenceSchema): tup = TupleSchema() class SequenceTwo(colander.SequenceSchema): mapping = MappingSchema() class IntSchemaRanged(IntSchema): validator = colander.Range(0, 10) class GlobalObjectSchema(colander.SchemaNode): def schema_type(self): return colander.GlobalObject(package=colander) class MainSchema(colander.MappingSchema): int = IntSchemaRanged() ob = GlobalObjectSchema() seq = SequenceOne() tup = TupleSchema() seq2 = SequenceTwo() MainSchema.name = name schema = MainSchema() return schema class TestDeclarativeWithInstantiate(unittest.TestCase, TestFunctional): def _makeSchema(self, name='schema'): import colander # an unlikely usage, but goos to test passing # parameters to instantiation works @colander.instantiate(name=name) class schema(colander.MappingSchema): int = colander.SchemaNode(colander.Int(), validator=colander.Range(0, 10)) ob = colander.SchemaNode(colander.GlobalObject(package=colander)) @colander.instantiate() class seq(colander.SequenceSchema): @colander.instantiate() class tup(colander.TupleSchema): tupint = colander.SchemaNode(colander.Int()) tupstring = colander.SchemaNode(colander.String()) @colander.instantiate() class tup(colander.TupleSchema): tupint = colander.SchemaNode(colander.Int()) tupstring = colander.SchemaNode(colander.String()) @colander.instantiate() class seq2(colander.SequenceSchema): @colander.instantiate() class mapping(colander.MappingSchema): key = colander.SchemaNode(colander.Int()) key2 = colander.SchemaNode(colander.Int()) return schema class Test_null(unittest.TestCase): def test___nonzero__(self): from colander import null self.assertFalse(null) def test___repr__(self): from colander import null self.assertEqual(repr(null), '') def test_pickling(self): from colander import null import pickle self.assertTrue(pickle.loads(pickle.dumps(null)) is null) class Dummy(object): pass class DummySchemaNode(object): def __init__(self, typ, name='', exc=None, default=None): self.typ = typ self.name = name self.exc = exc self.required = default is None self.default = default self.children = [] def deserialize(self, val): from colander import Invalid if self.exc: raise Invalid(self, self.exc) return val def serialize(self, val): from colander import Invalid if self.exc: raise Invalid(self, self.exc) return val def __getitem__(self, name): for child in self.children: if child.name == name: return child class DummyValidator(object): def __init__(self, msg=None, children=None): self.msg = msg self.children = children def __call__(self, node, value): from colander import Invalid if self.msg: e = Invalid(node, self.msg) self.children and e.children.extend(self.children) raise e class Uncooperative(object): def __str__(self): raise ValueError('I wont cooperate') __unicode__ = __str__ class DummyType(object): def serialize(self, node, value): return value def deserialize(self, node, value): return value def flatten(self, node, appstruct, prefix='', listitem=False): if listitem: key = prefix.rstrip('.') else: key = prefix + 'appstruct' return {key:appstruct} def unflatten(self, node, paths, fstruct): assert paths == [node.name] return fstruct[node.name]