diff --git a/typing_extensions/CHANGELOG b/typing_extensions/CHANGELOG index fd1abb93e..975a0032d 100644 --- a/typing_extensions/CHANGELOG +++ b/typing_extensions/CHANGELOG @@ -1,5 +1,6 @@ # Release 4.x.x +- Add `reveal_type`. Backport from bpo-46414. - Runtime support for PEP 681 and `typing_extensions.dataclass_transform`. - `Annotated` can now wrap `ClassVar` and `Final`. Backport from bpo-46491. Patch by Gregory Beauregard (@GBeauregard). diff --git a/typing_extensions/README.rst b/typing_extensions/README.rst index 28081c3d2..961bdf93e 100644 --- a/typing_extensions/README.rst +++ b/typing_extensions/README.rst @@ -40,6 +40,10 @@ This module currently contains the following: - ``@dataclass_transform()`` (see PEP 681) - ``NotRequired`` (see PEP 655) - ``Required`` (see PEP 655) + +- In ``typing`` since Python 3.11 + + - ``reveal_type`` - ``Self`` (see PEP 673) - In ``typing`` since Python 3.10 diff --git a/typing_extensions/src/test_typing_extensions.py b/typing_extensions/src/test_typing_extensions.py index cb32dd077..03a75e4c4 100644 --- a/typing_extensions/src/test_typing_extensions.py +++ b/typing_extensions/src/test_typing_extensions.py @@ -22,7 +22,7 @@ from typing_extensions import TypeAlias, ParamSpec, Concatenate, ParamSpecArgs, ParamSpecKwargs, TypeGuard from typing_extensions import Awaitable, AsyncIterator, AsyncContextManager, Required, NotRequired from typing_extensions import Protocol, runtime, runtime_checkable, Annotated, overload, final, is_typeddict -from typing_extensions import dataclass_transform +from typing_extensions import dataclass_transform, reveal_type try: from typing_extensions import get_type_hints except ImportError: @@ -2346,6 +2346,12 @@ def cached(self): ... self.assertIs(True, Methods.cached.__final__) +class RevealTypeTests(BaseTestCase): + def test_reveal_type(self): + obj = object() + self.assertIs(obj, reveal_type(obj)) + + class DataclassTransformTests(BaseTestCase): def test_decorator(self): def create_model(*, frozen: bool = False, kw_only: bool = True): diff --git a/typing_extensions/src/typing_extensions.py b/typing_extensions/src/typing_extensions.py index bcf169530..b594e33f7 100644 --- a/typing_extensions/src/typing_extensions.py +++ b/typing_extensions/src/typing_extensions.py @@ -78,6 +78,7 @@ def _check_generic(cls, parameters): 'NewType', 'overload', 'Protocol', + 'reveal_type', 'runtime', 'runtime_checkable', 'Text', @@ -2343,6 +2344,29 @@ class Movie(TypedDict): Required = _Required(_root=True) NotRequired = _NotRequired(_root=True) +if hasattr(typing, "reveal_type"): + reveal_type = typing.reveal_type +else: + def reveal_type(__obj: T) -> T: + """Reveal the inferred type of a variable. + + When a static type checker encounters a call to ``reveal_type()``, + it will emit the inferred type of the argument:: + + x: int = 1 + reveal_type(x) + + Running a static type checker (e.g., ``mypy``) on this example + will produce output similar to 'Revealed type is "builtins.int"'. + + At runtime, the function prints the runtime type of the + argument and returns it unchanged. + + """ + print(f"Runtime type is {type(__obj).__name__!r}", file=sys.stderr) + return __obj + + if hasattr(typing, 'dataclass_transform'): dataclass_transform = typing.dataclass_transform else: