-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
extmod: Implement a minimal typing module. #15911
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #15911 +/- ##
=======================================
Coverage 98.57% 98.57%
=======================================
Files 164 165 +1
Lines 21336 21344 +8
=======================================
+ Hits 21031 21039 +8
Misses 305 305 ☔ View full report in Codecov by Sentry. |
Code size report:
|
e63ca72
to
80a1dfa
Compare
Test for failing Codecov added. |
80a1dfa
to
320c464
Compare
We added |
Agree that currently the most important use case for I see a lot of downloads of the type stubs, and it's growing steadily. Thr use will only increase when the stubs are integrated with the documentation. So I would prefer this to be enabled on the major ports, and disabled on the memory constrained ports. For |
23816a9
to
090a41a
Compare
On second thought I don't think
Essentially, yes. It requires that collections/abc.py is added in micropython-lib and contains just Likewise |
Hi @stinos, I build and tested a RPI_PICO image with // enable typing module in C
#define MICROPY_PY_TYPING (1)
#define MICROPY_PY_TYPING_EXTRA_MODULES (1) I can the same notebook with tests that I used to validate the a short breakdown:
of the failing runtime checks I think that
for complete test results see : verify_type_checking.ipynb for the tests that have different results between CPython , the .mpy amd the .c implementation I have added the results in # %%micropython --reset
from typing import TYPE_CHECKING
from abc import ABC, abstractmethod
from math import pi
class Shape(ABC):
@abstractmethod
def get_area(self) -> float:
pass
@abstractmethod
def get_perimeter(self) -> float:
pass
class Circle(Shape):
def __init__(self, radius) -> None:
self.radius = radius
def get_area(self) -> float:
return pi * self.radius**2
def get_perimeter(self) -> float:
return 2 * pi * self.radius
class Square(Shape):
def __init__(self, side) -> None:
self.side = side
def get_area(self) -> float:
return self.side**2
def get_perimeter(self) -> float:
return 4 * self.side
c1 = Circle(5)
s1 = Square(5)
for shape in [c1, s1]:
a = shape.get_area()
p = shape.get_perimeter()
print(a, p)
print(f"{type(a)=}")
print(f"{type(p)=}")
assert isinstance(a, (float, int)), "Area should be a float"
assert isinstance(p, (float, int)), "Perimeter should be a float"
# CPython
# ----------------------
# 78.53981633974483 31.41592653589793
# type(a)=<class 'float'>
# type(p)=<class 'float'>
# 25 20
# type(a)=<class 'int'>
# type(p)=<class 'int'>
# MicroPython typing.py
# ----------------------
# 78.53982 31.41593
# type(a)=<class 'float'>
# type(p)=<class 'float'>
# 25 20
# type(a)=<class 'int'>
# type(p)=<class 'int'>
# Micropython - modtyping.c
# ----------------------
# <any_call> <any_call>
# type(a)=<class 'any_call'>
# type(p)=<class 'any_call'>
# WARNING |Traceback (most recent call last):
# WARNING | File "<stdin>", line 52, in <module>
# ERROR |AssertionError: Area should be a float
# |
Great, thanks for testing! Do you mind checking the code size the .c implementation takes (pico isn't included in the ci build code size report)? Thing is still: the closer it gets to just freezing the .py implementations (and for whatever reason on the unix build it seems already way over it), the less sense it makes to follow this path.
I think that repository is private since I get a 404 trying to access it.
Well, it's a bit more than just 'isinstance does not work', this is not good.. I didn't even test that because I had no idea the ability to derive from a native type could even be broken and assumed it would first look in the derived class for attributes and only then in the base class. edit implementation details: core reason is that
The implementation is likely not active; either you have to make sure there's no |
Firmware size.
|
Signed-off-by: stijn <stijn@ignitron.net>
090a41a
to
a32e6d6
Compare
Yes that works, but you'd have to repeat that for every single type, whereas
Essentially what you're posted, except that 'No Typing' and 'C typing' have the same size so they're both 'C typing' probably? Anyway while fixing the implementation (code sample you posted works now) I found a blocker, see your So that means our typing implementation, whatever it is, must have all possible typing-related decorators implemented explicitly (and they definitely do not currently) otherwise the runtime behavior of code using an unlisted decorator is incorrect because the current implementations which make the module's No-one probably really thought this through so far, but this is a rather serious issue. |
No
yeah, noticed that, may have fumbled the definitions, here are numbers for Variants I created of the PIMORONI_PICOLIPO-FLASH
The .c implementation , even if it is for part of the functionality, and currently does not pass all tests, is significantly lower. .mpy Package size breakdown :
I think the risk is acceptable, as with the implementation of the typing @decorators, we are actually 'unbreaking' code, rather than breaking it. The way I have been using |
Thanks for the elaborate info.
Right, I changed that already in the most recent version though.
Yeah, I kind of expected this.
I have to say I'm not convinced, at least not for our production code :)
Ok but if that is a hard requirement, the C implementation is a no-go?
I made a start with implementing it in C the other way around, so no |
The general rule in MicroPython is that if something can be reasonable implemented in Python, then it should. that is why there are several As static and runtime typing in Python is still rapidly developing, my worry is that a size optimized C-implementation will be harder to maintain and extend, than a Python based solution. Also the mip installable approach adds a degree of freedom, as it can be installed on (almost) any port/board/family of micropython. perhaps we need to rank/ weight what is, or we find, important, in order to make a good-enough choice wrt to the implementation:
and then score the different solutions. |
Summary
The compiler already ignores type hints but to improve runtime support a minimal
typing
(andabc
andtyping_extensions
) module is implemented in C because code-size wise that is the cheapest to do. Also see micropython/micropython-lib#584 for background.Note @Josverl asked to support
__future__
andcollections.abc
as well but I did not (yet) do that because:__future__
is easy to add as an alias but the result would be that anything you ask is possible,i.e.if __future__.just_inventing_something:
would pass. Unclear if we want that.collections.abc
correctly in the presence of micropython-lib'scollections
moduleTesting
A basic test is added.
Trade-offs and Alternatives
Nested = Iterable[Tuple[MyAlias, ...]]
) work because the compiler cannot distinguish them from normal Python code.Note I really have no idea how many people would actually use this so maybe makes more sense to disable this by default in all but the PC ports.
Also note that
dir(typing)
or REPL completion ontyping.
will list all qstrs :)