Fixed #33043 -- Made method_decorator() preserve wrapper assignments.

Regression in f434f5b84f.
This commit is contained in:
Vinay Karanam 2021-08-23 18:28:38 +05:30 committed by Mariusz Felisiak
parent 004b4620f6
commit 8806e8809e
2 changed files with 24 additions and 1 deletions

View File

@ -37,7 +37,7 @@ def _multi_decorate(decorators, method):
# 'self' argument, but it's a closure over self so it can call # 'self' argument, but it's a closure over self so it can call
# 'func'. Also, wrap method.__get__() in a function because new # 'func'. Also, wrap method.__get__() in a function because new
# attributes can't be set on bound method objects, only on functions. # attributes can't be set on bound method objects, only on functions.
bound_method = partial(method.__get__(self, type(self))) bound_method = wraps(method)(partial(method.__get__(self, type(self))))
for dec in decorators: for dec in decorators:
bound_method = dec(bound_method) bound_method = dec(bound_method)
return bound_method(*args, **kwargs) return bound_method(*args, **kwargs)

View File

@ -425,6 +425,29 @@ class MethodDecoratorTests(SimpleTestCase):
def __module__(cls): def __module__(cls):
return "tests" return "tests"
def test_wrapper_assignments(self):
"""@method_decorator preserves wrapper assignments."""
func_name = None
func_module = None
def decorator(func):
@wraps(func)
def inner(*args, **kwargs):
nonlocal func_name, func_module
func_name = getattr(func, '__name__', None)
func_module = getattr(func, '__module__', None)
return func(*args, **kwargs)
return inner
class Test:
@method_decorator(decorator)
def method(self):
return 'tests'
Test().method()
self.assertEqual(func_name, 'method')
self.assertIsNotNone(func_module)
class XFrameOptionsDecoratorsTests(TestCase): class XFrameOptionsDecoratorsTests(TestCase):
""" """