From d7ef46503f4a1a49e56b4ffc6a39f4200b35168e Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Mon, 16 Sep 2013 15:02:33 -0400 Subject: [PATCH] Un-break wrapping of callable instances as 'colander.deferred'. Fixes #141. --- CHANGES.txt | 9 +++++++++ colander/__init__.py | 5 ++++- colander/tests/test_colander.py | 28 +++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index ce772d7..63f1b89 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,12 @@ +Unreleased +---------- + +Bug Fixes +~~~~~~~~~ + +- Un-break wrapping of callable instances as ``colander.deferred``. + See https://github.com/Pylons/colander/issues/141. + 1.0b1 (2013-09-01) ------------------ diff --git a/colander/__init__.py b/colander/__init__.py index 15e70a7..bbebe4b 100644 --- a/colander/__init__.py +++ b/colander/__init__.py @@ -2129,7 +2129,10 @@ class deferred(object): """ A decorator which can be used to define deferred schema values (missing values, widgets, validators, etc.)""" def __init__(self, wrapped): - functools.update_wrapper(self, wrapped) + try: + functools.update_wrapper(self, wrapped) + except AttributeError: #non-function + self.__doc__ = getattr(wrapped, '__doc__', None) self.wrapped = wrapped def __call__(self, node, kw): diff --git a/colander/tests/test_colander.py b/colander/tests/test_colander.py index 51d8266..7d60998 100644 --- a/colander/tests/test_colander.py +++ b/colander/tests/test_colander.py @@ -3052,12 +3052,34 @@ class TestDeferred(unittest.TestCase): self.assertEqual(result, 'abc') def test_retain_func_details(self): - def wrapper_func(node, kw): + def wrapped_func(node, kw): """Can you hear me now?""" pass # pragma: no cover - inst = self._makeOne(wrapper_func) + inst = self._makeOne(wrapped_func) self.assertEqual(inst.__doc__, 'Can you hear me now?') - self.assertEqual(inst.__name__, 'wrapper_func') + 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):