diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 9007c0daf59a4d..c719979552397f 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1963,6 +1963,25 @@ Functions and decorators .. versionadded:: 3.11 +.. function:: reveal_locals() + + Reveal the inferred static types of all local variables. + + When a static type checker encounters a call to this function, + it emits a diagnostic with the types of all variables in the current + scope. For example:: + + def greet(user_id: int) -> None: + message = f"Hello user #{user_id}" + reveal_locals() # Revealed local types are: user_id: int, message: str + + Like :func:`reveal_type`, this function is useful for debugging how + the type checker understands a piece of code. + + At runtime, this function does nothing. + + .. 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 85f74064458f2d..fa8caf54a2ee44 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -20,7 +20,7 @@ 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 reveal_type, reveal_locals from typing import no_type_check, no_type_check_decorator from typing import Type from typing import NamedTuple, TypedDict @@ -5290,13 +5290,16 @@ def bar(self): self.assertIn('baz', dir(Foo[int])) -class RevealTypeTests(BaseTestCase): +class RevealTests(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") + def test_reveal_locals(self): + self.assertIsNone(reveal_locals()) + class AllTests(BaseTestCase): """Tests for __all__.""" diff --git a/Lib/typing.py b/Lib/typing.py index 0cf9755022e9b8..f30b5908665aed 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -130,6 +130,7 @@ def _idfunc(_, x): 'overload', 'ParamSpecArgs', 'ParamSpecKwargs', + 'reveal_locals', 'reveal_type', 'runtime_checkable', 'Text', @@ -2696,3 +2697,23 @@ def reveal_type(obj: T, /) -> T: """ print(f"Runtime type is {type(obj).__name__!r}", file=sys.stderr) return obj + + +def reveal_locals() -> None: + """Reveal the inferred static types of all local variables. + + When a static type checker encounters a call to this function, + it emits a diagnostic with the types of all variables in the current + scope. For example:: + + def greet(user_id: int) -> None: + message = f"Hello user #{user_id}" + reveal_locals() # Revealed local types are: user_id: int, message: str + + Like :func:`reveal_type`, this function is useful for debugging how + the type checker understands a piece of code. + + At runtime, this function does nothing. + + """ + pass diff --git a/Misc/NEWS.d/next/Library/2022-01-23-13-21-14.bpo-46479.a-qhRL.rst b/Misc/NEWS.d/next/Library/2022-01-23-13-21-14.bpo-46479.a-qhRL.rst new file mode 100644 index 00000000000000..713fbbf9ddc633 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-23-13-21-14.bpo-46479.a-qhRL.rst @@ -0,0 +1 @@ +Add :func:`typing.reveal_locals`. Patch by Jelle Zijlstra.