Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
tests/extmod/typing_runtime: Add tests and improve formatting.
Signed-off-by: Jos Verlinde <[email protected]>
  • Loading branch information
Josverl authored and stinos committed Oct 13, 2025
commit 5c5bc592a2db1e2cd73c8222fd01b6282877b5f2
168 changes: 138 additions & 30 deletions tests/extmod/typing_runtime.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
print("Testing runtime aspects of typing module")


try:
from typing import TYPE_CHECKING
except ImportError:
print("SKIP")
raise SystemExit

print("# Python 3.5+")
print("### Miscellaneous")


print("Testing : typing.TYPE_CHECKING - Python 3.5.2")
print("typing.TYPE_CHECKING")
if TYPE_CHECKING:
from typing_extensions import TypeGuard

print("Testing : typing parameter annotations")
from typing import Any, Dict, List
print("typing parameter annotations")
from typing import Any, Dict, List, Union


def add_numbers(a: int, b: int) -> int:
Expand All @@ -38,7 +42,7 @@ def process_data(data: Dict[str, Any]) -> None:
process_data({"key": "value", "number": 42})


print("Testing : typing.Self - Python 3.11")
print("typing.Self - Python 3.11")
from typing import Callable, Self


Expand All @@ -55,7 +59,7 @@ def cb(x):
base.register(cb)


print("Testing : typing@no_type_check decorator")
print("typing@no_type_check decorator")
from typing import no_type_check


Expand All @@ -66,7 +70,7 @@ def quad(r0):

print(quad(1))

print("Testing : typing.Protocol")
print("typing.Protocol")

from typing import Protocol

Expand All @@ -93,7 +97,7 @@ def add(adder: Adder) -> None:
add(IntAdder())
add(FloatAdder())

print("Testing : typing.NewType")
print("typing.NewType")

from typing import NewType

Expand All @@ -105,7 +109,7 @@ def add(adder: Adder) -> None:
assert isinstance(some_id, int), "NewType should be instance of the original type"


print("Testing : typing.Any")
print("typing.Any")
from typing import Any

a: Any = None
Expand Down Expand Up @@ -138,7 +142,7 @@ def hash_b(item: Any) -> int:
print(hash_b(42))
print(hash_b("foo"))

print("Testing : typing.AnyStr")
print("typing.AnyStr")

from typing import AnyStr

Expand All @@ -150,12 +154,12 @@ def concat(a: AnyStr, b: AnyStr) -> AnyStr:
concat("foo", "bar") # OK, output has type 'str'
concat(b"foo", b"bar") # OK, output has type 'bytes'
try:
concat("foo", b"bar") # Error, cannot mix str and bytes
concat("foo", b"bar") # Error, cannot mix str and bytes # type: ignore
except TypeError:
print("TypeError is expected")


print("Testing : typing.LiteralString")
print("typing.LiteralString")
from typing import LiteralString


Expand All @@ -179,7 +183,7 @@ def caller(arbitrary_string: str, literal_string: LiteralString) -> None:

caller(some_str, literal_str)

print("Testing : typing.overload")
print("typing.overload")

from typing import overload

Expand All @@ -201,9 +205,8 @@ def bar(x):
print(bar(42))


print("Testing : typing.Required, NotRequired in TypedDict")

# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#required-and-notrequired
print("typing.Required, NotRequired in TypedDict")
# https://typing.readthedocs.io/en/latest/spec/typeddict.html#required-and-notrequired

from typing import NotRequired, Required, TypedDict

Expand All @@ -217,7 +220,7 @@ class Movie(TypedDict):
m = Movie(title="Life of Brian", year=1979)


print("Testing : typing.TypeVar")
print("typing.TypeVar")

from typing import List, TypeVar

Expand All @@ -235,7 +238,7 @@ def first(container: List[T]) -> T:
print(first(list_two))


print("Testing : typing.Generator")
print("typing.Generator")

from typing import Generator

Expand All @@ -250,7 +253,7 @@ def echo(a: float) -> Generator[int, float, str]:
print(v)


print("Testing : typing.NoReturn")
print("typing.NoReturn")

from typing import NoReturn

Expand All @@ -261,7 +264,7 @@ def stop() -> NoReturn:

#

print("Testing : typing.Final")
print("typing.Final")

from typing import Final

