Fixed #21247 -- Made method_decorator play nicely with descriptors
When a method decorator was used in conjunction with a decorator implemented as a descriptor, method_decorator did not correctly respect the method binding. Thanks for Graham Dumpleton for the report and initial patch.
This commit is contained in:
parent
97a8fd4682
commit
80cd64ee17
|
@ -22,7 +22,7 @@ def method_decorator(decorator):
|
||||||
def _wrapper(self, *args, **kwargs):
|
def _wrapper(self, *args, **kwargs):
|
||||||
@decorator
|
@decorator
|
||||||
def bound_func(*args2, **kwargs2):
|
def bound_func(*args2, **kwargs2):
|
||||||
return func(self, *args2, **kwargs2)
|
return func.__get__(self, type(self))(*args2, **kwargs2)
|
||||||
# bound_func has the signature that 'decorator' expects i.e. no
|
# bound_func has the signature that 'decorator' expects i.e. no
|
||||||
# 'self' argument, but it is a closure over self so it can call
|
# 'self' argument, but it is a closure over self so it can call
|
||||||
# 'func' correctly.
|
# 'func' correctly.
|
||||||
|
|
|
@ -232,9 +232,45 @@ class MethodDecoratorTests(TestCase):
|
||||||
def method(self):
|
def method(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# t = Test()
|
|
||||||
self.assertEqual(Test().method(), False)
|
self.assertEqual(Test().method(), False)
|
||||||
|
|
||||||
|
def test_descriptors(self):
|
||||||
|
|
||||||
|
def original_dec(wrapped):
|
||||||
|
def _wrapped(arg):
|
||||||
|
return wrapped(arg)
|
||||||
|
|
||||||
|
return _wrapped
|
||||||
|
|
||||||
|
method_dec = method_decorator(original_dec)
|
||||||
|
|
||||||
|
class bound_wrapper(object):
|
||||||
|
def __init__(self, wrapped):
|
||||||
|
self.wrapped = wrapped
|
||||||
|
self.__name__ = wrapped.__name__
|
||||||
|
|
||||||
|
def __call__(self, arg):
|
||||||
|
return self.wrapped(arg)
|
||||||
|
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
return self
|
||||||
|
|
||||||
|
class descriptor_wrapper(object):
|
||||||
|
def __init__(self, wrapped):
|
||||||
|
self.wrapped = wrapped
|
||||||
|
self.__name__ = wrapped.__name__
|
||||||
|
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
return bound_wrapper(self.wrapped.__get__(instance, owner))
|
||||||
|
|
||||||
|
class Test(object):
|
||||||
|
@method_dec
|
||||||
|
@descriptor_wrapper
|
||||||
|
def method(self, arg):
|
||||||
|
return arg
|
||||||
|
|
||||||
|
self.assertEqual(Test().method(1), 1)
|
||||||
|
|
||||||
|
|
||||||
class XFrameOptionsDecoratorsTests(TestCase):
|
class XFrameOptionsDecoratorsTests(TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue