New submission from Thomas <thomas.d.mc...@gmail.com>:
@classmethod defines a __wrapped__ attribute that always points to the inner most function in a decorator chain while functool's update_wrapper has been fixed to set the wrapper.__wrapped__ attribute after updating the wrapper.__dict__ (see https://bugs.python.org/issue17482) so .__wrapped__ points to the next decorator in the chain. This results in inconsistency of the value of the.__wrapped__ attribute. Consider this code: from functools import update_wrapper class foo_deco: def __init__(self, func): self._func = func update_wrapper(self, func) def __call__(self, *args, **kwargs): return self._func(*args, **kwargs) class bar_deco: def __init__(self, func): self._func = func update_wrapper(self, func) def __call__(self, *args, **kwargs): return self._func(*args, **kwargs) class Foo: @classmethod @foo_deco def bar_cm(self): pass @bar_deco @foo_deco def bar_bar(self): pass print(Foo.bar_cm.__wrapped__) # <function Foo.bar_cm at 0x7fb0254433a0> print(Foo.bar_bar.__wrapped__) # <__main__.foo_deco object at 0x7fb025445fd0> # The foo_deco object is available on bar_cm this way though print(Foo.__dict__['bar_cm'].__func__) # <__main__.foo_deco object at 0x7fb025445fa0> It would be more consistent if the fix that was applied to update_wrapper was ported to classmethod's construction (or classmethod could invoke update_wrapper directly, maybe). It's also worth noting that @staticmethod behaves the same and @property doesn't define a .__wrapped__ attribute. For @property, I don't know if this is by design or if it was just never ported, but I believe it would be a great addition just to be able to go down a decorator chain without having to special-case the code. ---------- components: Extension Modules messages: 399965 nosy: Thomas701 priority: normal severity: normal status: open title: @classmethod doesn't set __wrapped__ the same way as functool's update_wrapper type: behavior versions: Python 3.9 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue44961> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com