Expand All @@ -271,7 +274,7 @@ def stop() -> NoReturn:
print(CONST)


print("Testing : typing.final")
print("typing.final")

from typing import final

Expand Down Expand Up @@ -299,21 +302,25 @@ class Other(Leaf): # type: ignore # Error reported by type checker
other = Other()


print("Testing : typing.TypeVarTuple and typing.Unpack")
print("typing.TypeVarTuple and typing.Unpack")

from typing import TypeVarTuple, Unpack

Ts = TypeVarTuple("Ts")
tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible
tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible # type: ignore


print("Testing : typing.Callable, ParamSpec")
print("typing.Callable, ParamSpec")

# ParamSpec, 3.11 notation
# https://docs.python.org/3/library/typing.html#typing.ParamSpec

# FIXME: from collections.abc import Callable
from typing import Callable
try:
from collections.abc import Callable
except ImportError:
print("- [ ] FIXME: from collections.abc import Callable")

from typing import Callable # Workaround for test
from typing import TypeVar, ParamSpec

T = TypeVar("T")
Expand Down Expand Up @@ -341,8 +348,109 @@ def add_two(x: float, y: float) -> float:
assert x == 3, "add_two(1, 2) == 3"


print("Testing : typing.")
print("Testing : typing.")
print("Testing : typing.")
print("Testing : typing.")
print("Testing : typing.")
print("typing.get_origin()")
# https://docs.python.org/3/library/typing.html#typing.get_origin

from typing import get_origin

# FIXME: - cpy_diff - get_origin() unsupported, or always returns None
if not get_origin(str) is None:
print("- [ ] FIXME: cpy_diff - get_origin(str) should be None")
# assert get_origin(Dict[str, int]) is dict
# assert get_origin(Union[int, str]) is Union

print("typing.get_args()")
# https://docs.python.org/3/library/typing.html#typing.get_args
from typing import get_args, Dict, Union

# FIXME: - cpy_diff - get_args() unsupported, or always returns ()
if not get_args(int) == ():
print("- [ ] FIXME: cpy_diff - get_args(int) should be ()")

# assert get_args(Dict[int, str]) == (int, str), "get_args(Dict[int, str]) should be (int, str)"
# assert get_args(Union[int, str]) == (int, str), "get_args(Union[int, str]) should be (int, str)"


print("Subscriptables")

from typing import (
AbstractSet,
AsyncContextManager,
AsyncGenerator,
AsyncIterable,
AsyncIterator,
Awaitable,
)
from typing import (
Callable,
ChainMap,
Collection,
Container,
ContextManager,
Coroutine,
Counter,
DefaultDict,
)
from typing import (
Deque,
Dict,
FrozenSet,
Generator,
Generic,
Iterable,
Iterator,
List,
Literal,
Mapping,
)
from typing import (
MutableMapping,
MutableSequence,
MutableSet,
NamedTuple,
Optional,
OrderedDict,
Self,
)
from typing import Sequence, Set, Tuple, Type, Union


t_01: AbstractSet[Any]
t_02: AsyncContextManager[Any]
t_03: AsyncGenerator[Any]
t_04: AsyncIterable[Any]
t_05: AsyncIterator[Any]
t_06: Awaitable[Any]
t_07: Callable[[], Any]
t_08: ChainMap[Any, Any]
t_09: Collection[Any]
t_10: Container[Any]
t_11: ContextManager[Any]
t_12: Coroutine[Any, Any, Any]
t_13: Counter[Any]
t_14: DefaultDict[Any, Any]
t_15: Deque[Any]
t_16: Dict[Any, Any]
t_17: FrozenSet[Any]
t_18: Generator[Any]
# t_19: Generic[Any]
t_20: Iterable[Any]
t_21: Iterator[Any]
t_22: List[Any]
t_23: Literal[1, 2, 3, "a", b"b", True, None]
t_24: Mapping[Any, Any]
t_25: MutableMapping[Any, Any]
t_26: MutableSequence[Any]
t_27: MutableSet[Any]
t_28: NamedTuple
t_29: Optional[Any]
t_30: OrderedDict[Any, Any]
# t_31: Self[Any]
t_32: Sequence[Any]
t_33: Set[Any]
t_34: Tuple[Any]
t_35: Type[Any]
t_36: Union[Any, Any]


print("-----")