bpo-46414: Add typing.reveal_type (#30646)

Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
This commit is contained in:
Jelle Zijlstra 2022-02-01 18:48:55 -08:00 • committed by GitHub
parent b1288964e3
commit abcc3d75f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 1 deletions

View file

@ -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

View file

@ -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__."""

View file

@ -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

View file

@ -0,0 +1 @@
Add :func:`typing.reveal_type`. Patch by Jelle Zijlstra.