From abcc3d75f6e570519cb37c62130a2295c6928bff Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 1 Feb 2022 18:48:55 -0800 Subject: bpo-46414: Add typing.reveal_type (#30646) Co-authored-by: Nikita Sobolev --- Doc/library/typing.rst | 31 ++++++++++++++++++++++ Lib/test/test_typing.py | 11 +++++++- Lib/typing.py | 21 +++++++++++++++ .../2022-01-17-10-00-02.bpo-46414.Ld0b_y.rst | 1 + 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2022-01-17-10-00-02.bpo-46414.Ld0b_y.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index cdfd403..9007c0d 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1932,6 +1932,37 @@ Functions and decorators runtime we intentionally don't check anything (we want this to be as fast as possible). +.. function:: reveal_type(obj) + + Reveal the inferred static type of an expression. + + When a static type checker encounters a call to this function, + it emits a diagnostic with the type of the argument. For example:: + + x: int = 1 + reveal_type(x) # Revealed type is "builtins.int" + + This can be useful when you want to debug how your type checker + handles a particular piece of code. + + The function returns its argument unchanged, which allows using + it within an expression:: + + x = reveal_type(1) # Revealed type is "builtins.int" + + Most type checkers support ``reveal_type()`` anywhere, even if the + name is not imported from ``typing``. Importing the name from + ``typing`` allows your code to run without runtime errors and + communicates intent more clearly. + + At runtime, this function prints the runtime type of its argument to stderr + and returns it unchanged:: + + x = reveal_type(1) # prints "Runtime type is int" + print(x) # prints "1" + + .. versionadded:: 3.11 + .. decorator:: overload The ``@overload`` decorator allows describing functions and methods diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 090d4c7..85f7406 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -20,6 +20,7 @@ from typing import cast, runtime_checkable from typing import get_type_hints from typing import get_origin, get_args from typing import is_typeddict +from typing import reveal_type from typing import no_type_check, no_type_check_decorator from typing import Type from typing import NamedTuple, TypedDict @@ -34,7 +35,7 @@ import typing import weakref import types -from test.support import import_helper +from test.support import import_helper, captured_stderr from test import mod_generics_cache from test import _typed_dict_helper @@ -5289,6 +5290,14 @@ class SpecialAttrsTests(BaseTestCase): self.assertIn('baz', dir(Foo[int])) +class RevealTypeTests(BaseTestCase): + def test_reveal_type(self): + obj = object() + with captured_stderr() as stderr: + self.assertIs(obj, reveal_type(obj)) + self.assertEqual(stderr.getvalue(), "Runtime type is 'object'\n") + + class AllTests(BaseTestCase): """Tests for __all__.""" diff --git a/Lib/typing.py b/Lib/typing.py index dac9c6c..0cf9755 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -130,6 +130,7 @@ __all__ = [ 'overload', 'ParamSpecArgs', 'ParamSpecKwargs', + 'reveal_type', 'runtime_checkable', 'Text', 'TYPE_CHECKING', @@ -2675,3 +2676,23 @@ class re(metaclass=_DeprecatedType): re.__name__ = __name__ + '.re' sys.modules[re.__name__] = re + + +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 diff --git a/Misc/NEWS.d/next/Library/2022-01-17-10-00-02.bpo-46414.Ld0b_y.rst b/Misc/NEWS.d/next/Library/2022-01-17-10-00-02.bpo-46414.Ld0b_y.rst new file mode 100644 index 0000000..0fdbfa7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-17-10-00-02.bpo-46414.Ld0b_y.rst @@ -0,0 +1 @@ +Add :func:`typing.reveal_type`. Patch by Jelle Zijlstra. -- cgit v0.12