From 396e06a49c0e84d053f5f85f39e94412d44777ec Mon Sep 17 00:00:00 2001 From: "jay.hennen" Date: Tue, 18 Apr 2017 16:43:03 -0700 Subject: [PATCH 1/2] GlobalObject serializes modules and classes to absolute import paths only --- colander/__init__.py | 7 ++++++- colander/tests/test_colander.py | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/colander/__init__.py b/colander/__init__.py index c5de77c..2b90cb3 100644 --- a/colander/__init__.py +++ b/colander/__init__.py @@ -9,6 +9,7 @@ import pprint import re import translationstring import warnings +import types from .compat import ( text_, @@ -1578,7 +1579,11 @@ class GlobalObject(SchemaType): return null try: - return appstruct.__name__ + if isinstance(appstruct, types.ModuleType): + return appstruct.__name__ + else: + return '{0.__module__}.{0.__name__}'.format(appstruct) + except AttributeError: raise Invalid(node, _('"${val}" has no __name__', diff --git a/colander/tests/test_colander.py b/colander/tests/test_colander.py index 28ce8cf..acae4af 100644 --- a/colander/tests/test_colander.py +++ b/colander/tests/test_colander.py @@ -2096,6 +2096,43 @@ class TestGlobalObject(unittest.TestCase): result = typ.serialize(node, colander.tests) self.assertEqual(result, 'colander.tests') + def test_serialize_class(self): + cls = self.__class__ + typ = self._makeOne() + node = DummySchemaNode(None) + result = typ.serialize(node, cls) + self.assertEqual(result, 'colander.tests.test_colander.TestGlobalObject') + + def test_deserialize_class_ok(self): + import colander + names = ( + 'colander.tests.test_colander.TestGlobalObject', + '.tests.test_colander.TestGlobalObject', + ) + typ = self._makeOne(colander) + node = DummySchemaNode(None) + for name in names: + result = typ.deserialize(node, name) + self.assertEqual(result, self.__class__) + + names = ('.TestGlobalObject',) + typ = self._makeOne(colander.tests.test_colander) + node = DummySchemaNode(None) + for name in names: + result = typ.deserialize(node, name) + self.assertEqual(result, self.__class__) + + def test_deserialize_class_fail(self): + import colander + names = ('.test_colander.TestGlobalObject', + '.TestGlobalObject') + typ = self._makeOne(colander) + node = DummySchemaNode(None) + for name in names: + e = invalid_exc(typ.deserialize, node, name) + self.assertEqual(e.msg.interpolate(), + 'The dotted name "{0}" cannot be imported'.format(name)) + def test_serialize_fail(self): typ = self._makeOne() node = DummySchemaNode(None) From 7ada0d5a38449e4d0e4092c05323dc91b64410e5 Mon Sep 17 00:00:00 2001 From: "jay.hennen" Date: Tue, 18 Apr 2017 16:46:10 -0700 Subject: [PATCH 2/2] added GlobalObject intermediate module serialization test --- colander/tests/test_colander.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/colander/tests/test_colander.py b/colander/tests/test_colander.py index acae4af..eb3c8ff 100644 --- a/colander/tests/test_colander.py +++ b/colander/tests/test_colander.py @@ -2095,6 +2095,12 @@ class TestGlobalObject(unittest.TestCase): node = DummySchemaNode(None) result = typ.serialize(node, colander.tests) self.assertEqual(result, 'colander.tests') + + from colander import tests + typ = self._makeOne() + node = DummySchemaNode(None) + result = typ.serialize(node, tests) + self.assertEqual(result, 'colander.tests') def test_serialize_class(self): cls = self.__class__