PEP 702: Move to warnings, expand spec (#3442)
This commit is contained in:
parent
c972a76923
commit
00295ada36
|
@ -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
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue