Skip to content
Open
Show file tree
Hide file tree
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
test/cpydiff: Add tests to document typing differences.
These are constructs used in static typing that are different between
MicroPython and CPython, and should be documented as such.

Signed-off-by: Jos Verlinde <[email protected]>
  • Loading branch information
Josverl authored and stinos committed Oct 9, 2025
commit e772ee1877d54707c3ffc2be55e4d67ddcefc684
12 changes: 12 additions & 0 deletions tests/cpydiff/core_class_metaclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
categories: Core,Classes
description: Defining a class with a metaclass is not possible.
cause: Unknown
workaround: Unknown
"""

from abc import ABCMeta


class MyABC(metaclass=ABCMeta):
pass
32 changes: 32 additions & 0 deletions tests/cpydiff/modules_typing_generics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
categories: Modules,typing
description: User Defined Generics
cause: Micropython does not implement User Defined Generics
workaround: None
"""

from typing import Dict, Generic, TypeVar

T = TypeVar("T")


class Registry(Generic[T]):
def __init__(self) -> None:
self._store: Dict[str, T] = {}

def set_item(self, k: str, v: T) -> None:
self._store[k] = v

def get_item(self, k: str) -> T:
return self._store[k]


family_name_reg = Registry[str]()
family_age_reg = Registry[int]()

family_name_reg.set_item("husband", "steve")
family_name_reg.set_item("dad", "john")

family_age_reg.set_item("steve", 30)

print(repr(family_name_reg.__dict__))
12 changes: 12 additions & 0 deletions tests/cpydiff/modules_typing_getargs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
categories: Modules,typing
description: ``get_args()`` function not fully implemented.
cause: Micropython does not implement all typing features
workaround: None
"""

from typing import get_args

# partial implementation of get_args
x = get_args(int)
assert x == (), f"expected () but got {x}"
13 changes: 13 additions & 0 deletions tests/cpydiff/modules_typing_getorigin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""
categories: Modules,typing
description: ``get_origin()`` function not fully implemented.
cause: Micropython does not implement all typing features from Python 3.8+
workaround: None
"""
# https://docs.python.org/3/library/typing.html#typing.get_origin

from typing import Dict, get_origin

assert get_origin(Dict[str, int]) is dict, "origin Dict cannot be detected"

assert get_origin(str) is None, "origin str should be None"
24 changes: 24 additions & 0 deletions tests/cpydiff/modules_typing_reveal_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
categories: Modules,typing
description: ``reveal_type()`` is not implemented.
cause: Micropython does not implement all typing features
workaround: None
"""

from typing import Self, reveal_type


class Foo:
def return_self(self) -> Self:
...


class SubclassOfFoo(Foo):
pass


foo = Foo()
sub = SubclassOfFoo()

reveal_type(foo)
reveal_type(sub)
17 changes: 17 additions & 0 deletions tests/cpydiff/modules_typing_runtime_checkable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
categories: Modules,typing
description: ``runtime_checkable()`` is not implemented.
cause: Micropython does not implement all typing features from Python 3.8+
workaround: None
"""

from typing import runtime_checkable, Protocol


@runtime_checkable
class SwallowLaden(Protocol):
def __iter__(self):
...


assert isinstance([1, 2, 3], SwallowLaden)
10 changes: 4 additions & 6 deletions tests/cpydiff/modules_typing_typeddict.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
"""
categories: Modules,typing
description: ``TypedDict`` does not behave according to spec.
description: ``TypedDict`` class not allowed for instance or class checks.
cause: Micropython does not implement all typing features
workaround: None
"""
# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html

from typing import TypedDict
from typing import TypeVar, TypedDict


class Movie(TypedDict):
title: str
name: str
year: int


movie = Movie(title="Life of Brian", year=1979)
print("Type is: ", type(movie))
movie: Movie = {"name": "Blade Runner", "year": 1982}

try:
if isinstance(movie, Movie): # type: ignore
Expand Down
11 changes: 5 additions & 6 deletions tests/extmod/typing_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def hash_b(item: Any) -> int:
print(hash_b(42))
print(hash_b("foo"))

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

from typing import AnyStr

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


print("Testing : typing.LiteralString")
Expand Down Expand Up @@ -201,11 +201,11 @@ def bar(x):
print(bar(42))


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

# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#required-and-notrequired

from typing import Annotated, NotRequired, Required, TypedDict
from typing import NotRequired, Required, TypedDict


class Movie(TypedDict):
Expand All @@ -215,7 +215,6 @@ class Movie(TypedDict):


m = Movie(title="Life of Brian", year=1979)
print(type(m)) # <class 'dict'>


print("Testing : typing.TypeVar")
Expand Down
12 changes: 0 additions & 12 deletions tests/extmod/typing_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@

MyAlias = str
Vector: typing.List[float]
Nested = Iterable[Tuple[MyAlias, ...]]
UserId = NewType("UserId", int)
T = TypeVar("T", int, float, complex)

Expand All @@ -66,14 +65,3 @@

def func_with_hints(c: int, b: MyAlias, a: Union[int, None], lst: List[float] = [0.0]) -> Any:
pass


class ClassWithHints(Generic[T]):
a: int = 0

def foo(self, other: int) -> None:
self.typed_thing: List[T] = []


class Bar(ClassWithHints[Any]):
pass
Loading