8000 Add @typing_extensions.deprecated (#105) · python/typing_extensions@673e5ce · GitHub
[go: up one dir, main page]

Skip to content

Commit 673e5ce

Browse files
Add @typing_extensions.deprecated (#105)
See PEP 702, python/peps#2942.
1 parent 27646ec commit 673e5ce

File tree

4 files changed

+77
-1
lines changed

4 files changed

+77
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Unreleased
22

3+
- Runtime support for PEP 702, adding `typing_extensions.deprecated`. Patch
4+
by Jelle Zijlstra.
35
- Add better default value for TypeVar `default` parameter, PEP 696. Enables
46
runtime check if `None` was passed as default. Patch by Marc Mueller (@cdce8p).
57
- The `@typing_extensions.override` decorator now sets the `.__override__`

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ This module currently contains the following:
3838
- `override` (see [PEP 698](https://peps.python.org/pep-0698/))
3939
- The `default=` argument to `TypeVar`, `ParamSpec`, and `TypeVarTuple` (see [PEP 696](https://peps.python.org/pep-0696/))
4040
- The `infer_variance=` argument to `TypeVar` (see [PEP 695](https://peps.python.org/pep-0695/))
41+
- The `@deprecated` decorator (see [PEP 702](https://peps.python.org/pep-0698/))
4142

4243
- In `typing` since Python 3.11
4344

src/test_typing_extensions.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from typing_extensions import assert_type, get_type_hints, get_origin, get_args
3030
from typing_extensions import clear_overloads, get_overloads, overload
3131
from typing_extensions import NamedTuple
32-
from typing_extensions import override
32+
from typing_extensions import override, deprecated
3333
from _typed_dict_test_helper import Foo, FooGeneric
3434

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

204204

205+
class DeprecatedTests(BaseTestCase):
206+
def test_deprecated(self):
207+
@deprecated("A will go away soon")
208+
class A:
209+
pass
210+
211+
self.assertEqual(A.__deprecated__, "A will go away soon")
212+
self.assertIsInstance(A, type)
213+
214+
@deprecated("b will go away soon")
215+
def b():
216+
pass
217+
218+
self.assertEqual(b.__deprecated__, "b will go away soon")
219+
self.assertIsInstance(b, types.FunctionType)
220+
221+
@overload
222+
@deprecated("no more ints")
223+
def h(x: int) -> int: ...
224+
@overload
225+
def h(x: str) -> str: ...
226+
def h(x):
227+
return x
228+
229+
overloads = get_overloads(h)
230+
self.assertEqual(len(overloads), 2)
231+
self.assertEqual(overloads[0].__deprecated__, "no more ints")
232+
233+
205234
class AnyTests(BaseTestCase):
206235
def test_can_subclass(self):
207236
class Mock(Any): pass

src/typing_extensions.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
'assert_type',
5353
'clear_overloads',
5454
'dataclass_transform',
55+
'deprecated',
5556
'get_overloads',
5657
'final',
5758
'get_args',
@@ -2129,6 +2130,49 @@ def method(self) -> None:
21292130
return __arg
21302131

21312132

2133+
if hasattr(typing, "deprecated"):
2134+
deprecated = typing.deprecated
2135+
else:
2136+
_T = typing.TypeVar("_T")
2137+
2138+
def deprecated(__msg: str) -> typing.Callable[[_T], _T]:
2139+
"""Indicate that a class, function or overload is deprecated.
2140+
2141+
Usage:
2142+
2143+
@deprecated("Use B instead")
2144+
class A:
2145+
pass
2146+
2147+
@deprecated("Use g instead")
2148+
def f():
2149+
pass
2150+
2151+
@overload
2152+
@deprecated("int support is deprecated")
2153+
def g(x: int) -> int: ...
2154+
@overload
2155+
def g(x: str) -> int: ...
2156+
2157+
When this decorator is applied to an object, the type checker
2158+
will generate a diagnostic on usage of the deprecated object.
2159+
2160+
No runtime warning is issued. The decorator sets the ``__deprecated__``
2161+
attribute on the decorated object to the deprecation message
2162+
passed to the decorator. If applied to an overload, the decorator
2163+
must be after the ``@overload`` decorator for the attribute to
2164+
exist on the overload as returned by ``get_overloads()``.
2165+
2166+
See PEP 702 for details.
2167+
2168+
"""
2169+
def decorator(__arg: _T) -> _T:
2170+
__arg.__deprecated__ = __msg
2171+
return __arg
2172+
2173+
return decorator
2174+
2175+
21322176
# We have to do some monkey patching to deal with the dual nature of
21332177
# Unpack/TypeVarTuple:
21342178
# - We want Unpack to be a kind of TypeVar so it gets accepted in

0 commit comments

Comments
 (0)
0