Skip to content

Commit

Permalink
Add @typing_extensions.deprecated (#105)
Browse files Browse the repository at this point in the history
See PEP 702, python/peps#2942.
  • Loading branch information
JelleZijlstra committed Jan 3, 2023
1 parent 27646ec commit 673e5ce
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,7 @@
# Unreleased

- Runtime support for PEP 702, adding `typing_extensions.deprecated`. Patch
by Jelle Zijlstra.
- Add better default value for TypeVar `default` parameter, PEP 696. Enables
runtime check if `None` was passed as default. Patch by Marc Mueller (@cdce8p).
- The `@typing_extensions.override` decorator now sets the `.__override__`
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -38,6 +38,7 @@ This module currently contains the following:
- `override` (see [PEP 698](https://peps.python.org/pep-0698/))
- The `default=` argument to `TypeVar`, `ParamSpec`, and `TypeVarTuple` (see [PEP 696](https://peps.python.org/pep-0696/))
- The `infer_variance=` argument to `TypeVar` (see [PEP 695](https://peps.python.org/pep-0695/))
- The `@deprecated` decorator (see [PEP 702](https://peps.python.org/pep-0698/))

- In `typing` since Python 3.11

Expand Down
31 changes: 30 additions & 1 deletion src/test_typing_extensions.py
Expand Up @@ -29,7 +29,7 @@
from typing_extensions import assert_type, get_type_hints, get_origin, get_args
from typing_extensions import clear_overloads, get_overloads, overload
from typing_extensions import NamedTuple
from typing_extensions import override
from typing_extensions import override, deprecated
from _typed_dict_test_helper import Foo, FooGeneric

# Flags used to mark tests that only apply after a specific
Expand Down Expand Up @@ -202,6 +202,35 @@ def static_method_bad_order():
self.assertIs(False, hasattr(Derived.static_method_bad_order, "__override__"))


class DeprecatedTests(BaseTestCase):
def test_deprecated(self):
@deprecated("A will go away soon")
class A:
pass

self.assertEqual(A.__deprecated__, "A will go away soon")
self.assertIsInstance(A, type)

@deprecated("b will go away soon")
def b():
pass

self.assertEqual(b.__deprecated__, "b will go away soon")
self.assertIsInstance(b, types.FunctionType)

@overload
@deprecated("no more ints")
def h(x: int) -> int: ...
@overload
def h(x: str) -> str: ...
def h(x):
return x

overloads = get_overloads(h)
self.assertEqual(len(overloads), 2)
self.assertEqual(overloads[0].__deprecated__, "no more ints")


class AnyTests(BaseTestCase):
def test_can_subclass(self):
class Mock(Any): pass
Expand Down
44 changes: 44 additions & 0 deletions src/typing_extensions.py
Expand Up @@ -52,6 +52,7 @@
'assert_type',
'clear_overloads',
'dataclass_transform',
'deprecated',
'get_overloads',
'final',
'get_args',
Expand Down Expand Up @@ -2129,6 +2130,49 @@ def method(self) -> None:
return __arg


if hasattr(typing, "deprecated"):
deprecated = typing.deprecated
else:
_T = typing.TypeVar("_T")

def deprecated(__msg: str) -> typing.Callable[[_T], _T]:
"""Indicate that a class, function or overload is deprecated.
Usage:
@deprecated("Use B instead")
class A:
pass
@deprecated("Use g instead")
def f():
pass
@overload
@deprecated("int support is deprecated")
def g(x: int) -> int: ...
@overload
def g(x: str) -> int: ...
When this decorator is applied to an object, the type checker
will generate a diagnostic on usage of the deprecated object.
No runtime warning is issued. The decorator sets the ``__deprecated__``
attribute on the decorated object to the deprecation message
passed to the decorator. If applied to an overload, the decorator
must be after the ``@overload`` decorator for the attribute to
exist on the overload as returned by ``get_overloads()``.
See PEP 702 for details.
"""
def decorator(__arg: _T) -> _T:
__arg.__deprecated__ = __msg
return __arg

return decorator


# We have to do some monkey patching to deal with the dual nature of
# Unpack/TypeVarTuple:
# - We want Unpack to be a kind of TypeVar so it gets accepted in
Expand Down

0 comments on commit 673e5ce

Please sign in to comment.