Skip to content

Commit ebaf094

Browse files
authored
GH-89519: Deprecate classmethod descriptor chaining (#92379)
1 parent bebb944 commit ebaf094

File tree

4 files changed

+20
-1
lines changed

4 files changed

+20
-1
lines changed

Doc/howto/descriptor.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,8 @@ Using the non-data descriptor protocol, a pure Python version of
13491349
if cls is None:
13501350
cls = type(obj)
13511351
if hasattr(type(self.f), '__get__'):
1352+
# This code path was added in Python 3.9
1353+
# and was deprecated in Python 3.11.
13521354
return self.f.__get__(cls, cls)
13531355
return MethodType(self.f, cls)
13541356

@@ -1386,7 +1388,7 @@ Using the non-data descriptor protocol, a pure Python version of
13861388
The code path for ``hasattr(type(self.f), '__get__')`` was added in
13871389
Python 3.9 and makes it possible for :func:`classmethod` to support
13881390
chained decorators. For example, a classmethod and property could be
1389-
chained together:
1391+
chained together. In Python 3.11, this functionality was deprecated.
13901392

13911393
.. testcode::
13921394

Doc/library/functions.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,11 @@ are always available. They are listed here in alphabetical order.
271271
``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``) and
272272
have a new ``__wrapped__`` attribute.
273273

274+
.. versionchanged:: 3.11
275+
Class methods can no longer wrap other :term:`descriptors <descriptor>` such as
276+
:func:`property`.
277+
278+
274279
.. function:: compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
275280

276281
Compile the *source* into a code or AST object. Code objects can be executed

Doc/whatsnew/3.11.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,14 @@ CPython bytecode changes
10841084
Deprecated
10851085
==========
10861086

1087+
* Chaining :class:`classmethod` descriptors (introduced in :issue:`19072`)
1088+
is now deprecated. It can no longer be used to wrap other descriptors
1089+
such as :class:`property`. The core design of this feature was flawed
1090+
and caused a number of downstream problems. To "pass-through" a
1091+
:class:`classmethod`, consider using the ``__wrapped__`` attribute
1092+
that was added in Python 3.10.
1093+
(Contributed by Raymond Hettinger in :gh:`89519`.)
1094+
10871095
* Octal escapes with value larger than ``0o377`` now produce
10881096
a :exc:`DeprecationWarning`.
10891097
In a future Python version they will be a :exc:`SyntaxWarning` and
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Chaining classmethod descriptors (introduced in bpo-19072) is deprecated. It
2+
can no longer be used to wrap other descriptors such as property(). The
3+
core design of this feature was flawed, and it caused a number of downstream
4+
problems.

0 commit comments

Comments
 (0)