PEP 702: Move to warnings, expand spec (#3442)

This commit is contained in:
Jelle Zijlstra 2023-09-19 20:15:30 -07:00 committed by GitHub
parent c972a76923
commit 00295ada36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 51 additions and 13 deletions

View File

@ -7,7 +7,7 @@ Type: Standards Track
Topic: Typing Topic: Typing
Content-Type: text/x-rst Content-Type: text/x-rst
Created: 30-Dec-2022 Created: 30-Dec-2022
Python-Version: 3.12 Python-Version: 3.13
Post-History: `01-Jan-2023 <https://mail.python.org/archives/list/typing-sig@python.org/thread/AKTFUYW3WDT7R7PGRIJQZMYHMDJNE4QH/>`__, Post-History: `01-Jan-2023 <https://mail.python.org/archives/list/typing-sig@python.org/thread/AKTFUYW3WDT7R7PGRIJQZMYHMDJNE4QH/>`__,
`22-Jan-2023 <https://discuss.python.org/t/pep-702-marking-deprecations-using-the-type-system/23036>`__ `22-Jan-2023 <https://discuss.python.org/t/pep-702-marking-deprecations-using-the-type-system/23036>`__
@ -15,7 +15,7 @@ Post-History: `01-Jan-2023 <https://mail.python.org/archives/list/typing-sig@pyt
Abstract Abstract
======== ========
This PEP adds an ``@typing.deprecated()`` decorator that marks a class or function This PEP adds an ``@warnings.deprecated()`` decorator that marks a class or function
as deprecated, enabling static checkers to warn when it is used. By default, this as deprecated, enabling static checkers to warn when it is used. By default, this
decorator will also raise a runtime ``DeprecationWarning``. decorator will also raise a runtime ``DeprecationWarning``.
@ -99,7 +99,7 @@ There are similar existing third-party tools:
Specification Specification
============= =============
A new decorator ``@deprecated()`` is added to the :mod:`typing` module. This A new decorator ``@deprecated()`` is added to the :mod:`warnings` module. This
decorator can be used on a class, function or method to mark it as deprecated. decorator can be used on a class, function or method to mark it as deprecated.
This includes :class:`typing.TypedDict` and :class:`typing.NamedTuple` definitions. This includes :class:`typing.TypedDict` and :class:`typing.NamedTuple` definitions.
With overloaded functions, the decorator may be applied to individual overloads, With overloaded functions, the decorator may be applied to individual overloads,
@ -132,16 +132,20 @@ For deprecated classes and functions, this includes:
* If ``import *`` is used, usage of deprecated objects from the * If ``import *`` is used, usage of deprecated objects from the
module (``from module import *; x = deprecated_object()``) module (``from module import *; x = deprecated_object()``)
* ``from`` imports (``from module import deprecated_object``) * ``from`` imports (``from module import deprecated_object``)
* Any syntax that indirectly triggers a call to the function. For example,
if the ``__add__`` method of a class ``C`` is deprecated, then
the code ``C() + C()`` should trigger a diagnostic. Similarly, if the
setter of a property is marked deprecated, attempts to set the property
should trigger a diagnostic.
There are some additional scenarios where deprecations could come into play: If a method is marked with the :func:`typing.override` decorator from :pep:`698`
and the base class method it overrides is deprecated, the type checker should
produce a diagnostic.
* An object implements a :class:`typing.Protocol`, but one of the methods There are additional scenarios where deprecations could come into play.
required for protocol compliance is deprecated. For example, an object may implement a :class:`typing.Protocol`, but one
* A class uses the ``@override`` decorator from :pep:`698` to assert that of the methods required for protocol compliance is deprecated.
its method overrides a base class method, but the base class method is As scenarios such as this one appear complex and relatively unlikely to come up in practice,
deprecated.
As these scenarios appear complex and relatively unlikely to come up in practice,
this PEP does not mandate that type checkers detect them. this PEP does not mandate that type checkers detect them.
Example Example
@ -151,7 +155,7 @@ As an example, consider this library stub named ``library.pyi``:
.. code-block:: python .. code-block:: python
from typing import deprecated from warnings import deprecated
@deprecated("Use Spam instead") @deprecated("Use Spam instead")
class Ham: ... class Ham: ...
@ -165,6 +169,20 @@ As an example, consider this library stub named ``library.pyi``:
@overload @overload
def foo(x: str) -> str: ... def foo(x: str) -> str: ...
class Spam:
@deprecated("There is enough spam in the world")
def __add__(self, other: object) -> object: ...
@property
@deprecated("All spam will be equally greasy")
def greasy(self) -> float: ...
@property
def shape(self) -> str: ...
@shape.setter
@deprecated("Shapes are becoming immutable")
def shape(self, value: str) -> None: ...
Here is how type checkers should handle usage of this library: Here is how type checkers should handle usage of this library:
.. code-block:: python .. code-block:: python
@ -181,6 +199,15 @@ Here is how type checkers should handle usage of this library:
ham = Ham() # no error (already reported above) ham = Ham() # no error (already reported above)
spam = library.Spam()
spam + 1 # error: Use of deprecated method Spam.__add__. There is enough spam in the world.
spam.greasy # error: Use of deprecated property Spam.greasy. All spam will be equally greasy.
spam.shape # no error
spam.shape = "cube" # error: Use of deprecated property setter Spam.shape. Shapes are becoming immutable.
The exact wording of the diagnostics is up to the type checker and is not part
of the specification.
Runtime behavior Runtime behavior
---------------- ----------------
@ -209,6 +236,7 @@ To accommodate runtime introspection, the decorator sets an attribute
``__deprecated__`` on the object it is passed, as well as on the wrapper ``__deprecated__`` on the object it is passed, as well as on the wrapper
callables it generates for deprecated classes and functions. callables it generates for deprecated classes and functions.
The value of the attribute is the message passed to the decorator. The value of the attribute is the message passed to the decorator.
Decorating objecs that do not allow setting this attribute is not supported.
If a ``Protocol`` with the ``@runtime_checkable`` decorator is marked as deprecated, If a ``Protocol`` with the ``@runtime_checkable`` decorator is marked as deprecated,
the ``__deprecated__`` attribute should not be considered a member of the protocol, the ``__deprecated__`` attribute should not be considered a member of the protocol,
@ -263,7 +291,8 @@ Reference implementation
======================== ========================
A runtime implementation of the ``@deprecated`` decorator is A runtime implementation of the ``@deprecated`` decorator is
`available <https://github.com/python/typing_extensions/pull/105>`__. available in the `typing-extensions <https://pypi.org/project/typing-extensions/>`_
library since version 4.5.0.
The ``pyanalyze`` type checker has The ``pyanalyze`` type checker has
`prototype support <https://github.com/quora/pyanalyze/pull/578>`__ `prototype support <https://github.com/quora/pyanalyze/pull/578>`__
for emitting deprecation errors, as does for emitting deprecation errors, as does
@ -309,6 +338,15 @@ show that this feature is not commonly needed.
Features for deprecating more kinds of objects could be added in a future Features for deprecating more kinds of objects could be added in a future
PEP. PEP.
Placing the decorator in the ``typing`` module
----------------------------------------------
An earlier version of this PEP proposed placing the ``@deprecated``
decorator in the :mod:`typing` module. However, there was feedback
that it would be unexpected for a decorator in the :mod:`typing` module
to have runtime behavior. Therefore, the PEP now proposes adding the
decorator the :mod:`warnings` module instead.
Acknowledgments Acknowledgments
=============== ===============