if cls is None:
cls = type(obj)
if hasattr(type(self.f), '__get__'):
+ # This code path was added in Python 3.9
+ # and was deprecated in Python 3.11.
return self.f.__get__(cls, cls)
return MethodType(self.f, cls)
The code path for ``hasattr(type(self.f), '__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:
+chained together. In Python 3.11, this functionality was deprecated.
.. testcode::
``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``) and
have a new ``__wrapped__`` attribute.
+ .. versionchanged:: 3.11
+ Class methods can no longer wrap other :term:`descriptors <descriptor>` such as
+ :func:`property`.
+
+
.. function:: compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
Compile the *source* into a code or AST object. Code objects can be executed
Deprecated
==========
+* Chaining :class:`classmethod` descriptors (introduced in :issue:`19072`)
+ is now deprecated. It can no longer be used to wrap other descriptors
+ such as :class:`property`. The core design of this feature was flawed
+ and caused a number of downstream problems. To "pass-through" a
+ :class:`classmethod`, consider using the ``__wrapped__`` attribute
+ that was added in Python 3.10.
+ (Contributed by Raymond Hettinger in :gh:`89519`.)
+
* Octal escapes with value larger than ``0o377`` now produce
a :exc:`DeprecationWarning`.
In a future Python version they will be a :exc:`SyntaxWarning` and
--- /dev/null
+Chaining classmethod descriptors (introduced in bpo-19072) is deprecated. It
+can no longer be used to wrap other descriptors such as property(). The
+core design of this feature was flawed, and it caused a number of downstream
+problems.