From 40bcd663a41bdc203823504b2e3539bb98e8c1c4 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 14 Oct 2025 10:46:01 +0200 Subject: [PATCH 1/3] python-stdlib: Add modules to support typing. typing, typing_extensions and collections.abc Signed-off-by: Jos Verlinde --- .../collections-abc/collections/abc.py | 7 ++ python-stdlib/collections-abc/manifest.py | 5 + python-stdlib/typing/manifest.py | 8 ++ python-stdlib/typing/typing.py | 97 +++++++++++++++++++ python-stdlib/typing_extensions/manifest.py | 10 ++ .../typing_extensions/typing_extensions.py | 5 + 6 files changed, 132 insertions(+) create mode 100644 python-stdlib/collections-abc/collections/abc.py create mode 100644 python-stdlib/collections-abc/manifest.py create mode 100644 python-stdlib/typing/manifest.py create mode 100644 python-stdlib/typing/typing.py create mode 100644 python-stdlib/typing_extensions/manifest.py create mode 100644 python-stdlib/typing_extensions/typing_extensions.py diff --git a/python-stdlib/collections-abc/collections/abc.py b/python-stdlib/collections-abc/collections/abc.py new file mode 100644 index 000000000..ef626141a --- /dev/null +++ b/python-stdlib/collections-abc/collections/abc.py @@ -0,0 +1,7 @@ +# collections.abc +# minimal support for runtime typing +# type: ignore +try: + from typing import __Ignore as ABC, __getattr__ as __getattr__ +except: + pass \ No newline at end of file diff --git a/python-stdlib/collections-abc/manifest.py b/python-stdlib/collections-abc/manifest.py new file mode 100644 index 000000000..24376bb5e --- /dev/null +++ b/python-stdlib/collections-abc/manifest.py @@ -0,0 +1,5 @@ +metadata(version="1.26.1") + +# require("collections") +require("typing") +package("collections") diff --git a/python-stdlib/typing/manifest.py b/python-stdlib/typing/manifest.py new file mode 100644 index 000000000..e7866b38b --- /dev/null +++ b/python-stdlib/typing/manifest.py @@ -0,0 +1,8 @@ +# type: ignore + +metadata(version="1.26.1", description="Typing module for MicroPython.") + +# default to opt_level 3 for minimal firmware size +options.defaults(opt_level=3) + +module("typing.py", opt=options.opt_level) diff --git a/python-stdlib/typing/typing.py b/python-stdlib/typing/typing.py new file mode 100644 index 000000000..23cfc04fc --- /dev/null +++ b/python-stdlib/typing/typing.py @@ -0,0 +1,97 @@ +""" +This module provides runtime support for type hints. +based on : +- https://github.com/micropython/micropython-lib/pull/584 +- https://github.com/Josverl/micropython-stubs/tree/main/mip +- https://github.com/Josverl/rt_typing + +""" + +# ------------------------------------- +# code reduction by Ignoring type hints +# ------------------------------------- +class __Ignore: + """A class to ignore type hints in code.""" + + def __call__(*args, **kwargs): + # May need some guardrails here + pass + + def __getitem__(self, arg): + # May need some guardrails here + return __ignore + + def __getattr__(self, attr): + if attr in self.__dict__: + return self.__dict__[attr] + return __ignore + + +__ignore = __Ignore() +# ----------------- +# typing essentials +# ----------------- +TYPE_CHECKING = False + +def final(arg): # ( 6 + bytes) + # decorator to indicate that a method should not be overridden + # https://docs.python.org/3/library/typing.html#typing.final + return arg + + +# def overload(arg): # ( 27 bytes) +# # ignore functions signatures with @overload decorator +# return None +overload = __ignore # saves bytes, and is semantically similar + +def NewType(_, arg): # (21 bytes) + # https://docs.python.org/3/library/typing.html#newtype + # MicroPython: just use the original type. + return arg + +# --------------- +# useful methods +# --------------- + +# https://docs.python.org/3/library/typing.html#typing.cast +# def cast(type, arg): # ( 23 bytes) +# return arg +cast = NewType # saves bytes, and is semantically similar + +# https://docs.python.org/3/library/typing.html#typing.no_type_check +# def no_type_check(arg): # ( 26 bytes) +# # decorator to disable type checking on a function or method +# return arg +no_type_check = final # saves bytes, and is semantically similar + +# ------------------- +# less useful methods +# ------------------- + +# def reveal_type(x): # ( 38 bytes) +# # # https://docs.python.org/3/library/typing.html#typing.reveal_type +# return x +# or for smaller size: +reveal_type = final # saves bytes, and is semantically similar + + +# def get_origin(type): # ( 23 bytes) +# # https://docs.python.org/3/library/typing.html#typing.get_origin +# # Return None for all unsupported objects. +# return None + + +# def get_args(arg): # ( 22 bytes) +# # https://docs.python.org/3/library/typing.html#typing.get_args +# # Python 3.8+ only +# return () + + +# ref: https://github.com/micropython/micropython-lib/pull/584#issuecomment-2317690854 + +def __getattr__(x): + return __ignore + +# snarky way to alias typing_extensions to typing ( saving 59 bytes) +import sys +sys.modules["typing_extensions"] = sys.modules["typing"] diff --git a/python-stdlib/typing_extensions/manifest.py b/python-stdlib/typing_extensions/manifest.py new file mode 100644 index 000000000..addbec166 --- /dev/null +++ b/python-stdlib/typing_extensions/manifest.py @@ -0,0 +1,10 @@ +metadata(version="1.26.1") + + +# default to opt_level 3 for minimal firmware size +options.defaults(opt_level=3) + +module("typing_extensions.py", opt=options.opt_level) + +require("typing") +package("typing_extensions") diff --git a/python-stdlib/typing_extensions/typing_extensions.py b/python-stdlib/typing_extensions/typing_extensions.py new file mode 100644 index 000000000..3f800bfaf --- /dev/null +++ b/python-stdlib/typing_extensions/typing_extensions.py @@ -0,0 +1,5 @@ +# typing_extensions.py +# type: ignore + +from typing import * +from typing import __getattr__ \ No newline at end of file From 3e07ccf3860f1973c265d1a916d57ff302f78110 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 14 Oct 2025 10:47:15 +0200 Subject: [PATCH 2/3] python-stdlib: Update modules to allow for new typing modules. `__future__`, `abc`, `collection` Signed-off-by: Jos Verlinde --- python-stdlib/__future__/manifest.py | 6 ++++-- python-stdlib/abc/abc.py | 12 ++++++++++-- python-stdlib/abc/manifest.py | 6 ++++-- python-stdlib/collections/collections/__init__.py | 8 ++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/python-stdlib/__future__/manifest.py b/python-stdlib/__future__/manifest.py index e06f3268d..017d10e9e 100644 --- a/python-stdlib/__future__/manifest.py +++ b/python-stdlib/__future__/manifest.py @@ -1,3 +1,5 @@ -metadata(version="0.1.0") +metadata(version="1.26.1") -module("__future__.py") +options.defaults(opt_level=3) + +module("__future__.py", opt=options.opt_level) diff --git a/python-stdlib/abc/abc.py b/python-stdlib/abc/abc.py index c2c707f62..670e4e5ac 100644 --- a/python-stdlib/abc/abc.py +++ b/python-stdlib/abc/abc.py @@ -1,6 +1,14 @@ +# type: ignore class ABC: pass -def abstractmethod(f): - return f +def abstractmethod(arg): + return arg + +try: + # add functionality if typing module is available + from typing import __getattr__ as __getattr__ + +except: # naked except saves 4 bytes + pass diff --git a/python-stdlib/abc/manifest.py b/python-stdlib/abc/manifest.py index c76312960..277dc3ef9 100644 --- a/python-stdlib/abc/manifest.py +++ b/python-stdlib/abc/manifest.py @@ -1,3 +1,5 @@ -metadata(version="0.1.0") +metadata(version="0.2.0") -module("abc.py") +options.defaults(opt_level=3) + +module("abc.py", opt=options.opt_level) diff --git a/python-stdlib/collections/collections/__init__.py b/python-stdlib/collections/collections/__init__.py index 36dfc1c41..da0df43bc 100644 --- a/python-stdlib/collections/collections/__init__.py +++ b/python-stdlib/collections/collections/__init__.py @@ -6,6 +6,14 @@ from .defaultdict import defaultdict except ImportError: pass +# optional collections.abc typing dummy module +try: + # cannot use relative import here + import collections.abc as abc + import sys + sys.modules['collections.abc'] = abc +except ImportError: + pass class MutableMapping: From 6868a06b03c5ca787809b7bc25e361705877530d Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 14 Oct 2025 10:47:28 +0200 Subject: [PATCH 3/3] micropython/bundle-typing: Add bundle for typing modules. This also defaults the mpy-cross opt level to 3, to reduce firmware size. Signed-off-by: Jos Verlinde --- micropython/bundles/bundle-typing/manifest.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 micropython/bundles/bundle-typing/manifest.py diff --git a/micropython/bundles/bundle-typing/manifest.py b/micropython/bundles/bundle-typing/manifest.py new file mode 100644 index 000000000..5b1c854ca --- /dev/null +++ b/micropython/bundles/bundle-typing/manifest.py @@ -0,0 +1,18 @@ +# type: ignore[all] + +metadata( + version="1.26.1", + description="Limited runtime typing support for MicroPython.", +) + +options.defaults(opt_level=3, extensions=False) + +# Primary typing related modules +require("__future__", opt_level=options.opt_level) +require("typing", opt_level=options.opt_level) +require("abc", opt_level=options.opt_level) + +# # Optional typing modules +if options.extensions: + require("typing_extensions", opt_level=options.opt_level) + require("collections-abc", opt_level=options.opt_level)