GeezerVison is showing github.com — Add @typing_extensions.deprecated (#105) · python/typing_extensions@673e5ce
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: CHANGELOG.md +2Lines changed: 2 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | # Unreleased | 2 | 2 |
| | 3 | +- Runtime support for PEP 702, adding `typing_extensions.deprecated`. Patch | | 4 | + by Jelle Zijlstra. | 3 | 5 | - Add better default value for TypeVar `default` parameter, PEP 696. Enables | 4 | 6 | runtime check if `None` was passed as default. Patch by Marc Mueller (@cdce8p). | 5 | 7 | - The `@typing_extensions.override` decorator now sets the `.__override__` | |
Collapse file Copy file name to clipboardExpand all lines: README.md +1Lines changed: 1 addition & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -38,6 +38,7 @@ This module currently contains the following: | 38 | 38 | - `override` (see [PEP 698](https://peps.python.org/pep-0698/)) | 39 | 39 | - The `default=` argument to `TypeVar`, `ParamSpec`, and `TypeVarTuple` (see [PEP 696](https://peps.python.org/pep-0696/)) | 40 | 40 | - 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/)) | 41 | 42 |
| 42 | 43 | - In `typing` since Python 3.11 | 43 | 44 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/test_typing_extensions.py +30-1Lines changed: 30 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 29 | 29 | from typing_extensions import assert_type, get_type_hints, get_origin, get_args | 30 | 30 | from typing_extensions import clear_overloads, get_overloads, overload | 31 | 31 | from typing_extensions import NamedTuple | 32 | | -from typing_extensions import override | | 32 | +from typing_extensions import override, deprecated | 33 | 33 | from _typed_dict_test_helper import Foo, FooGeneric | 34 | 34 |
| 35 | 35 | # Flags used to mark tests that only apply after a specific | @@ -202,6 +202,35 @@ def static_method_bad_order(): | 202 | 202 | self.assertIs(False, hasattr(Derived.static_method_bad_order, "__override__")) | 203 | 203 |
| 204 | 204 |
| | 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 | + | 205 | 234 | class AnyTests(BaseTestCase): | 206 | 235 | def test_can_subclass(self): | 207 | 236 | class Mock(Any): pass | |
Collapse file Copy file name to clipboardExpand all lines: src/typing_extensions.py +44Lines changed: 44 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 52 | 52 | 'assert_type', | 53 | 53 | 'clear_overloads', | 54 | 54 | 'dataclass_transform', | | 55 | + 'deprecated', | 55 | 56 | 'get_overloads', | 56 | 57 | 'final', | 57 | 58 | 'get_args', | @@ -2129,6 +2130,49 @@ def method(self) -> None: | 2129 | 2130 | return __arg | 2130 | 2131 |
| 2131 | 2132 |
| | 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 | + | 2132 | 2176 | # We have to do some monkey patching to deal with the dual nature of | 2133 | 2177 | # Unpack/TypeVarTuple: | 2134 | 2178 | # - We want Unpack to be a kind of TypeVar so it gets accepted in | |
|