diff options
author | Raymond Hettinger <rhettinger@users.noreply.github.com> | 2023-10-27 05:24:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-27 05:24:56 (GMT) |
commit | 7f9a99e8549b792662f2cd28bf38a4d4625bd402 (patch) | |
tree | 3e31df6a620f6a41c9a3547187ee794bbe343823 /Doc | |
parent | ee2d22f06d8a4ca13b2dba5e8a7a639a3997cc69 (diff) | |
download | cpython-7f9a99e8549b792662f2cd28bf38a4d4625bd402.zip cpython-7f9a99e8549b792662f2cd28bf38a4d4625bd402.tar.gz cpython-7f9a99e8549b792662f2cd28bf38a4d4625bd402.tar.bz2 |
gh-89519: Remove classmethod descriptor chaining, deprecated since 3.11 (gh-110163)
Diffstat (limited to 'Doc')
-rw-r--r-- | Doc/howto/descriptor.rst | 41 | ||||
-rw-r--r-- | Doc/library/functions.rst | 2 | ||||
-rw-r--r-- | Doc/whatsnew/3.13.rst | 8 |
3 files changed, 19 insertions, 32 deletions
diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 1d9424c..024c1eb 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -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 diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index a5f580c..a72f779 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -285,7 +285,7 @@ are always available. They are listed here in alphabetical order. ``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``) and have a new ``__wrapped__`` attribute. - .. versionchanged:: 3.11 + .. deprecated-removed:: 3.11 3.13 Class methods can no longer wrap other :term:`descriptors <descriptor>` such as :func:`property`. diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 1053aa5..34dd3ea 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1228,6 +1228,14 @@ Deprecated Removed ------- +* Removed chained :class:`classmethod` descriptors (introduced in + :issue:`19072`). This 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 :attr:`!__wrapped__` + attribute that was added in Python 3.10. (Contributed by Raymond + Hettinger in :gh:`89519`.) + * Remove many APIs (functions, macros, variables) with names prefixed by ``_Py`` or ``_PY`` (considered as private API). If your project is affected by one of these removals and you consider that the removed API should remain |