From c17f63fae57dc02e78bd6931b8fb6c6c2f9d4d81 Mon Sep 17 00:00:00 2001 From: "Miss Skeleton (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Fri, 23 Oct 2020 19:01:35 -0700 Subject: [PATCH] bpo-19072: Update descriptor howto for decorator chaining (GH-22934) (GH-22935) --- Doc/howto/descriptor.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 4a53b9e6156..4e9fad30d31 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -872,6 +872,16 @@ Using the non-data descriptor protocol, a pure Python version of def __get__(self, obj, cls=None): if cls is None: cls = type(obj) - def newfunc(*args): - return self.f(cls, *args) - return newfunc + if hasattr(obj, '__get__'): + return self.f.__get__(cls) + return types.MethodType(self.f, cls) + +The code path for ``hasattr(obj, '__get__')`` was added in Python 3.9 and +makes it possible for :func:`classmethod` to support chained decorators. +For example, a classmethod and property could be chained together:: + + class G: + @classmethod + @property + def __doc__(cls): + return f'A doc for {cls.__name__!r}'