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:
Marc Tamlyn 2014-02-09 11:10:05 +00:00
parent 97a8fd4682
commit 80cd64ee17
2 changed files with 38 additions and 2 deletions

View File

@ -22,7 +22,7 @@ def method_decorator(decorator):
def _wrapper(self, *args, **kwargs):
@decorator
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
# 'self' argument, but it is a closure over self so it can call
# 'func' correctly.

View File

@ -232,9 +232,45 @@ class MethodDecoratorTests(TestCase):
def method(self):
return True
# t = Test()
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):
"""