mirror of
https://github.com/python/cpython.git
synced 2025-11-03 03:22:27 +00:00
gh-89519: Remove classmethod descriptor chaining, deprecated since 3.11 (gh-110163)
This commit is contained in:
parent
ee2d22f06d
commit
7f9a99e854
8 changed files with 25 additions and 193 deletions
|
|
@ -1141,6 +1141,16 @@ roughly equivalent to:
|
|||
obj = self.__self__
|
||||
return func(obj, *args, **kwargs)
|
||||
|
||||
def __getattribute__(self, name):
|
||||
"Emulate method_getset() in Objects/classobject.c"
|
||||
if name == '__doc__':
|
||||
return self.__func__.__doc__
|
||||
return object.__getattribute__(self, name)
|
||||
|
||||
def __getattr__(self, name):
|
||||
"Emulate method_getattro() in Objects/classobject.c"
|
||||
return getattr(self.__func__, name)
|
||||
|
||||
To support automatic creation of methods, functions include the
|
||||
:meth:`__get__` method for binding methods during attribute access. This
|
||||
means that functions are non-data descriptors that return bound methods
|
||||
|
|
@ -1420,10 +1430,6 @@ Using the non-data descriptor protocol, a pure Python version of
|
|||
def __get__(self, obj, cls=None):
|
||||
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)
|
||||
|
||||
.. testcode::
|
||||
|
|
@ -1436,11 +1442,6 @@ Using the non-data descriptor protocol, a pure Python version of
|
|||
"Class method that returns a tuple"
|
||||
return (cls.__name__, x, y)
|
||||
|
||||
@ClassMethod
|
||||
@property
|
||||
def __doc__(cls):
|
||||
return f'A doc for {cls.__name__!r}'
|
||||
|
||||
|
||||
.. doctest::
|
||||
:hide:
|
||||
|
|
@ -1453,10 +1454,6 @@ Using the non-data descriptor protocol, a pure Python version of
|
|||
>>> t.cm(11, 22)
|
||||
('T', 11, 22)
|
||||
|
||||
# Check the alternate path for chained descriptors
|
||||
>>> T.__doc__
|
||||
"A doc for 'T'"
|
||||
|
||||
# Verify that T uses our emulation
|
||||
>>> type(vars(T)['cm']).__name__
|
||||
'ClassMethod'
|
||||
|
|
@ -1481,24 +1478,6 @@ Using the non-data descriptor protocol, a pure Python version of
|
|||
('T', 11, 22)
|
||||
|
||||
|
||||
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. In Python 3.11, this functionality was deprecated.
|
||||
|
||||
.. testcode::
|
||||
|
||||
class G:
|
||||
@classmethod
|
||||
@property
|
||||
def __doc__(cls):
|
||||
return f'A doc for {cls.__name__!r}'
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> G.__doc__
|
||||
"A doc for 'G'"
|
||||
|
||||
The :func:`functools.update_wrapper` call in ``ClassMethod`` adds a
|
||||
``__wrapped__`` attribute that refers to the underlying function. Also
|
||||
it carries forward the attributes necessary to make the wrapper look
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue