summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2022-03-17 03:02:26 (GMT)
committerGitHub <noreply@github.com>2022-03-17 03:02:26 (GMT)
commit96568e995d840c66edb25b6b9d85e4dcccf5a936 (patch)
tree907a903c2807fb7437b4e5a5779d034609320a9f
parent7c353b7594545fb9403b3123a17ad06cadc2f73d (diff)
downloadcpython-96568e995d840c66edb25b6b9d85e4dcccf5a936.zip
cpython-96568e995d840c66edb25b6b9d85e4dcccf5a936.tar.gz
cpython-96568e995d840c66edb25b6b9d85e4dcccf5a936.tar.bz2
bpo-46480: add typing.assert_type (GH-30843)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: David Foster <david@dafoster.net>
-rw-r--r--Doc/library/typing.rst25
-rw-r--r--Lib/test/test_typing.py18
-rw-r--r--Lib/typing.py17
-rw-r--r--Misc/NEWS.d/next/Library/2022-01-23-16-33-07.bpo-46480.E4jHlh.rst1
4 files changed, 60 insertions, 1 deletions
diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst
index c7c2cd6..57979cb 100644
--- a/Doc/library/typing.rst
+++ b/Doc/library/typing.rst
@@ -2148,6 +2148,31 @@ Functions and decorators
runtime we intentionally don't check anything (we want this
to be as fast as possible).
+.. function:: assert_type(val, typ, /)
+
+ Assert (to the type checker) that *val* has an inferred type of *typ*.
+
+ When the type checker encounters a call to ``assert_type()``, it
+ emits an error if the value is not of the specified type::
+
+ def greet(name: str) -> None:
+ assert_type(name, str) # OK, inferred type of `name` is `str`
+ assert_type(name, int) # type checker error
+
+ At runtime this returns the first argument unchanged with no side effects.
+
+ This function is useful for ensuring the type checker's understanding of a
+ script is in line with the developer's intentions::
+
+ def complex_function(arg: object):
+ # Do some complex type-narrowing logic,
+ # after which we hope the inferred type will be `int`
+ ...
+ # Test whether the type checker correctly understands our function
+ assert_type(arg, int)
+
+ .. versionadded:: 3.11
+
.. function:: assert_never(arg, /)
Assert to the type checker that a line of code is unreachable.
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index b212b52..e88f732 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -16,7 +16,7 @@ from typing import Union, Optional, Literal
from typing import Tuple, List, Dict, MutableMapping
from typing import Callable
from typing import Generic, ClassVar, Final, final, Protocol
-from typing import cast, runtime_checkable
+from typing import assert_type, cast, runtime_checkable
from typing import get_type_hints
from typing import get_origin, get_args
from typing import is_typeddict
@@ -3302,6 +3302,22 @@ class CastTests(BaseTestCase):
cast('hello', 42)
+class AssertTypeTests(BaseTestCase):
+
+ def test_basics(self):
+ arg = 42
+ self.assertIs(assert_type(arg, int), arg)
+ self.assertIs(assert_type(arg, str | float), arg)
+ self.assertIs(assert_type(arg, AnyStr), arg)
+ self.assertIs(assert_type(arg, None), arg)
+
+ def test_errors(self):
+ # Bogus calls are not expected to fail.
+ arg = 42
+ self.assertIs(assert_type(arg, 42), arg)
+ self.assertIs(assert_type(arg, 'hello'), arg)
+
+
# We need this to make sure that `@no_type_check` respects `__module__` attr:
from test import ann_module8
diff --git a/Lib/typing.py b/Lib/typing.py
index dd68e71..6930f5d 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -118,6 +118,7 @@ __all__ = [
# One-off things.
'AnyStr',
+ 'assert_type',
'assert_never',
'cast',
'final',
@@ -2093,6 +2094,22 @@ def cast(typ, val):
return val
+def assert_type(val, typ, /):
+ """Assert (to the type checker) that the value is of the given type.
+
+ When the type checker encounters a call to assert_type(), it
+ emits an error if the value is not of the specified type::
+
+ def greet(name: str) -> None:
+ assert_type(name, str) # ok
+ assert_type(name, int) # type checker error
+
+ At runtime this returns the first argument unchanged and otherwise
+ does nothing.
+ """
+ return val
+
+
_allowed_types = (types.FunctionType, types.BuiltinFunctionType,
types.MethodType, types.ModuleType,
WrapperDescriptorType, MethodWrapperType, MethodDescriptorType)
diff --git a/Misc/NEWS.d/next/Library/2022-01-23-16-33-07.bpo-46480.E4jHlh.rst b/Misc/NEWS.d/next/Library/2022-01-23-16-33-07.bpo-46480.E4jHlh.rst
new file mode 100644
index 0000000..fd18a81
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-01-23-16-33-07.bpo-46480.E4jHlh.rst
@@ -0,0 +1 @@
+Add :func:`typing.assert_type`. Patch by Jelle Zijlstra.