From 14940fdd96e77778cacdf0963913a343b1f33b9a Mon Sep 17 00:00:00 2001 From: dpwrussell Date: Tue, 26 Nov 2013 12:00:50 +0000 Subject: [PATCH] Fixed #21513 -- Added method_decorator support for argumented decorator Copied attributes into the decorated method and special case __name__ copy as this will not be present on a Class object. Added regression test to decorator suite. --- django/utils/decorators.py | 8 ++++++-- tests/decorators/tests.py | 22 +++++++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/django/utils/decorators.py b/django/utils/decorators.py index 7b3d25f988..4ccf1d69df 100644 --- a/django/utils/decorators.py +++ b/django/utils/decorators.py @@ -39,9 +39,13 @@ def method_decorator(decorator): update_wrapper(_wrapper, func) return _wrapper - update_wrapper(_dec, decorator) + + update_wrapper(_dec, decorator, assigned=available_attrs(decorator)) # Change the name to aid debugging. - _dec.__name__ = 'method_decorator(%s)' % decorator.__name__ + if hasattr(decorator, '__name__'): + _dec.__name__ = 'method_decorator(%s)' % decorator.__name__ + else: + _dec.__name__ = 'method_decorator(%s)' % decorator.__class__.__name__ return _dec diff --git a/tests/decorators/tests.py b/tests/decorators/tests.py index 9c654e500a..bd4fa4756c 100644 --- a/tests/decorators/tests.py +++ b/tests/decorators/tests.py @@ -1,4 +1,4 @@ -from functools import wraps +from functools import wraps, update_wrapper from unittest import TestCase import warnings @@ -174,6 +174,16 @@ def myattr2_dec(func): myattr2_dec_m = method_decorator(myattr2_dec) +class ClsDec(object): + def __init__(self, myattr): + self.myattr = myattr + + def __call__(self, f): + + def wrapped(): + return f() and self.myattr + return update_wrapper(wrapped, f) + class MethodDecoratorTests(TestCase): """ @@ -214,6 +224,16 @@ class MethodDecoratorTests(TestCase): self.assertEqual(Test.method.__doc__, 'A method') self.assertEqual(Test.method.__name__, 'method') + # Test for argumented decorator + def test_argumented(self): + class Test(object): + @method_decorator(ClsDec(False)) + def method(self): + return True + + # t = Test() + self.assertEqual(Test().method(), False) + class XFrameOptionsDecoratorsTests(TestCase): """